3737
3838_DEFAULT_TRANSACTION_NAME = "generic ASGI request"
3939
40+ TRANSACTION_STYLE_VALUES = ("endpoint" , "url" )
41+
4042
4143def _capture_exception (hub , exc ):
4244 # type: (Hub, Any) -> None
@@ -68,10 +70,10 @@ def _looks_like_asgi3(app):
6870
6971
7072class SentryAsgiMiddleware :
71- __slots__ = ("app" , "__call__" )
73+ __slots__ = ("app" , "__call__" , "transaction_style" )
7274
73- def __init__ (self , app , unsafe_context_data = False ):
74- # type: (Any, bool) -> None
75+ def __init__ (self , app , unsafe_context_data = False , transaction_style = "endpoint" ):
76+ # type: (Any, bool, str ) -> None
7577 """
7678 Instrument an ASGI application with Sentry. Provides HTTP/websocket
7779 data to sent events and basic handling for exceptions bubbling up
@@ -87,6 +89,12 @@ def __init__(self, app, unsafe_context_data=False):
8789 "The ASGI middleware for Sentry requires Python 3.7+ "
8890 "or the aiocontextvars package." + CONTEXTVARS_ERROR_MESSAGE
8991 )
92+ if transaction_style not in TRANSACTION_STYLE_VALUES :
93+ raise ValueError (
94+ "Invalid value for transaction_style: %s (must be in %s)"
95+ % (transaction_style , TRANSACTION_STYLE_VALUES )
96+ )
97+ self .transaction_style = transaction_style
9098 self .app = app
9199
92100 if _looks_like_asgi3 (app ):
@@ -179,12 +187,21 @@ def event_processor(self, event, hint, asgi_scope):
179187 event .get ("transaction" , _DEFAULT_TRANSACTION_NAME )
180188 == _DEFAULT_TRANSACTION_NAME
181189 ):
182- endpoint = asgi_scope .get ("endpoint" )
183- # Webframeworks like Starlette mutate the ASGI env once routing is
184- # done, which is sometime after the request has started. If we have
185- # an endpoint, overwrite our generic transaction name.
186- if endpoint :
187- event ["transaction" ] = transaction_from_function (endpoint )
190+ if self .transaction_style == "endpoint" :
191+ endpoint = asgi_scope .get ("endpoint" )
192+ # Webframeworks like Starlette mutate the ASGI env once routing is
193+ # done, which is sometime after the request has started. If we have
194+ # an endpoint, overwrite our generic transaction name.
195+ if endpoint :
196+ event ["transaction" ] = transaction_from_function (endpoint )
197+ elif self .transaction_style == "url" :
198+ # FastAPI includes the route object in the scope to let Sentry extract the
199+ # path from it for the transaction name
200+ route = asgi_scope .get ("route" )
201+ if route :
202+ path = getattr (route , "path" , None )
203+ if path is not None :
204+ event ["transaction" ] = path
188205
189206 event ["request" ] = request_info
190207
0 commit comments