@@ -178,6 +178,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
178178
179179from __future__ import annotations
180180
181+ import functools
181182import logging
182183import types
183184from typing import Collection , Literal
@@ -226,7 +227,7 @@ class FastAPIInstrumentor(BaseInstrumentor):
226227
227228 @staticmethod
228229 def instrument_app (
229- app ,
230+ app : fastapi . FastAPI ,
230231 server_request_hook : ServerRequestHook = None ,
231232 client_request_hook : ClientRequestHook = None ,
232233 client_response_hook : ClientResponseHook = None ,
@@ -290,9 +291,11 @@ def instrument_app(
290291 # to faithfully record what is returned to the client since it technically cannot know what `ServerErrorMiddleware` is going to do.
291292
292293 def build_middleware_stack (self : Starlette ) -> ASGIApp :
293- app = type (self ).build_middleware_stack (self )
294- app = OpenTelemetryMiddleware (
295- app ,
294+ inner_server_error_middleware : ASGIApp = (
295+ self ._original_build_middleware_stack ()
296+ ) # type: ignore
297+ otel_middleware = OpenTelemetryMiddleware (
298+ inner_server_error_middleware ,
296299 excluded_urls = excluded_urls ,
297300 default_span_details = _get_default_span_details ,
298301 server_request_hook = server_request_hook ,
@@ -310,12 +313,28 @@ def build_middleware_stack(self: Starlette) -> ASGIApp:
310313 # are handled.
311314 # This should not happen unless there is a bug in OpenTelemetryMiddleware, but if there is we don't want that
312315 # to impact the user's application just because we wrapped the middlewares in this order.
313- app = ServerErrorMiddleware (app )
314- return app
316+ if isinstance (
317+ inner_server_error_middleware , ServerErrorMiddleware
318+ ): # usually true
319+ outer_server_error_middleware = ServerErrorMiddleware (
320+ app = otel_middleware ,
321+ handler = inner_server_error_middleware .handler ,
322+ debug = inner_server_error_middleware .debug ,
323+ )
324+ else :
325+ # Something else seems to have patched things, or maybe Starlette changed.
326+ # Just create a default ServerErrorMiddleware.
327+ outer_server_error_middleware = ServerErrorMiddleware (
328+ app = otel_middleware
329+ )
330+ return outer_server_error_middleware
315331
316332 app ._original_build_middleware_stack = app .build_middleware_stack
317333 app .build_middleware_stack = types .MethodType (
318- build_middleware_stack , app
334+ functools .wraps (app .build_middleware_stack )(
335+ build_middleware_stack
336+ ),
337+ app ,
319338 )
320339
321340 app ._is_instrumented_by_opentelemetry = True
0 commit comments