Observability Tracing¶
Trigger: HTTP | State: stateless | Guarantee: request-response | Difficulty: intermediate
Overview¶
This recipe documents end-to-end request tracing in examples/runtime-and-ops/observability_tracing/.
It shows how an HTTP-triggered Azure Function can preserve correlation metadata,
emit structured logs,
and return trace headers that line up with Application Insights and OpenTelemetry-style propagation.
The Integration Matrix for this recipe is intentionally narrow: logging only. Instead of introducing a separate telemetry SDK, the function relies on Azure Functions runtime telemetry plus structured application logs.
When to Use¶
- You need a simple HTTP recipe that preserves correlation across upstream and downstream calls.
- You want Application Insights-friendly request tracing without adding a large observability stack.
- You need structured logs that can be filtered by correlation ID or trace ID during incident response.
When NOT to Use¶
- You need full custom span creation for many downstream dependencies inside one request path.
- You need message-based tracing across queues, topics, or event streams rather than request-response HTTP.
- You need a vendor-specific telemetry SDK pattern instead of Azure Functions runtime-native logging.
Architecture¶
flowchart LR
client[Client / upstream API] --> af[Azure Function\nHTTP trigger]
af --> ai[Application Insights]
ai --> dash[Tracing dashboard\nsearch + transaction view]
Prerequisites¶
- Python 3.10+
- Azure Functions Core Tools v4
- Application Insights connection string for Azure-side telemetry validation
- Familiarity with HTTP headers such as
traceparentandx-correlation-id
Project Structure¶
examples/runtime-and-ops/observability_tracing/
├── function_app.py
├── host.json
├── local.settings.json.example
├── pyproject.toml
└── README.md
Implementation¶
The function accepts inbound correlation headers, reuses them when present, and generates safe defaults when they are missing. It then logs request metadata as structured fields and echoes the correlation context back in the response.
@app.route(route="trace-demo", methods=["GET", "POST"], auth_level=func.AuthLevel.ANONYMOUS)
@with_context
def trace_demo(req: func.HttpRequest) -> func.HttpResponse:
traceparent, trace_id, span_id, generated = _extract_or_create_traceparent(req)
correlation_id = _extract_or_create_correlation_id(req)
logger.info(
"Processed traced request.",
extra={
"correlation_id": correlation_id,
"trace_id": trace_id,
"span_id": span_id,
"generated_traceparent": generated,
},
)
return func.HttpResponse(
body=json.dumps({"correlation_id": correlation_id, "traceparent": traceparent}),
mimetype="application/json",
headers={"x-correlation-id": correlation_id, "traceparent": traceparent},
)
Key behavior:
traceparentis preserved if the caller already started a distributed trace.x-correlation-idis reused when available and generated otherwise.- Structured logs carry
correlation_id,trace_id,span_id, and request metadata. - Application Insights can correlate request telemetry with these logs.
- OpenTelemetry-compatible tools can stitch the same request path via W3C trace context.
Behavior¶
sequenceDiagram
participant Client
participant Function as Azure Function
participant AI as Application Insights
Client->>Function: HTTP request with traceparent + x-correlation-id
Function->>Function: Reuse or create correlation context
Function->>AI: Emit request telemetry and structured logs
Function-->>Client: 200 OK with propagated trace headers
AI-->>Client: Correlated request visible in dashboard views
Run Locally¶
Then call the endpoint with explicit correlation headers:
curl -i \
-H "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" \
-H "x-correlation-id: checkout-req-42" \
"http://localhost:7071/api/trace-demo"
Expected Output¶
[Information] Received traced HTTP request. correlation_id=checkout-req-42 trace_id=4bf92f3577b34da6a3ce929d0e0e4736
[Information] Emitted custom telemetry event. telemetry_type=custom_event event_name=observability_trace_demo
HTTP/1.1 200 OK
x-correlation-id: checkout-req-42
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
Production Considerations¶
- Sampling: verify Application Insights sampling so traces remain useful during peak load.
- Privacy: avoid logging request bodies or sensitive headers alongside correlation fields.
- Consistency: standardize one correlation header name across callers and downstream services.
- Downstream calls: forward
traceparent,tracestate, and correlation headers when calling other APIs. - Dashboards: build saved queries around
operation_Id,trace_id, andcorrelation_id.