13
13
from sentry_sdk .integrations ._wsgi_common import RequestExtractor , _filter_headers
14
14
from sentry_sdk .integrations .logging import ignore_logger
15
15
16
- from sanic import Sanic # type: ignore
16
+ from sanic import Sanic , __version__ as VERSION # type: ignore
17
17
from sanic .exceptions import SanicException # type: ignore
18
18
from sanic .router import Router # type: ignore
19
19
from sanic .handlers import ErrorHandler # type: ignore
24
24
from typing import Any
25
25
from typing import Callable
26
26
from typing import Dict
27
- from typing import List
28
- from typing import Tuple
29
- from sanic .exceptions import InvalidUsage
30
27
from typing import Optional
31
28
from typing import Union
29
+ from typing import Tuple
32
30
from sanic .request import RequestParameters
33
31
34
32
@@ -46,12 +44,17 @@ def setup_once():
46
44
" or aiocontextvars package"
47
45
)
48
46
49
- # Sanic 0.8 and older creates a logger named "root" and puts a
50
- # stringified version of every exception in there (without exc_info),
51
- # which our error deduplication can't detect.
52
- #
53
- # https://github.com/huge-success/sanic/issues/1332
54
- ignore_logger ("root" )
47
+ if VERSION .startswith ("0.8." ):
48
+ # Sanic 0.8 and older creates a logger named "root" and puts a
49
+ # stringified version of every exception in there (without exc_info),
50
+ # which our error deduplication can't detect.
51
+ #
52
+ # We explicitly check the version here because it is a very
53
+ # invasive step to ignore this logger and not necessary in newer
54
+ # versions at all.
55
+ #
56
+ # https://github.com/huge-success/sanic/issues/1332
57
+ ignore_logger ("root" )
55
58
56
59
old_handle_request = Sanic .handle_request
57
60
@@ -79,7 +82,7 @@ async def sentry_handle_request(self, request, *args, **kwargs):
79
82
old_router_get = Router .get
80
83
81
84
def sentry_router_get (self , request ):
82
- # type: (Any, Request) -> Tuple[Callable, List, Dict[str, str], str]
85
+ # type: (Any, Request) -> Any
83
86
rv = old_router_get (self , request )
84
87
hub = Hub .current
85
88
if hub .get_integration (SanicIntegration ) is not None :
@@ -93,7 +96,7 @@ def sentry_router_get(self, request):
93
96
old_error_handler_lookup = ErrorHandler .lookup
94
97
95
98
def sentry_error_handler_lookup (self , exception ):
96
- # type: (Any, Union[ValueError, InvalidUsage] ) -> Optional[Callable]
99
+ # type: (Any, Exception ) -> Optional[Callable]
97
100
_capture_exception (exception )
98
101
old_error_handler = old_error_handler_lookup (self , exception )
99
102
@@ -104,13 +107,16 @@ def sentry_error_handler_lookup(self, exception):
104
107
return old_error_handler
105
108
106
109
async def sentry_wrapped_error_handler (request , exception ):
107
- # type: (Request, ValueError ) -> Any
110
+ # type: (Request, Exception ) -> Any
108
111
try :
109
112
response = old_error_handler (request , exception )
110
113
if isawaitable (response ):
111
114
response = await response
112
115
return response
113
116
except Exception :
117
+ # Report errors that occur in Sanic error handler. These
118
+ # exceptions will not even show up in Sanic's
119
+ # `sanic.exceptions` logger.
114
120
exc_info = sys .exc_info ()
115
121
_capture_exception (exc_info )
116
122
reraise (* exc_info )
@@ -120,13 +126,8 @@ async def sentry_wrapped_error_handler(request, exception):
120
126
ErrorHandler .lookup = sentry_error_handler_lookup
121
127
122
128
123
- def _capture_exception (
124
- exception # type: Union[Tuple[type, BaseException, Any], ValueError, InvalidUsage]
125
- ):
126
- # type: (...) -> None
127
- if isinstance (exception , SanicException ):
128
- return
129
-
129
+ def _capture_exception (exception ):
130
+ # type: (Union[Tuple[Optional[type], Optional[BaseException], Any], BaseException]) -> None
130
131
hub = Hub .current
131
132
integration = hub .get_integration (SanicIntegration )
132
133
if integration is None :
@@ -144,7 +145,14 @@ def _capture_exception(
144
145
def _make_request_processor (weak_request ):
145
146
# type: (Callable[[], Request]) -> Callable
146
147
def sanic_processor (event , hint ):
147
- # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
148
+ # type: (Dict[str, Any], Dict[str, Any]) -> Optional[Dict[str, Any]]
149
+
150
+ try :
151
+ if issubclass (hint ["exc_info" ][0 ], SanicException ):
152
+ return None
153
+ except KeyError :
154
+ pass
155
+
148
156
request = weak_request ()
149
157
if request is None :
150
158
return event
0 commit comments