Skip to content

Commit 343bca9

Browse files
authored
ref(sanic): Use new scopes API (#2875)
1 parent 4fc60aa commit 343bca9

File tree

2 files changed

+58
-65
lines changed

2 files changed

+58
-65
lines changed

sentry_sdk/integrations/sanic.py

Lines changed: 50 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
from inspect import isawaitable
44
from urllib.parse import urlsplit
55

6+
import sentry_sdk
67
from sentry_sdk import continue_trace
78
from sentry_sdk.consts import OP
8-
from sentry_sdk.hub import Hub
9+
from sentry_sdk.integrations import Integration, DidNotEnable
10+
from sentry_sdk.integrations._wsgi_common import RequestExtractor, _filter_headers
11+
from sentry_sdk.integrations.logging import ignore_logger
912
from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT, TRANSACTION_SOURCE_URL
1013
from sentry_sdk.scope import Scope
1114
from sentry_sdk.utils import (
@@ -16,10 +19,6 @@
1619
parse_version,
1720
reraise,
1821
)
19-
from sentry_sdk.integrations import Integration, DidNotEnable
20-
from sentry_sdk.integrations._wsgi_common import RequestExtractor, _filter_headers
21-
from sentry_sdk.integrations.logging import ignore_logger
22-
2322
from sentry_sdk._types import TYPE_CHECKING
2423

2524
if TYPE_CHECKING:
@@ -162,13 +161,13 @@ async def _startup(self):
162161
# type: (Sanic) -> None
163162
# This happens about as early in the lifecycle as possible, just after the
164163
# Request object is created. The body has not yet been consumed.
165-
self.signal("http.lifecycle.request")(_hub_enter)
164+
self.signal("http.lifecycle.request")(_context_enter)
166165

167166
# This happens after the handler is complete. In v21.9 this signal is not
168167
# dispatched when there is an exception. Therefore we need to close out
169-
# and call _hub_exit from the custom exception handler as well.
168+
# and call _context_exit from the custom exception handler as well.
170169
# See https://github.com/sanic-org/sanic/issues/2297
171-
self.signal("http.lifecycle.response")(_hub_exit)
170+
self.signal("http.lifecycle.response")(_context_exit)
172171

173172
# This happens inside of request handling immediately after the route
174173
# has been identified by the router.
@@ -178,23 +177,20 @@ async def _startup(self):
178177
await old_startup(self)
179178

180179

181-
async def _hub_enter(request):
180+
async def _context_enter(request):
182181
# type: (Request) -> None
183-
hub = Hub.current
184182
request.ctx._sentry_do_integration = (
185-
hub.get_integration(SanicIntegration) is not None
183+
sentry_sdk.get_client().get_integration(SanicIntegration) is not None
186184
)
187185

188186
if not request.ctx._sentry_do_integration:
189187
return
190188

191189
weak_request = weakref.ref(request)
192-
request.ctx._sentry_hub = Hub(hub)
193-
request.ctx._sentry_hub.__enter__()
194-
195-
with request.ctx._sentry_hub.configure_scope() as scope:
196-
scope.clear_breadcrumbs()
197-
scope.add_event_processor(_make_request_processor(weak_request))
190+
request.ctx._sentry_scope = sentry_sdk.isolation_scope()
191+
scope = request.ctx._sentry_scope.__enter__()
192+
scope.clear_breadcrumbs()
193+
scope.add_event_processor(_make_request_processor(weak_request))
198194

199195
transaction = continue_trace(
200196
dict(request.headers),
@@ -203,18 +199,20 @@ async def _hub_enter(request):
203199
name=request.path,
204200
source=TRANSACTION_SOURCE_URL,
205201
)
206-
request.ctx._sentry_transaction = request.ctx._sentry_hub.start_transaction(
202+
request.ctx._sentry_transaction = sentry_sdk.start_transaction(
207203
transaction
208204
).__enter__()
209205

210206

211-
async def _hub_exit(request, response=None):
207+
async def _context_exit(request, response=None):
212208
# type: (Request, Optional[BaseHTTPResponse]) -> None
213209
with capture_internal_exceptions():
214210
if not request.ctx._sentry_do_integration:
215211
return
216212

217-
integration = Hub.current.get_integration(SanicIntegration) # type: Integration
213+
integration = sentry_sdk.get_client().get_integration(
214+
SanicIntegration
215+
) # type: Integration
218216

219217
response_status = None if response is None else response.status
220218

@@ -228,7 +226,7 @@ async def _hub_exit(request, response=None):
228226
)
229227
request.ctx._sentry_transaction.__exit__(None, None, None)
230228

231-
request.ctx._sentry_hub.__exit__(None, None, None)
229+
request.ctx._sentry_scope.__exit__(None, None, None)
232230

233231

234232
async def _set_transaction(request, route, **_):
@@ -248,7 +246,7 @@ def _sentry_error_handler_lookup(self, exception, *args, **kwargs):
248246
if old_error_handler is None:
249247
return None
250248

251-
if Hub.current.get_integration(SanicIntegration) is None:
249+
if sentry_sdk.get_client().get_integration(SanicIntegration) is None:
252250
return old_error_handler
253251

254252
async def sentry_wrapped_error_handler(request, exception):
@@ -269,23 +267,21 @@ async def sentry_wrapped_error_handler(request, exception):
269267
# As mentioned in previous comment in _startup, this can be removed
270268
# after https://github.com/sanic-org/sanic/issues/2297 is resolved
271269
if SanicIntegration.version and SanicIntegration.version == (21, 9):
272-
await _hub_exit(request)
270+
await _context_exit(request)
273271

274272
return sentry_wrapped_error_handler
275273

276274

277275
async def _legacy_handle_request(self, request, *args, **kwargs):
278276
# type: (Any, Request, *Any, **Any) -> Any
279-
hub = Hub.current
280-
if hub.get_integration(SanicIntegration) is None:
277+
if sentry_sdk.get_client().get_integration(SanicIntegration) is None:
281278
return old_handle_request(self, request, *args, **kwargs)
282279

283280
weak_request = weakref.ref(request)
284281

285-
with Hub(hub) as hub:
286-
with hub.configure_scope() as scope:
287-
scope.clear_breadcrumbs()
288-
scope.add_event_processor(_make_request_processor(weak_request))
282+
with sentry_sdk.isolation_scope() as scope:
283+
scope.clear_breadcrumbs()
284+
scope.add_event_processor(_make_request_processor(weak_request))
289285

290286
response = old_handle_request(self, request, *args, **kwargs)
291287
if isawaitable(response):
@@ -297,51 +293,47 @@ async def _legacy_handle_request(self, request, *args, **kwargs):
297293
def _legacy_router_get(self, *args):
298294
# type: (Any, Union[Any, Request]) -> Any
299295
rv = old_router_get(self, *args)
300-
hub = Hub.current
301-
if hub.get_integration(SanicIntegration) is not None:
296+
if sentry_sdk.get_client().get_integration(SanicIntegration) is not None:
302297
with capture_internal_exceptions():
303-
with hub.configure_scope() as scope:
304-
if SanicIntegration.version and SanicIntegration.version >= (21, 3):
305-
# Sanic versions above and including 21.3 append the app name to the
306-
# route name, and so we need to remove it from Route name so the
307-
# transaction name is consistent across all versions
308-
sanic_app_name = self.ctx.app.name
309-
sanic_route = rv[0].name
310-
311-
if sanic_route.startswith("%s." % sanic_app_name):
312-
# We add a 1 to the len of the sanic_app_name because there is a dot
313-
# that joins app name and the route name
314-
# Format: app_name.route_name
315-
sanic_route = sanic_route[len(sanic_app_name) + 1 :]
316-
317-
scope.set_transaction_name(
318-
sanic_route, source=TRANSACTION_SOURCE_COMPONENT
319-
)
320-
else:
321-
scope.set_transaction_name(
322-
rv[0].__name__, source=TRANSACTION_SOURCE_COMPONENT
323-
)
298+
scope = Scope.get_isolation_scope()
299+
if SanicIntegration.version and SanicIntegration.version >= (21, 3):
300+
# Sanic versions above and including 21.3 append the app name to the
301+
# route name, and so we need to remove it from Route name so the
302+
# transaction name is consistent across all versions
303+
sanic_app_name = self.ctx.app.name
304+
sanic_route = rv[0].name
305+
306+
if sanic_route.startswith("%s." % sanic_app_name):
307+
# We add a 1 to the len of the sanic_app_name because there is a dot
308+
# that joins app name and the route name
309+
# Format: app_name.route_name
310+
sanic_route = sanic_route[len(sanic_app_name) + 1 :]
311+
312+
scope.set_transaction_name(
313+
sanic_route, source=TRANSACTION_SOURCE_COMPONENT
314+
)
315+
else:
316+
scope.set_transaction_name(
317+
rv[0].__name__, source=TRANSACTION_SOURCE_COMPONENT
318+
)
324319

325320
return rv
326321

327322

328323
def _capture_exception(exception):
329324
# type: (Union[Tuple[Optional[type], Optional[BaseException], Any], BaseException]) -> None
330-
hub = Hub.current
331-
integration = hub.get_integration(SanicIntegration)
325+
client = sentry_sdk.get_client()
326+
integration = client.get_integration(SanicIntegration)
332327
if integration is None:
333328
return
334329

335-
# If an integration is there, a client has to be there.
336-
client = hub.client # type: Any
337-
338330
with capture_internal_exceptions():
339331
event, hint = event_from_exception(
340332
exception,
341333
client_options=client.options,
342334
mechanism={"type": "sanic", "handled": False},
343335
)
344-
hub.capture_event(event, hint=hint)
336+
sentry_sdk.capture_event(event, hint=hint)
345337

346338

347339
def _make_request_processor(weak_request):

tests/integrations/sanic/test_sanic.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77

88
import pytest
99

10-
from sentry_sdk import capture_message, configure_scope
10+
from sentry_sdk import capture_message
1111
from sentry_sdk.integrations.sanic import SanicIntegration
12+
from sentry_sdk.scope import Scope
1213
from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT, TRANSACTION_SOURCE_URL
1314

1415
from sanic import Sanic, request, response, __version__ as SANIC_VERSION_RAW
@@ -233,13 +234,13 @@ def test_concurrency(sentry_init, app):
233234

234235
@app.route("/context-check/<i>")
235236
async def context_check(request, i):
236-
with configure_scope() as scope:
237-
scope.set_tag("i", i)
237+
scope = Scope.get_isolation_scope()
238+
scope.set_tag("i", i)
238239

239240
await asyncio.sleep(random.random())
240241

241-
with configure_scope() as scope:
242-
assert scope._tags["i"] == i
242+
scope = Scope.get_isolation_scope()
243+
assert scope._tags["i"] == i
243244

244245
return response.text("ok")
245246

@@ -328,8 +329,8 @@ async def runner():
328329
else:
329330
asyncio.run(runner())
330331

331-
with configure_scope() as scope:
332-
assert not scope._tags
332+
scope = Scope.get_isolation_scope()
333+
assert not scope._tags
333334

334335

335336
class TransactionTestConfig:

0 commit comments

Comments
 (0)