|
15 | 15 | from sentry_sdk.consts import OP |
16 | 16 | from sentry_sdk.integrations._asgi_common import ( |
17 | 17 | _get_headers, |
| 18 | + _get_request_attributes, |
18 | 19 | _get_request_data, |
19 | 20 | _get_url, |
20 | 21 | ) |
|
23 | 24 | nullcontext, |
24 | 25 | ) |
25 | 26 | from sentry_sdk.sessions import track_session |
26 | | -from sentry_sdk.traces import StreamedSpan |
| 27 | +from sentry_sdk.traces import ( |
| 28 | + StreamedSpan, |
| 29 | + SegmentSource, |
| 30 | + SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE, |
| 31 | +) |
27 | 32 | from sentry_sdk.tracing import ( |
28 | 33 | SOURCE_FOR_STYLE, |
29 | 34 | Transaction, |
|
40 | 45 | _get_installed_modules, |
41 | 46 | reraise, |
42 | 47 | capture_internal_exceptions, |
| 48 | + qualname_from_function, |
43 | 49 | ) |
44 | 50 |
|
45 | 51 | from typing import TYPE_CHECKING |
@@ -235,7 +241,7 @@ async def _run_app( |
235 | 241 | transaction_source, "value", transaction_source |
236 | 242 | ), |
237 | 243 | "sentry.origin": self.span_origin, |
238 | | - "asgi.type": ty, |
| 244 | + "network.protocol.name": ty, |
239 | 245 | } |
240 | 246 |
|
241 | 247 | if ty in ("http", "websocket"): |
@@ -301,6 +307,9 @@ async def _run_app( |
301 | 307 | else nullcontext() |
302 | 308 | ) |
303 | 309 |
|
| 310 | + for attribute, value in _get_request_attributes(scope): |
| 311 | + sentry_scope.set_attribute(attribute, value) |
| 312 | + |
304 | 313 | with span_ctx as span: |
305 | 314 | try: |
306 | 315 |
|
@@ -329,13 +338,24 @@ async def _sentry_wrapped_send( |
329 | 338 | return await send(event) |
330 | 339 |
|
331 | 340 | if asgi_version == 2: |
332 | | - return await self.app(scope)( |
| 341 | + result = await self.app(scope)( |
333 | 342 | receive, _sentry_wrapped_send |
334 | 343 | ) |
335 | 344 | else: |
336 | | - return await self.app( |
| 345 | + result = await self.app( |
337 | 346 | scope, receive, _sentry_wrapped_send |
338 | 347 | ) |
| 348 | + |
| 349 | + with capture_internal_exceptions(): |
| 350 | + name, source = self._get_segment_name_and_source( |
| 351 | + self.transaction_style, scope |
| 352 | + ) |
| 353 | + if isinstance(span, StreamedSpan): |
| 354 | + span.name = name |
| 355 | + span.set_attribute("sentry.span.source", source) |
| 356 | + |
| 357 | + return result |
| 358 | + |
339 | 359 | except Exception as exc: |
340 | 360 | suppress_chained_exceptions = ( |
341 | 361 | sentry_sdk.get_client() |
@@ -424,3 +444,40 @@ def _get_transaction_name_and_source( |
424 | 444 | return name, source |
425 | 445 |
|
426 | 446 | return name, source |
| 447 | + |
| 448 | + def _get_segment_name_and_source( |
| 449 | + self: "SentryAsgiMiddleware", segment_style: str, asgi_scope: "Any" |
| 450 | + ) -> "Tuple[str, str]": |
| 451 | + name = None |
| 452 | + source = SEGMENT_SOURCE_FOR_STYLE[segment_style] |
| 453 | + ty = asgi_scope.get("type") |
| 454 | + |
| 455 | + if segment_style == "endpoint": |
| 456 | + endpoint = asgi_scope.get("endpoint") |
| 457 | + # Webframeworks like Starlette mutate the ASGI env once routing is |
| 458 | + # done, which is sometime after the request has started. If we have |
| 459 | + # an endpoint, overwrite our generic transaction name. |
| 460 | + if endpoint: |
| 461 | + name = qualname_from_function(endpoint) or "" |
| 462 | + else: |
| 463 | + name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None) |
| 464 | + source = SegmentSource.URL.value |
| 465 | + |
| 466 | + elif segment_style == "url": |
| 467 | + # FastAPI includes the route object in the scope to let Sentry extract the |
| 468 | + # path from it for the transaction name |
| 469 | + route = asgi_scope.get("route") |
| 470 | + if route: |
| 471 | + path = getattr(route, "path", None) |
| 472 | + if path is not None: |
| 473 | + name = path |
| 474 | + else: |
| 475 | + name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None) |
| 476 | + source = SegmentSource.URL.value |
| 477 | + |
| 478 | + if name is None: |
| 479 | + name = _DEFAULT_TRANSACTION_NAME |
| 480 | + source = SegmentSource.ROUTE.value |
| 481 | + return name, source |
| 482 | + |
| 483 | + return name, source |
0 commit comments