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