fix(tracing): instrument FastAPI ASGI layer for inbound traceparent propagation#4972
fix(tracing): instrument FastAPI ASGI layer for inbound traceparent propagation#4972STHITAPRAJNAS wants to merge 2 commits intogoogle:mainfrom
Conversation
804ba13 to
0804639
Compare
|
Hi @STHITAPRAJNAS , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Your PR has been received by the team and is currently under review. We will provide feedback as soon as we have an update to share. |
|
Hi @ankursharmas , can you please review this. |
e84b2e6 to
8df3dba
Compare
|
Hi @ankursharmas — gentle ping! This PR has been ready for review since Mar 31 with all checks passing. Would appreciate your feedback when you get a chance. Thanks! |
…ropagation Fixes google#4767. When get_fast_api_app() is used in production behind an OTel-instrumented caller (e.g. a Next.js service using @opentelemetry/sdk-node), every inbound request carried a W3C traceparent header that ADK silently discarded. The TracerProvider and W3C propagator were already wired up correctly by _setup_telemetry(), but without an ASGI-level hook to extract the header, each request spawned a new trace root instead of continuing the caller's trace. The fix calls FastAPIInstrumentor.instrument_app(app) immediately after the FastAPI instance is created, but only when an OTel export pipeline is actually active (OTLP env vars or otel_to_cloud=True). The instrumentation is applied before the CORS and origin-check middleware are registered so that Starlette's reverse-registration order leaves the security wrappers outermost in the stack. The call is best-effort: if opentelemetry-instrumentation-fastapi is absent a debug-level message is emitted and the server starts normally. The package is added to the otel-gcp extras so users who install google-adk[otel-gcp] get end-to-end distributed tracing out of the box without any manual post-instrumentation step. opentelemetry-instrumentation-fastapi is also added to the test extras so the new unit tests can import it directly. google#4767
8df3dba to
7c6cb6b
Compare
|
Hi @ankursharmas — circling back on this one. The use case is propagating inbound |
Fixes #4767.
Root cause
get_fast_api_app()calls_setup_telemetry()which correctly configures aTracerProviderand registers the W3CTraceContextTextMapPropagator. However, theFastAPIapp returned to callers never had the OTel ASGI middleware applied to it. Because thetraceparentheader is only extracted at the ASGI boundary, every inbound HTTP request started a new trace root instead of continuing the distributed trace initiated by the upstream caller.The existing workaround —
FastAPIInstrumentor().instrument_app(app)applied manually afterget_fast_api_app()returns — confirms the plumbing is otherwise correct.What this PR does
After the
FastAPIinstance is created insideAdkWebServer.get_fast_api_app(), callFastAPIInstrumentor.instrument_app(app)when an OTel export pipeline is active (OTEL_EXPORTER_OTLP_*env vars orotel_to_cloud=True):Key design decisions:
ImportErroris caught and logged atDEBUGlevel; the server continues normally without the instrumentation.CORSMiddlewareand_OriginCheckMiddlewareso that Starlette's reverse-registration order leaves the security wrappers outermost, and the OTel middleware extracts headers before the route handler runs.Dependency changes
opentelemetry-instrumentation-fastapiis added to:otel-gcpextras — users who installgoogle-adk[otel-gcp]now get automatic end-to-end tracing without any manual post-instrumentation step.testextras — required by the new unit tests.Tests
Four new tests in
tests/unittests/cli/test_fast_api.py:test_fastapi_instrumented_when_otlp_env_var_setinstrument_appcalled when an OTLP env var is presenttest_fastapi_instrumented_when_otel_to_cloud_enabledinstrument_appcalled whenotel_to_cloud=Truetest_fastapi_not_instrumented_without_otel_configinstrument_appNOT called when OTel is unconfiguredtest_missing_fastapi_instrumentor_does_not_prevent_startup/healthresponds 200 even if the package is absent