@@ -186,6 +186,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
186186import logging
187187import types
188188from typing import Collection , Literal
189+ from weakref import WeakSet as _WeakSet
189190
190191import fastapi
191192from starlette .applications import Starlette
@@ -358,6 +359,11 @@ def uninstrument_app(app: fastapi.FastAPI):
358359 app .middleware_stack = app .build_middleware_stack ()
359360 app ._is_instrumented_by_opentelemetry = False
360361
362+ # Remove the app from the set of instrumented apps to avoid calling uninstrument twice
363+ # if the instrumentation is later disabled or such
364+ # Use discard to avoid KeyError if already GC'ed
365+ _InstrumentedFastAPI ._instrumented_fastapi_apps .discard (app )
366+
361367 def instrumentation_dependencies (self ) -> Collection [str ]:
362368 return _instruments
363369
@@ -388,7 +394,11 @@ def _instrument(self, **kwargs):
388394 fastapi .FastAPI = _InstrumentedFastAPI
389395
390396 def _uninstrument (self , ** kwargs ):
391- for instance in _InstrumentedFastAPI ._instrumented_fastapi_apps :
397+ # Create a copy of the set to avoid RuntimeError during iteration
398+ instances_to_uninstrument = list (
399+ _InstrumentedFastAPI ._instrumented_fastapi_apps
400+ )
401+ for instance in instances_to_uninstrument :
392402 self .uninstrument_app (instance )
393403 _InstrumentedFastAPI ._instrumented_fastapi_apps .clear ()
394404 fastapi .FastAPI = self ._original_fastapi
@@ -406,7 +416,8 @@ class _InstrumentedFastAPI(fastapi.FastAPI):
406416 _http_capture_headers_sanitize_fields : list [str ] | None = None
407417 _exclude_spans : list [Literal ["receive" , "send" ]] | None = None
408418
409- _instrumented_fastapi_apps = set ()
419+ # Track instrumented app instances using weak references to avoid GC leaks
420+ _instrumented_fastapi_apps = _WeakSet ()
410421 _sem_conv_opt_in_mode = _StabilityMode .DEFAULT
411422
412423 def __init__ (self , * args , ** kwargs ):
@@ -426,10 +437,6 @@ def __init__(self, *args, **kwargs):
426437 )
427438 _InstrumentedFastAPI ._instrumented_fastapi_apps .add (self )
428439
429- def __del__ (self ):
430- if self in _InstrumentedFastAPI ._instrumented_fastapi_apps :
431- _InstrumentedFastAPI ._instrumented_fastapi_apps .remove (self )
432-
433440
434441def _get_route_details (scope ):
435442 """
0 commit comments