@@ -189,6 +189,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
189189
190190import  fastapi 
191191from  starlette .applications  import  Starlette 
192+ from  starlette .middleware .errors  import  ServerErrorMiddleware 
192193from  starlette .routing  import  Match 
193194from  starlette .types  import  ASGIApp , Receive , Scope , Send 
194195
@@ -210,7 +211,6 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
210211from  opentelemetry .metrics  import  MeterProvider , get_meter 
211212from  opentelemetry .semconv .attributes .http_attributes  import  HTTP_ROUTE 
212213from  opentelemetry .trace  import  (
213-     Span ,
214214    TracerProvider ,
215215    get_current_span ,
216216    get_tracer ,
@@ -300,28 +300,17 @@ def instrument_app(
300300            # exceptions from user-provided hooks of tearing through, we wrap 
301301            # them to return without failure unconditionally. 
302302            def  build_middleware_stack (self : Starlette ) ->  ASGIApp :
303-                 def  failsafe (func ):
304-                     @functools .wraps (func ) 
305-                     def  wrapper (span : Span , * args , ** kwargs ):
306-                         if  func  is  not   None :
307-                             try :
308-                                 func (span , * args , ** kwargs )
309-                             except  Exception  as  exc :  # pylint: disable=broad-exception-caught 
310-                                 span .record_exception (exc )
311- 
312-                     return  wrapper 
313- 
314303                inner_server_error_middleware : ASGIApp  =  (  # type: ignore 
315304                    self ._original_build_middleware_stack ()  # type: ignore 
316305                )
317306
318-                 return  OpenTelemetryMiddleware (
307+                 otel_middleware   =  OpenTelemetryMiddleware (
319308                    inner_server_error_middleware ,
320309                    excluded_urls = excluded_urls ,
321310                    default_span_details = _get_default_span_details ,
322-                     server_request_hook = failsafe ( server_request_hook ) ,
323-                     client_request_hook = failsafe ( client_request_hook ) ,
324-                     client_response_hook = failsafe ( client_response_hook ) ,
311+                     server_request_hook = server_request_hook ,
312+                     client_request_hook = client_request_hook ,
313+                     client_response_hook = client_response_hook ,
325314                    # Pass in tracer/meter to get __name__and __version__ of fastapi instrumentation 
326315                    tracer = tracer ,
327316                    meter = meter ,
@@ -331,6 +320,24 @@ def wrapper(span: Span, *args, **kwargs):
331320                    exclude_spans = exclude_spans ,
332321                )
333322
323+                 # Wrap in an outer layer of ServerErrorMiddleware so that any exceptions raised in OpenTelemetryMiddleware 
324+                 # are handled. 
325+                 # This should not happen unless there is a bug in OpenTelemetryMiddleware, but if there is we don't want that 
326+                 # to impact the user's application just because we wrapped the middlewares in this order. 
327+                 if  isinstance (
328+                     inner_server_error_middleware , ServerErrorMiddleware 
329+                 ):  # usually true 
330+                     outer_server_error_middleware  =  ServerErrorMiddleware (
331+                         app = otel_middleware ,
332+                     )
333+                 else :
334+                     # Something else seems to have patched things, or maybe Starlette changed. 
335+                     # Just create a default ServerErrorMiddleware. 
336+                     outer_server_error_middleware  =  ServerErrorMiddleware (
337+                         app = otel_middleware 
338+                     )
339+                 return  outer_server_error_middleware 
340+ 
334341            app ._original_build_middleware_stack  =  app .build_middleware_stack 
335342            app .build_middleware_stack  =  types .MethodType (
336343                functools .wraps (app .build_middleware_stack )(
0 commit comments