|
15 | 15 | from sentry_sdk.utils import (
|
16 | 16 | capture_internal_exceptions,
|
17 | 17 | event_from_exception,
|
| 18 | + logger, |
18 | 19 | transaction_from_function,
|
19 | 20 | HAS_REAL_CONTEXTVARS,
|
20 | 21 | CONTEXTVARS_ERROR_MESSAGE,
|
|
25 | 26 | import asyncio
|
26 | 27 |
|
27 | 28 | from aiohttp import __version__ as AIOHTTP_VERSION
|
| 29 | + from aiohttp import ClientSession, TraceConfig |
28 | 30 | from aiohttp.web import Application, HTTPException, UrlDispatcher
|
29 | 31 | except ImportError:
|
30 | 32 | raise DidNotEnable("AIOHTTP not installed")
|
|
34 | 36 | if MYPY:
|
35 | 37 | from aiohttp.web_request import Request
|
36 | 38 | from aiohttp.abc import AbstractMatchInfo
|
| 39 | + from aiohttp import TraceRequestStartParams |
| 40 | + from aiohttp import TraceRequestEndParams |
| 41 | + from types import SimpleNamespace |
37 | 42 | from typing import Any
|
38 | 43 | from typing import Dict
|
39 | 44 | from typing import Optional
|
|
48 | 53 | TRANSACTION_STYLE_VALUES = ("handler_name", "method_and_path_pattern")
|
49 | 54 |
|
50 | 55 |
|
| 56 | +def create_trace_config() -> TraceConfig: |
| 57 | + async def on_request_start( |
| 58 | + session: ClientSession, |
| 59 | + trace_config_ctx: "SimpleNamespace", |
| 60 | + params: "TraceRequestStartParams", |
| 61 | + ): |
| 62 | + hub = Hub.current |
| 63 | + if hub.get_integration(AioHttpIntegration) is None: |
| 64 | + return |
| 65 | + |
| 66 | + method = params.method.upper() |
| 67 | + request_url = str(params.url) |
| 68 | + |
| 69 | + span = hub.start_span( |
| 70 | + op=OP.HTTP_CLIENT, description="%s %s" % (method, request_url) |
| 71 | + ) |
| 72 | + span.set_data("method", method) |
| 73 | + span.set_data("url", request_url) |
| 74 | + |
| 75 | + for key, value in hub.iter_trace_propagation_headers(span): |
| 76 | + logger.debug( |
| 77 | + "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( |
| 78 | + key=key, value=value, url=params.url |
| 79 | + ) |
| 80 | + ) |
| 81 | + params.headers[key] = value |
| 82 | + |
| 83 | + trace_config_ctx.span = span |
| 84 | + |
| 85 | + async def on_request_end( |
| 86 | + session: ClientSession, |
| 87 | + trace_config_ctx: "SimpleNamespace", |
| 88 | + params: "TraceRequestEndParams", |
| 89 | + ): |
| 90 | + if trace_config_ctx.span is None: |
| 91 | + return |
| 92 | + |
| 93 | + span = trace_config_ctx.span |
| 94 | + span.set_data("status_code", int(params.response.status)) |
| 95 | + span.set_http_status(int(params.response.status)) |
| 96 | + span.set_data("reason", params.response.reason) |
| 97 | + span.finish() |
| 98 | + |
| 99 | + trace_config = TraceConfig() |
| 100 | + |
| 101 | + trace_config.on_request_start.append(on_request_start) |
| 102 | + trace_config.on_request_end.append(on_request_end) |
| 103 | + |
| 104 | + return trace_config |
| 105 | + |
| 106 | + |
51 | 107 | class AioHttpIntegration(Integration):
|
52 | 108 | identifier = "aiohttp"
|
53 | 109 |
|
@@ -162,6 +218,22 @@ async def sentry_urldispatcher_resolve(self, request):
|
162 | 218 |
|
163 | 219 | UrlDispatcher.resolve = sentry_urldispatcher_resolve
|
164 | 220 |
|
| 221 | + old_client_session_init = ClientSession.__init__ |
| 222 | + |
| 223 | + def init(*args, **kwargs): |
| 224 | + hub = Hub.current |
| 225 | + if hub.get_integration(AioHttpIntegration) is None: |
| 226 | + return old_client_session_init(*args, **kwargs) |
| 227 | + |
| 228 | + client_trace_configs = list(kwargs.get("trace_configs", ())) |
| 229 | + trace_config = create_trace_config() |
| 230 | + client_trace_configs.append(trace_config) |
| 231 | + |
| 232 | + kwargs["trace_configs"] = client_trace_configs |
| 233 | + return old_client_session_init(*args, **kwargs) |
| 234 | + |
| 235 | + ClientSession.__init__ = init |
| 236 | + |
165 | 237 |
|
166 | 238 | def _make_request_processor(weak_request):
|
167 | 239 | # type: (Callable[[], Request]) -> EventProcessor
|
|
0 commit comments