|
15 | 15 |
|
16 | 16 | from sentry_sdk.integrations._asgi_common import (
|
17 | 17 | _get_headers,
|
| 18 | + _get_query, |
18 | 19 | _get_request_data,
|
19 | 20 | _get_url,
|
20 | 21 | )
|
|
57 | 58 |
|
58 | 59 | TRANSACTION_STYLE_VALUES = ("endpoint", "url")
|
59 | 60 |
|
| 61 | +ASGI_SCOPE_PROPERTY_TO_ATTRIBUTE = { |
| 62 | + "http_version": "network.protocol.version", |
| 63 | + "method": "http.request.method", |
| 64 | + "path": "url.path", |
| 65 | + "scheme": "url.scheme", |
| 66 | + "type": "network.protocol.name", |
| 67 | +} |
| 68 | + |
60 | 69 |
|
61 | 70 | def _capture_exception(exc, mechanism_type="asgi"):
|
62 | 71 | # type: (Any, str) -> None
|
@@ -213,23 +222,21 @@ async def _run_app(self, scope, receive, send, asgi_version):
|
213 | 222 | )
|
214 | 223 | if should_trace
|
215 | 224 | else nullcontext()
|
216 |
| - ) as transaction: |
217 |
| - if transaction is not None: |
218 |
| - logger.debug( |
219 |
| - "[ASGI] Started transaction: %s", transaction |
220 |
| - ) |
221 |
| - transaction.set_tag("asgi.type", ty) |
| 225 | + ) as span: |
| 226 | + if span is not None: |
| 227 | + logger.debug("[ASGI] Started transaction: %s", span) |
| 228 | + span.set_tag("asgi.type", ty) |
222 | 229 | try:
|
223 | 230 |
|
224 | 231 | async def _sentry_wrapped_send(event):
|
225 | 232 | # type: (Dict[str, Any]) -> Any
|
226 | 233 | is_http_response = (
|
227 | 234 | event.get("type") == "http.response.start"
|
228 |
| - and transaction is not None |
| 235 | + and span is not None |
229 | 236 | and "status" in event
|
230 | 237 | )
|
231 | 238 | if is_http_response:
|
232 |
| - transaction.set_http_status(event["status"]) |
| 239 | + span.set_http_status(event["status"]) |
233 | 240 |
|
234 | 241 | return await send(event)
|
235 | 242 |
|
@@ -328,12 +335,31 @@ def _get_transaction_name_and_source(self, transaction_style, asgi_scope):
|
328 | 335 |
|
329 | 336 | def _prepopulate_attributes(scope):
|
330 | 337 | # type: (Any) -> dict[str, Any]
|
331 |
| - """Unpack asgi_scope into serializable attributes.""" |
| 338 | + """Unpack ASGI scope into serializable OTel attributes.""" |
332 | 339 | scope = scope or {}
|
333 | 340 |
|
334 | 341 | attributes = {}
|
335 |
| - for attr in ("endpoint", "path", "root_path", "route", "scheme", "server", "type"): |
| 342 | + for attr, key in ASGI_SCOPE_PROPERTY_TO_ATTRIBUTE.items(): |
336 | 343 | if scope.get(attr):
|
337 |
| - attributes[f"asgi_scope.{attr}"] = scope[attr] |
| 344 | + attributes[key] = scope[attr] |
| 345 | + |
| 346 | + for attr in ("client", "server"): |
| 347 | + if scope.get(attr): |
| 348 | + try: |
| 349 | + host, port = scope[attr] |
| 350 | + attributes[f"{attr}.address"] = host |
| 351 | + attributes[f"{attr}.port"] = port |
| 352 | + except Exception: |
| 353 | + pass |
| 354 | + |
| 355 | + try: |
| 356 | + full_url = _get_url(scope) |
| 357 | + query = _get_query(scope) |
| 358 | + if query: |
| 359 | + full_url = f"{full_url}?{query}" |
| 360 | + |
| 361 | + attributes["url.full"] = full_url |
| 362 | + except Exception: |
| 363 | + pass |
338 | 364 |
|
339 | 365 | return attributes
|
0 commit comments