Skip to content

fix(fastapi): support instrumenting middleware-wrapped applications#4729

Open
kshitizj03 wants to merge 3 commits into
open-telemetry:mainfrom
kshitizj03:fix/4031-fastapi-middleware-wrapped-app
Open

fix(fastapi): support instrumenting middleware-wrapped applications#4729
kshitizj03 wants to merge 3 commits into
open-telemetry:mainfrom
kshitizj03:fix/4031-fastapi-middleware-wrapped-app

Conversation

@kshitizj03

Copy link
Copy Markdown
Contributor

Description

FastAPIInstrumentor.instrument_app/uninstrument_app assumed they were handed a fastapi.FastAPI instance and raised AttributeError: 'CORSMiddleware' object has no attribute 'build_middleware_stack' when given an application wrapped in ASGI middleware, e.g. CORSMiddleware(app=fastapi_app).

This adds a _unwrap_middleware helper that follows the conventional .app attribute chain down to the underlying application, and skips gracefully with a warning when no app is found. The public app parameter annotation is widened to ASGIApp to reflect that wrapped apps are now accepted.

Note: the unwrap stop-condition and guards check Starlette rather than fastapi.FastAPI. fastapi.FastAPI is monkeypatched to the _InstrumentedFastAPI subclass while global instrumentation is active, so gating on fastapi.FastAPI would make pre-existing app instances fail the isinstance check during that window.

Builds on the approach and review feedback from the now-stale #4041 (@punitmahes), with @xrmx's notes applied (stop unwrapping at the app instance; changelog under Fixed) and the parameter typing he flagged addressed.

Fixes #4031

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • Added an integration test instrumenting a CORSMiddleware-wrapped app and asserting theemitted SERVER span name and http.route attribute (name and value type).
  • Added unit tests for _unwrap_middleware (bare app, single/nested middleware, FastAPIinstance with an unrelated app attribute, and the no-app-found case) and for the skip path when no FastAPI application is found.
  • Ran the full opentelemetry-instrumentation-fastapi suite against both the oldest(fastapi==0.119.1/starlette==0.48.0) and latest (fastapi==0.137.2/starlette==1.3.1) pinned versions, all passing. ruff check and ruff format --check clean.

Does This PR Require a Core Repo Change?

  • No.

Checklist:

See contributing.md for styleguide, changelog guidelines, and more.

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

FastAPIInstrumentor.instrument_app/uninstrument_app assumed they were
handed a fastapi.FastAPI instance and raised AttributeError when given an
application wrapped in ASGI middleware such as
CORSMiddleware(app=fastapi_app), because the wrapper has no
build_middleware_stack method.

Add a _unwrap_middleware helper that follows the conventional `.app`
attribute chain down to the underlying Starlette/FastAPI application, and
skip gracefully with a warning when none is found. Widen the public app
parameter annotation to ASGIApp to reflect that wrapped apps are now
accepted. The unwrap stop-condition and guards check Starlette rather
than fastapi.FastAPI because the latter is monkeypatched to a subclass
while global instrumentation is active, which would make pre-existing app
instances fail an isinstance check.

Builds on the approach and maintainer review feedback from the
previously abandoned PR open-telemetry#4041 by @punitmahes.

Fixes open-telemetry#4031

Assisted-by: Claude Opus 4.8
@kshitizj03 kshitizj03 requested a review from a team as a code owner June 22, 2026 19:50
towncrier uses the fragment filename as the changelog reference, so name
it after the PR (open-telemetry#4729) rather than the issue.

Assisted-by: Claude Opus 4.8
The non-FastAPI uninstrument test referenced no instance state, tripping
pylint R6301 (no-self-use) in CI. Assert that uninstrument_app on a
non-Starlette app does not attach _original_build_middleware_stack, which
both uses self and strengthens the test.

Assisted-by: Claude Opus 4.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Incompatible with CORSMiddleware app

1 participant