1010from sentry_sdk ._types import MYPY
1111from sentry_sdk .hub import Hub , _should_send_default_pii
1212from sentry_sdk .integrations ._wsgi_common import _filter_headers
13- from sentry_sdk .utils import transaction_from_function
13+ from sentry_sdk .utils import ContextVar , event_from_exception , transaction_from_function
1414
1515if MYPY :
1616 from typing import Dict
17+ from typing import Any
18+
19+
20+ _asgi_middleware_applied = ContextVar ("sentry_asgi_middleware_applied" )
21+
22+
23+ def _capture_exception (hub , exc ):
24+ # type: (Hub, Any) -> None
25+
26+ # Check client here as it might have been unset while streaming response
27+ if hub .client is not None :
28+ event , hint = event_from_exception (
29+ exc ,
30+ client_options = hub .client .options ,
31+ mechanism = {"type" : "asgi" , "handled" : False },
32+ )
33+ hub .capture_event (event , hint = hint )
1734
1835
1936class SentryAsgiMiddleware :
@@ -35,20 +52,31 @@ async def run_asgi2(receive, send):
3552 return self ._run_app (scope , lambda : self .app (scope , receive , send ))
3653
3754 async def _run_app (self , scope , callback ):
38- hub = Hub .current
39- with Hub (hub ) as hub :
40- with hub .configure_scope () as sentry_scope :
41- sentry_scope ._name = "asgi"
42- sentry_scope .transaction = scope .get ("path" ) or "unknown asgi request"
43-
44- processor = functools .partial (self .event_processor , asgi_scope = scope )
45- sentry_scope .add_event_processor (processor )
46-
47- try :
48- await callback ()
49- except Exception as exc :
50- hub .capture_exception (exc )
51- raise exc from None
55+ if _asgi_middleware_applied .get (False ):
56+ return await callback ()
57+
58+ _asgi_middleware_applied .set (True )
59+ try :
60+ hub = Hub (Hub .current )
61+ with hub :
62+ with hub .configure_scope () as sentry_scope :
63+ sentry_scope ._name = "asgi"
64+ sentry_scope .transaction = (
65+ scope .get ("path" ) or "unknown asgi request"
66+ )
67+
68+ processor = functools .partial (
69+ self .event_processor , asgi_scope = scope
70+ )
71+ sentry_scope .add_event_processor (processor )
72+
73+ try :
74+ await callback ()
75+ except Exception as exc :
76+ _capture_exception (hub , exc )
77+ raise exc from None
78+ finally :
79+ _asgi_middleware_applied .set (False )
5280
5381 def event_processor (self , event , hint , asgi_scope ):
5482 request_info = event .setdefault ("request" , {})
0 commit comments