9
9
from sentry_sdk .utils import (
10
10
capture_internal_exceptions ,
11
11
event_from_exception ,
12
+ transaction_from_function ,
12
13
HAS_REAL_CONTEXTVARS ,
13
14
)
14
15
15
16
import asyncio
16
- from aiohttp .web import Application , HTTPException # type: ignore
17
+ from aiohttp .web import Application , HTTPException , UrlDispatcher # type: ignore
17
18
18
19
from sentry_sdk ._types import MYPY
19
20
20
21
if MYPY :
21
22
from aiohttp .web_request import Request # type: ignore
23
+ from aiohttp .abc import AbstractMatchInfo # type: ignore
22
24
from typing import Any
23
25
from typing import Dict
24
26
from typing import Tuple
25
27
from typing import Callable
26
28
27
29
from sentry_sdk .utils import ExcInfo
30
+ from sentry_sdk ._types import EventProcessor
28
31
29
32
30
33
class AioHttpIntegration (Integration ):
@@ -60,14 +63,17 @@ async def inner():
60
63
scope .clear_breadcrumbs ()
61
64
scope .add_event_processor (_make_request_processor (weak_request ))
62
65
63
- try :
64
- response = await old_handle (self , request )
65
- except HTTPException :
66
- raise
67
- except Exception :
68
- reraise (* _capture_exception (hub ))
66
+ # If this transaction name makes it to the UI, AIOHTTP's
67
+ # URL resolver did not find a route or died trying.
68
+ with hub .span (transaction = "generic AIOHTTP request" ):
69
+ try :
70
+ response = await old_handle (self , request )
71
+ except HTTPException :
72
+ raise
73
+ except Exception :
74
+ reraise (* _capture_exception (hub ))
69
75
70
- return response
76
+ return response
71
77
72
78
# Explicitly wrap in task such that current contextvar context is
73
79
# copied. Just doing `return await inner()` will leak scope data
@@ -76,9 +82,30 @@ async def inner():
76
82
77
83
Application ._handle = sentry_app_handle
78
84
85
+ old_urldispatcher_resolve = UrlDispatcher .resolve
86
+
87
+ async def sentry_urldispatcher_resolve (self , request ):
88
+ # type: (UrlDispatcher, Request) -> AbstractMatchInfo
89
+ rv = await old_urldispatcher_resolve (self , request )
90
+
91
+ name = None
92
+
93
+ try :
94
+ name = transaction_from_function (rv .handler )
95
+ except Exception :
96
+ pass
97
+
98
+ if name is not None :
99
+ with Hub .current .configure_scope () as scope :
100
+ scope .transaction = name
101
+
102
+ return rv
103
+
104
+ UrlDispatcher .resolve = sentry_urldispatcher_resolve
105
+
79
106
80
107
def _make_request_processor (weak_request ):
81
- # type: (Callable[[], Request]) -> Callable
108
+ # type: (Callable[[], Request]) -> EventProcessor
82
109
def aiohttp_processor (
83
110
event , # type: Dict[str, Any]
84
111
hint , # type: Dict[str, Tuple[type, BaseException, Any]]
0 commit comments