Skip to content

Commit 05a713c

Browse files
authored
ref(starlette): Use new scopes API (#2877)
1 parent f416845 commit 05a713c

File tree

2 files changed

+121
-133
lines changed

2 files changed

+121
-133
lines changed

sentry_sdk/integrations/starlette.py

Lines changed: 119 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
import functools
33
from copy import deepcopy
44

5+
import sentry_sdk
56
from sentry_sdk._types import TYPE_CHECKING
67
from sentry_sdk.consts import OP
7-
from sentry_sdk.hub import Hub, _should_send_default_pii
88
from sentry_sdk.integrations import DidNotEnable, Integration
99
from sentry_sdk.integrations._wsgi_common import (
1010
_is_json_content_type,
1111
request_body_within_bounds,
1212
)
1313
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
14-
from sentry_sdk.scope import Scope
14+
from sentry_sdk.scope import Scope, should_send_default_pii
1515
from sentry_sdk.tracing import (
1616
SOURCE_FOR_STYLE,
1717
TRANSACTION_SOURCE_COMPONENT,
@@ -20,6 +20,7 @@
2020
from sentry_sdk.utils import (
2121
AnnotatedValue,
2222
capture_internal_exceptions,
23+
ensure_integration_enabled,
2324
event_from_exception,
2425
logger,
2526
parse_version,
@@ -29,7 +30,6 @@
2930
if TYPE_CHECKING:
3031
from typing import Any, Awaitable, Callable, Dict, Optional, Tuple
3132

32-
from sentry_sdk.scope import Scope as SentryScope
3333
from sentry_sdk._types import Event
3434

3535
try:
@@ -104,58 +104,54 @@ def _enable_span_for_middleware(middleware_class):
104104

105105
async def _create_span_call(app, scope, receive, send, **kwargs):
106106
# type: (Any, Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]], Any) -> None
107-
hub = Hub.current
108-
integration = hub.get_integration(StarletteIntegration)
109-
if integration is not None:
110-
middleware_name = app.__class__.__name__
111-
112-
# Update transaction name with middleware name
113-
name, source = _get_transaction_from_middleware(app, scope, integration)
114-
if name is not None:
115-
Scope.get_current_scope().set_transaction_name(
116-
name,
117-
source=source,
118-
)
107+
integration = sentry_sdk.get_client().get_integration(StarletteIntegration)
108+
if integration is None:
109+
return await old_call(app, scope, receive, send, **kwargs)
119110

120-
with hub.start_span(
121-
op=OP.MIDDLEWARE_STARLETTE, description=middleware_name
122-
) as middleware_span:
123-
middleware_span.set_tag("starlette.middleware_name", middleware_name)
124-
125-
# Creating spans for the "receive" callback
126-
async def _sentry_receive(*args, **kwargs):
127-
# type: (*Any, **Any) -> Any
128-
hub = Hub.current
129-
with hub.start_span(
130-
op=OP.MIDDLEWARE_STARLETTE_RECEIVE,
131-
description=getattr(receive, "__qualname__", str(receive)),
132-
) as span:
133-
span.set_tag("starlette.middleware_name", middleware_name)
134-
return await receive(*args, **kwargs)
135-
136-
receive_name = getattr(receive, "__name__", str(receive))
137-
receive_patched = receive_name == "_sentry_receive"
138-
new_receive = _sentry_receive if not receive_patched else receive
139-
140-
# Creating spans for the "send" callback
141-
async def _sentry_send(*args, **kwargs):
142-
# type: (*Any, **Any) -> Any
143-
hub = Hub.current
144-
with hub.start_span(
145-
op=OP.MIDDLEWARE_STARLETTE_SEND,
146-
description=getattr(send, "__qualname__", str(send)),
147-
) as span:
148-
span.set_tag("starlette.middleware_name", middleware_name)
149-
return await send(*args, **kwargs)
150-
151-
send_name = getattr(send, "__name__", str(send))
152-
send_patched = send_name == "_sentry_send"
153-
new_send = _sentry_send if not send_patched else send
154-
155-
return await old_call(app, scope, new_receive, new_send, **kwargs)
111+
middleware_name = app.__class__.__name__
156112

157-
else:
158-
return await old_call(app, scope, receive, send, **kwargs)
113+
# Update transaction name with middleware name
114+
name, source = _get_transaction_from_middleware(app, scope, integration)
115+
if name is not None:
116+
Scope.get_current_scope().set_transaction_name(
117+
name,
118+
source=source,
119+
)
120+
121+
with sentry_sdk.start_span(
122+
op=OP.MIDDLEWARE_STARLETTE, description=middleware_name
123+
) as middleware_span:
124+
middleware_span.set_tag("starlette.middleware_name", middleware_name)
125+
126+
# Creating spans for the "receive" callback
127+
async def _sentry_receive(*args, **kwargs):
128+
# type: (*Any, **Any) -> Any
129+
with sentry_sdk.start_span(
130+
op=OP.MIDDLEWARE_STARLETTE_RECEIVE,
131+
description=getattr(receive, "__qualname__", str(receive)),
132+
) as span:
133+
span.set_tag("starlette.middleware_name", middleware_name)
134+
return await receive(*args, **kwargs)
135+
136+
receive_name = getattr(receive, "__name__", str(receive))
137+
receive_patched = receive_name == "_sentry_receive"
138+
new_receive = _sentry_receive if not receive_patched else receive
139+
140+
# Creating spans for the "send" callback
141+
async def _sentry_send(*args, **kwargs):
142+
# type: (*Any, **Any) -> Any
143+
with sentry_sdk.start_span(
144+
op=OP.MIDDLEWARE_STARLETTE_SEND,
145+
description=getattr(send, "__qualname__", str(send)),
146+
) as span:
147+
span.set_tag("starlette.middleware_name", middleware_name)
148+
return await send(*args, **kwargs)
149+
150+
send_name = getattr(send, "__name__", str(send))
151+
send_patched = send_name == "_sentry_send"
152+
new_send = _sentry_send if not send_patched else send
153+
154+
return await old_call(app, scope, new_receive, new_send, **kwargs)
159155

160156
not_yet_patched = old_call.__name__ not in [
161157
"_create_span_call",
@@ -171,17 +167,17 @@ async def _sentry_send(*args, **kwargs):
171167

172168
def _capture_exception(exception, handled=False):
173169
# type: (BaseException, **Any) -> None
174-
hub = Hub.current
175-
if hub.get_integration(StarletteIntegration) is None:
170+
client = sentry_sdk.get_client()
171+
if client.get_integration(StarletteIntegration) is None:
176172
return
177173

178174
event, hint = event_from_exception(
179175
exception,
180-
client_options=hub.client.options if hub.client else None,
176+
client_options=client.options,
181177
mechanism={"type": StarletteIntegration.identifier, "handled": handled},
182178
)
183179

184-
hub.capture_event(event, hint=hint)
180+
sentry_sdk.capture_event(event, hint=hint)
185181

186182

187183
def patch_exception_middleware(middleware_class):
@@ -265,30 +261,29 @@ def _add_user_to_sentry_scope(scope):
265261
if "user" not in scope:
266262
return
267263

268-
if not _should_send_default_pii():
264+
if not should_send_default_pii():
269265
return
270266

271-
hub = Hub.current
272-
if hub.get_integration(StarletteIntegration) is None:
267+
if sentry_sdk.get_client().get_integration(StarletteIntegration) is None:
273268
return
274269

275-
with hub.configure_scope() as sentry_scope:
276-
user_info = {} # type: Dict[str, Any]
277-
starlette_user = scope["user"]
270+
user_info = {} # type: Dict[str, Any]
271+
starlette_user = scope["user"]
278272

279-
username = getattr(starlette_user, "username", None)
280-
if username:
281-
user_info.setdefault("username", starlette_user.username)
273+
username = getattr(starlette_user, "username", None)
274+
if username:
275+
user_info.setdefault("username", starlette_user.username)
282276

283-
user_id = getattr(starlette_user, "id", None)
284-
if user_id:
285-
user_info.setdefault("id", starlette_user.id)
277+
user_id = getattr(starlette_user, "id", None)
278+
if user_id:
279+
user_info.setdefault("id", starlette_user.id)
286280

287-
email = getattr(starlette_user, "email", None)
288-
if email:
289-
user_info.setdefault("email", starlette_user.email)
281+
email = getattr(starlette_user, "email", None)
282+
if email:
283+
user_info.setdefault("email", starlette_user.email)
290284

291-
sentry_scope.user = user_info
285+
sentry_scope = Scope.get_isolation_scope()
286+
sentry_scope.user = user_info
292287

293288

294289
def patch_authentication_middleware(middleware_class):
@@ -348,7 +343,7 @@ def patch_asgi_app():
348343

349344
async def _sentry_patched_asgi_app(self, scope, receive, send):
350345
# type: (Starlette, StarletteScope, Receive, Send) -> None
351-
integration = Hub.current.get_integration(StarletteIntegration)
346+
integration = sentry_sdk.get_client().get_integration(StarletteIntegration)
352347
if integration is None:
353348
return await old_app(self, scope, receive, send)
354349

@@ -389,8 +384,9 @@ def _sentry_request_response(func):
389384

390385
async def _sentry_async_func(*args, **kwargs):
391386
# type: (*Any, **Any) -> Any
392-
hub = Hub.current
393-
integration = hub.get_integration(StarletteIntegration)
387+
integration = sentry_sdk.get_client().get_integration(
388+
StarletteIntegration
389+
)
394390
if integration is None:
395391
return await old_func(*args, **kwargs)
396392

@@ -400,27 +396,27 @@ async def _sentry_async_func(*args, **kwargs):
400396
Scope.get_current_scope(), integration.transaction_style, request
401397
)
402398

403-
with hub.configure_scope() as sentry_scope:
404-
extractor = StarletteRequestExtractor(request)
405-
info = await extractor.extract_request_info()
399+
sentry_scope = Scope.get_isolation_scope()
400+
extractor = StarletteRequestExtractor(request)
401+
info = await extractor.extract_request_info()
406402

407-
def _make_request_event_processor(req, integration):
408-
# type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event]
409-
def event_processor(event, hint):
410-
# type: (Event, Dict[str, Any]) -> Event
403+
def _make_request_event_processor(req, integration):
404+
# type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event]
405+
def event_processor(event, hint):
406+
# type: (Event, Dict[str, Any]) -> Event
411407

412-
# Add info from request to event
413-
request_info = event.get("request", {})
414-
if info:
415-
if "cookies" in info:
416-
request_info["cookies"] = info["cookies"]
417-
if "data" in info:
418-
request_info["data"] = info["data"]
419-
event["request"] = deepcopy(request_info)
408+
# Add info from request to event
409+
request_info = event.get("request", {})
410+
if info:
411+
if "cookies" in info:
412+
request_info["cookies"] = info["cookies"]
413+
if "data" in info:
414+
request_info["data"] = info["data"]
415+
event["request"] = deepcopy(request_info)
420416

421-
return event
417+
return event
422418

423-
return event_processor
419+
return event_processor
424420

425421
sentry_scope._name = StarletteIntegration.identifier
426422
sentry_scope.add_event_processor(
@@ -430,43 +426,44 @@ def event_processor(event, hint):
430426
return await old_func(*args, **kwargs)
431427

432428
func = _sentry_async_func
429+
433430
else:
434431

432+
@ensure_integration_enabled(StarletteIntegration, old_func)
435433
def _sentry_sync_func(*args, **kwargs):
436434
# type: (*Any, **Any) -> Any
437-
hub = Hub.current
438-
integration = hub.get_integration(StarletteIntegration)
439-
if integration is None:
440-
return old_func(*args, **kwargs)
435+
integration = sentry_sdk.get_client().get_integration(
436+
StarletteIntegration
437+
)
438+
sentry_scope = Scope.get_isolation_scope()
441439

442-
with hub.configure_scope() as sentry_scope:
443-
if sentry_scope.profile is not None:
444-
sentry_scope.profile.update_active_thread_id()
440+
if sentry_scope.profile is not None:
441+
sentry_scope.profile.update_active_thread_id()
445442

446-
request = args[0]
443+
request = args[0]
447444

448-
_set_transaction_name_and_source(
449-
sentry_scope, integration.transaction_style, request
450-
)
445+
_set_transaction_name_and_source(
446+
sentry_scope, integration.transaction_style, request
447+
)
451448

452-
extractor = StarletteRequestExtractor(request)
453-
cookies = extractor.extract_cookies_from_request()
449+
extractor = StarletteRequestExtractor(request)
450+
cookies = extractor.extract_cookies_from_request()
454451

455-
def _make_request_event_processor(req, integration):
456-
# type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event]
457-
def event_processor(event, hint):
458-
# type: (Event, dict[str, Any]) -> Event
452+
def _make_request_event_processor(req, integration):
453+
# type: (Any, Any) -> Callable[[Event, dict[str, Any]], Event]
454+
def event_processor(event, hint):
455+
# type: (Event, dict[str, Any]) -> Event
459456

460-
# Extract information from request
461-
request_info = event.get("request", {})
462-
if cookies:
463-
request_info["cookies"] = cookies
457+
# Extract information from request
458+
request_info = event.get("request", {})
459+
if cookies:
460+
request_info["cookies"] = cookies
464461

465-
event["request"] = deepcopy(request_info)
462+
event["request"] = deepcopy(request_info)
466463

467-
return event
464+
return event
468465

469-
return event_processor
466+
return event_processor
470467

471468
sentry_scope._name = StarletteIntegration.identifier
472469
sentry_scope.add_event_processor(
@@ -507,8 +504,7 @@ def _sentry_jinja2templates_init(self, *args, **kwargs):
507504
# type: (Jinja2Templates, *Any, **Any) -> None
508505
def add_sentry_trace_meta(request):
509506
# type: (Request) -> Dict[str, Any]
510-
hub = Hub.current
511-
trace_meta = Markup(hub.trace_propagation_meta())
507+
trace_meta = Markup(Scope.get_current_scope().trace_propagation_meta())
512508
return {
513509
"sentry_trace_meta": trace_meta,
514510
}
@@ -537,27 +533,21 @@ def __init__(self, request):
537533

538534
def extract_cookies_from_request(self):
539535
# type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]]
540-
client = Hub.current.client
541-
if client is None:
542-
return None
543-
544536
cookies = None # type: Optional[Dict[str, Any]]
545-
if _should_send_default_pii():
537+
if should_send_default_pii():
546538
cookies = self.cookies()
547539

548540
return cookies
549541

550542
async def extract_request_info(self):
551543
# type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]]
552-
client = Hub.current.client
553-
if client is None:
554-
return None
544+
client = sentry_sdk.get_client()
555545

556546
request_info = {} # type: Dict[str, Any]
557547

558548
with capture_internal_exceptions():
559549
# Add cookies
560-
if _should_send_default_pii():
550+
if should_send_default_pii():
561551
request_info["cookies"] = self.cookies()
562552

563553
# If there is no body, just return the cookies
@@ -648,7 +638,7 @@ def _transaction_name_from_router(scope):
648638

649639

650640
def _set_transaction_name_and_source(scope, transaction_style, request):
651-
# type: (SentryScope, str, Any) -> None
641+
# type: (Scope, str, Any) -> None
652642
name = None
653643
source = SOURCE_FOR_STYLE[transaction_style]
654644

0 commit comments

Comments
 (0)