diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index eb862f218f..994ae4c348 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -2,12 +2,17 @@ import contextlib from typing import Any, TypeVar, Callable, Awaitable, Iterator -from sentry_sdk import Hub +import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import add_query_source, record_sql_queries -from sentry_sdk.utils import parse_version, capture_internal_exceptions +from sentry_sdk.utils import ( + ensure_integration_enabled, + ensure_integration_enabled_async, + parse_version, + capture_internal_exceptions, +) try: import asyncpg # type: ignore[import-not-found] @@ -54,8 +59,7 @@ def setup_once() -> None: def _wrap_execute(f: Callable[..., Awaitable[T]]) -> Callable[..., Awaitable[T]]: async def _inner(*args: Any, **kwargs: Any) -> T: - hub = Hub.current - integration = hub.get_integration(AsyncPGIntegration) + integration = sentry_sdk.get_client().get_integration(AsyncPGIntegration) # Avoid recording calls to _execute twice. # Calls to Connection.execute with args also call @@ -65,13 +69,11 @@ async def _inner(*args: Any, **kwargs: Any) -> T: return await f(*args, **kwargs) query = args[1] - with record_sql_queries( - hub, None, query, None, None, executemany=False - ) as span: + with record_sql_queries(None, query, None, None, executemany=False) as span: res = await f(*args, **kwargs) with capture_internal_exceptions(): - add_query_source(hub, span) + add_query_source(span) return res @@ -83,21 +85,19 @@ async def _inner(*args: Any, **kwargs: Any) -> T: @contextlib.contextmanager def _record( - hub: Hub, cursor: SubCursor | None, query: str, params_list: tuple[Any, ...] | None, *, executemany: bool = False, ) -> Iterator[Span]: - integration = hub.get_integration(AsyncPGIntegration) - if not integration._record_params: + integration = sentry_sdk.get_client().get_integration(AsyncPGIntegration) + if integration is not None and not integration._record_params: params_list = None param_style = "pyformat" if params_list else None with record_sql_queries( - hub, cursor, query, params_list, @@ -111,16 +111,11 @@ def _record( def _wrap_connection_method( f: Callable[..., Awaitable[T]], *, executemany: bool = False ) -> Callable[..., Awaitable[T]]: + @ensure_integration_enabled_async(AsyncPGIntegration, f) async def _inner(*args: Any, **kwargs: Any) -> T: - hub = Hub.current - integration = hub.get_integration(AsyncPGIntegration) - - if integration is None: - return await f(*args, **kwargs) - query = args[1] params_list = args[2] if len(args) > 2 else None - with _record(hub, None, query, params_list, executemany=executemany) as span: + with _record(None, query, params_list, executemany=executemany) as span: _set_db_data(span, args[0]) res = await f(*args, **kwargs) @@ -130,18 +125,12 @@ async def _inner(*args: Any, **kwargs: Any) -> T: def _wrap_cursor_creation(f: Callable[..., T]) -> Callable[..., T]: + @ensure_integration_enabled(AsyncPGIntegration, f) def _inner(*args: Any, **kwargs: Any) -> T: # noqa: N807 - hub = Hub.current - integration = hub.get_integration(AsyncPGIntegration) - - if integration is None: - return f(*args, **kwargs) - query = args[1] params_list = args[2] if len(args) > 2 else None with _record( - hub, None, query, params_list, @@ -157,17 +146,12 @@ def _inner(*args: Any, **kwargs: Any) -> T: # noqa: N807 def _wrap_connect_addr(f: Callable[..., Awaitable[T]]) -> Callable[..., Awaitable[T]]: + @ensure_integration_enabled_async(AsyncPGIntegration, f) async def _inner(*args: Any, **kwargs: Any) -> T: - hub = Hub.current - integration = hub.get_integration(AsyncPGIntegration) - - if integration is None: - return await f(*args, **kwargs) - user = kwargs["params"].user database = kwargs["params"].database - with hub.start_span(op=OP.DB, description="connect") as span: + with sentry_sdk.start_span(op=OP.DB, description="connect") as span: span.set_data(SPANDATA.DB_SYSTEM, "postgresql") addr = kwargs.get("addr") if addr: @@ -180,7 +164,9 @@ async def _inner(*args: Any, **kwargs: Any) -> T: span.set_data(SPANDATA.DB_USER, user) with capture_internal_exceptions(): - hub.add_breadcrumb(message="connect", category="query", data=span._data) + sentry_sdk.add_breadcrumb( + message="connect", category="query", data=span._data + ) res = await f(*args, **kwargs) return res diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 8f2d608464..1683804e48 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -4,11 +4,11 @@ import weakref from importlib import import_module +import sentry_sdk from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.db.explain_plan.django import attach_explain_plan_to_span -from sentry_sdk.hub import Hub, _should_send_default_pii -from sentry_sdk.scope import Scope, add_global_event_processor +from sentry_sdk.scope import Scope, add_global_event_processor, should_send_default_pii from sentry_sdk.serializer import add_global_repr_processor from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_URL from sentry_sdk.tracing_utils import add_query_source, record_sql_queries @@ -19,6 +19,7 @@ SENSITIVE_DATA_SUBSTITUTE, logger, capture_internal_exceptions, + ensure_integration_enabled, event_from_exception, transaction_from_function, walk_exception_chain, @@ -146,11 +147,9 @@ def setup_once(): old_app = WSGIHandler.__call__ + @ensure_integration_enabled(DjangoIntegration, old_app) def sentry_patched_wsgi_handler(self, environ, start_response): # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse - if Hub.current.get_integration(DjangoIntegration) is None: - return old_app(self, environ, start_response) - bound_old_app = old_app.__get__(self, WSGIHandler) from django.conf import settings @@ -229,11 +228,6 @@ def _django_queryset_repr(value, hint): if not isinstance(value, QuerySet) or value._result_cache: return NotImplemented - # Do not call Hub.get_integration here. It is intentional that - # running under a new hub does not suddenly start executing - # querysets. This might be surprising to the user but it's likely - # less annoying. - return "<%s from %s at 0x%x>" % ( value.__class__.__name__, value.__module__, @@ -400,8 +394,8 @@ def _set_transaction_name_and_source(scope, transaction_style, request): def _before_get_response(request): # type: (WSGIRequest) -> None - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) + if integration is None: return @@ -431,8 +425,7 @@ def _attempt_resolve_again(request, scope, transaction_style): def _after_get_response(request): # type: (WSGIRequest) -> None - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is None or integration.transaction_style != "url": return @@ -490,7 +483,7 @@ def wsgi_request_event_processor(event, hint): with capture_internal_exceptions(): DjangoRequestExtractor(request).extract_into_event(event) - if _should_send_default_pii(): + if should_send_default_pii(): with capture_internal_exceptions(): _set_user_info(request, event) @@ -501,22 +494,19 @@ def wsgi_request_event_processor(event, hint): def _got_request_exception(request=None, **kwargs): # type: (WSGIRequest, **Any) -> None - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) + client = sentry_sdk.get_client() + integration = client.get_integration(DjangoIntegration) if integration is not None: if request is not None and integration.transaction_style == "url": scope = Scope.get_current_scope() _attempt_resolve_again(request, scope, integration.transaction_style) - # If an integration is there, a client has to be there. - client = hub.client # type: Any - event, hint = event_from_exception( sys.exc_info(), client_options=client.options, mechanism={"type": "django", "handled": False}, ) - hub.capture_event(event, hint=hint) + sentry_sdk.capture_event(event, hint=hint) class DjangoRequestExtractor(RequestExtractor): @@ -612,62 +602,56 @@ def install_sql_hook(): # This won't work on Django versions < 1.6 return + @ensure_integration_enabled(DjangoIntegration, real_execute) def execute(self, sql, params=None): # type: (CursorWrapper, Any, Optional[Any]) -> Any - hub = Hub.current - if hub.get_integration(DjangoIntegration) is None: - return real_execute(self, sql, params) - with record_sql_queries( - hub, self.cursor, sql, params, paramstyle="format", executemany=False + self.cursor, sql, params, paramstyle="format", executemany=False ) as span: _set_db_data(span, self) - if hub.client: - options = hub.client.options["_experiments"].get("attach_explain_plans") - if options is not None: - attach_explain_plan_to_span( - span, - self.cursor.connection, - sql, - params, - self.mogrify, - options, - ) + options = ( + sentry_sdk.get_client() + .options["_experiments"] + .get("attach_explain_plans") + ) + if options is not None: + attach_explain_plan_to_span( + span, + self.cursor.connection, + sql, + params, + self.mogrify, + options, + ) result = real_execute(self, sql, params) with capture_internal_exceptions(): - add_query_source(hub, span) + add_query_source(span) return result + @ensure_integration_enabled(DjangoIntegration, real_executemany) def executemany(self, sql, param_list): # type: (CursorWrapper, Any, List[Any]) -> Any - hub = Hub.current - if hub.get_integration(DjangoIntegration) is None: - return real_executemany(self, sql, param_list) - with record_sql_queries( - hub, self.cursor, sql, param_list, paramstyle="format", executemany=True + self.cursor, sql, param_list, paramstyle="format", executemany=True ) as span: _set_db_data(span, self) result = real_executemany(self, sql, param_list) with capture_internal_exceptions(): - add_query_source(hub, span) + add_query_source(span) return result + @ensure_integration_enabled(DjangoIntegration, real_connect) def connect(self): # type: (BaseDatabaseWrapper) -> None - hub = Hub.current - if hub.get_integration(DjangoIntegration) is None: - return real_connect(self) - with capture_internal_exceptions(): - hub.add_breadcrumb(message="connect", category="query") + sentry_sdk.add_breadcrumb(message="connect", category="query") - with hub.start_span(op=OP.DB, description="connect") as span: + with sentry_sdk.start_span(op=OP.DB, description="connect") as span: _set_db_data(span, self) return real_connect(self) @@ -679,7 +663,6 @@ def connect(self): def _set_db_data(span, cursor_or_db): # type: (Span, Any) -> None - db = cursor_or_db.db if hasattr(cursor_or_db, "db") else cursor_or_db vendor = db.vendor span.set_data(SPANDATA.DB_SYSTEM, vendor) diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index 44c992f501..bb060b1de2 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -11,13 +11,18 @@ from django.core.handlers.wsgi import WSGIRequest -from sentry_sdk import Hub +import sentry_sdk +from sentry_sdk import Scope from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import OP -from sentry_sdk.hub import _should_send_default_pii from sentry_sdk.integrations.asgi import SentryAsgiMiddleware -from sentry_sdk.utils import capture_internal_exceptions +from sentry_sdk.scope import should_send_default_pii +from sentry_sdk.utils import ( + capture_internal_exceptions, + ensure_integration_enabled, + ensure_integration_enabled_async, +) if TYPE_CHECKING: @@ -51,7 +56,7 @@ def asgi_request_event_processor(event, hint): with capture_internal_exceptions(): DjangoRequestExtractor(request).extract_into_event(event) - if _should_send_default_pii(): + if should_send_default_pii(): with capture_internal_exceptions(): _set_user_info(request, event) @@ -67,13 +72,9 @@ def patch_django_asgi_handler_impl(cls): old_app = cls.__call__ + @ensure_integration_enabled_async(DjangoIntegration, old_app) async def sentry_patched_asgi_handler(self, scope, receive, send): # type: (Any, Any, Any, Any) -> Any - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) - if integration is None: - return await old_app(self, scope, receive, send) - middleware = SentryAsgiMiddleware( old_app.__get__(self, cls), unsafe_context_data=True )._run_asgi3 @@ -86,18 +87,14 @@ async def sentry_patched_asgi_handler(self, scope, receive, send): if modern_django_asgi_support: old_create_request = cls.create_request + @ensure_integration_enabled(DjangoIntegration, old_create_request) def sentry_patched_create_request(self, *args, **kwargs): # type: (Any, *Any, **Any) -> Any - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) - if integration is None: - return old_create_request(self, *args, **kwargs) - - with hub.configure_scope() as scope: - request, error_response = old_create_request(self, *args, **kwargs) - scope.add_event_processor(_make_asgi_request_event_processor(request)) + request, error_response = old_create_request(self, *args, **kwargs) + scope = Scope.get_isolation_scope() + scope.add_event_processor(_make_asgi_request_event_processor(request)) - return request, error_response + return request, error_response cls.create_request = sentry_patched_create_request @@ -123,11 +120,9 @@ def patch_channels_asgi_handler_impl(cls): if channels.__version__ < "3.0.0": old_app = cls.__call__ + @ensure_integration_enabled_async(DjangoIntegration, old_app) async def sentry_patched_asgi_handler(self, receive, send): # type: (Any, Any, Any) -> Any - if Hub.current.get_integration(DjangoIntegration) is None: - return await old_app(self, receive, send) - middleware = SentryAsgiMiddleware( lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True ) @@ -142,20 +137,19 @@ async def sentry_patched_asgi_handler(self, receive, send): patch_django_asgi_handler_impl(cls) -def wrap_async_view(hub, callback): - # type: (Hub, Any) -> Any +def wrap_async_view(callback): + # type: (Any) -> Any @functools.wraps(callback) async def sentry_wrapped_callback(request, *args, **kwargs): # type: (Any, *Any, **Any) -> Any - - with hub.configure_scope() as sentry_scope: - if sentry_scope.profile is not None: - sentry_scope.profile.update_active_thread_id() - - with hub.start_span( - op=OP.VIEW_RENDER, description=request.resolver_match.view_name - ): - return await callback(request, *args, **kwargs) + sentry_scope = Scope.get_isolation_scope() + if sentry_scope.profile is not None: + sentry_scope.profile.update_active_thread_id() + + with sentry_sdk.start_span( + op=OP.VIEW_RENDER, description=request.resolver_match.view_name + ): + return await callback(request, *args, **kwargs) return sentry_wrapped_callback diff --git a/sentry_sdk/integrations/django/caching.py b/sentry_sdk/integrations/django/caching.py index f017304630..1b2bb477b1 100644 --- a/sentry_sdk/integrations/django/caching.py +++ b/sentry_sdk/integrations/django/caching.py @@ -4,8 +4,9 @@ from django import VERSION as DJANGO_VERSION from django.core.cache import CacheHandler -from sentry_sdk import Hub +import sentry_sdk from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.utils import ensure_integration_enabled if TYPE_CHECKING: @@ -35,16 +36,16 @@ def _patch_cache_method(cache, method_name): # type: (CacheHandler, str) -> None from sentry_sdk.integrations.django import DjangoIntegration + original_method = getattr(cache, method_name) + + @ensure_integration_enabled(DjangoIntegration, original_method) def _instrument_call(cache, method_name, original_method, args, kwargs): # type: (CacheHandler, str, Callable[..., Any], Any, Any) -> Any - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) - if integration is None or not integration.cache_spans: - return original_method(*args, **kwargs) - description = _get_span_description(method_name, args, kwargs) - with hub.start_span(op=OP.CACHE_GET_ITEM, description=description) as span: + with sentry_sdk.start_span( + op=OP.CACHE_GET_ITEM, description=description + ) as span: value = original_method(*args, **kwargs) if value: @@ -58,8 +59,6 @@ def _instrument_call(cache, method_name, original_method, args, kwargs): return value - original_method = getattr(cache, method_name) - @functools.wraps(original_method) def sentry_method(*args, **kwargs): # type: (*Any, **Any) -> Any @@ -89,8 +88,8 @@ def sentry_get_item(self, alias): # type: (CacheHandler, str) -> Any cache = original_get_item(self, alias) - integration = Hub.current.get_integration(DjangoIntegration) - if integration and integration.cache_spans: + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) + if integration is not None and integration.cache_spans: _patch_cache(cache) return cache @@ -106,8 +105,8 @@ def sentry_create_connection(self, alias): # type: (CacheHandler, str) -> Any cache = original_create_connection(self, alias) - integration = Hub.current.get_integration(DjangoIntegration) - if integration and integration.cache_spans: + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) + if integration is not None and integration.cache_spans: _patch_cache(cache) return cache diff --git a/sentry_sdk/integrations/django/middleware.py b/sentry_sdk/integrations/django/middleware.py index 086fd68b28..9d191ce076 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -6,7 +6,7 @@ from django import VERSION as DJANGO_VERSION -from sentry_sdk import Hub +import sentry_sdk from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import OP from sentry_sdk.utils import ( @@ -71,8 +71,7 @@ def _wrap_middleware(middleware, middleware_name): def _check_middleware_span(old_method): # type: (Callable[..., Any]) -> Optional[Span] - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is None or not integration.middleware_spans: return None @@ -83,7 +82,7 @@ def _check_middleware_span(old_method): if function_basename: description = "{}.{}".format(description, function_basename) - middleware_span = hub.start_span( + middleware_span = sentry_sdk.start_span( op=OP.MIDDLEWARE_DJANGO, description=description ) middleware_span.set_tag("django.function_name", function_name) diff --git a/sentry_sdk/integrations/django/signals_handlers.py b/sentry_sdk/integrations/django/signals_handlers.py index 40fdd9c2f0..f974805f97 100644 --- a/sentry_sdk/integrations/django/signals_handlers.py +++ b/sentry_sdk/integrations/django/signals_handlers.py @@ -2,7 +2,7 @@ from django.dispatch import Signal -from sentry_sdk import Hub +import sentry_sdk from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import OP from sentry_sdk.integrations.django import DJANGO_VERSION @@ -52,8 +52,6 @@ def patch_signals(): def _sentry_live_receivers(self, sender): # type: (Signal, Any) -> Union[tuple[list[Callable[..., Any]], list[Callable[..., Any]]], list[Callable[..., Any]]] - hub = Hub.current - if DJANGO_VERSION >= (5, 0): sync_receivers, async_receivers = old_live_receivers(self, sender) else: @@ -66,7 +64,7 @@ def sentry_sync_receiver_wrapper(receiver): def wrapper(*args, **kwargs): # type: (Any, Any) -> Any signal_name = _get_receiver_name(receiver) - with hub.start_span( + with sentry_sdk.start_span( op=OP.EVENT_DJANGO, description=signal_name, ) as span: @@ -75,7 +73,7 @@ def wrapper(*args, **kwargs): return wrapper - integration = hub.get_integration(DjangoIntegration) + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration and integration.signals_spans: for idx, receiver in enumerate(sync_receivers): sync_receivers[idx] = sentry_sync_receiver_wrapper(receiver) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 885ba21860..15ea0e1b99 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -4,9 +4,11 @@ from django.utils.safestring import mark_safe from django import VERSION as DJANGO_VERSION -from sentry_sdk import Hub +import sentry_sdk +from sentry_sdk import Scope from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import OP +from sentry_sdk.utils import ensure_integration_enabled if TYPE_CHECKING: from typing import Any @@ -65,11 +67,10 @@ def patch_templates(): @property # type: ignore def rendered_content(self): # type: (SimpleTemplateResponse) -> str - hub = Hub.current - if hub.get_integration(DjangoIntegration) is None: + if sentry_sdk.get_client().get_integration(DjangoIntegration) is None: return real_rendered_content.fget(self) - with hub.start_span( + with sentry_sdk.start_span( op=OP.TEMPLATE_RENDER, description=_get_template_name_description(self.template_name), ) as span: @@ -85,18 +86,18 @@ def rendered_content(self): real_render = django.shortcuts.render @functools.wraps(real_render) + @ensure_integration_enabled(DjangoIntegration, real_render) def render(request, template_name, context=None, *args, **kwargs): # type: (django.http.HttpRequest, str, Optional[Dict[str, Any]], *Any, **Any) -> django.http.HttpResponse - hub = Hub.current - if hub.get_integration(DjangoIntegration) is None: - return real_render(request, template_name, context, *args, **kwargs) # Inject trace meta tags into template context context = context or {} if "sentry_trace_meta" not in context: - context["sentry_trace_meta"] = mark_safe(hub.trace_propagation_meta()) + context["sentry_trace_meta"] = mark_safe( + Scope.get_current_scope().trace_propagation_meta() + ) - with hub.start_span( + with sentry_sdk.start_span( op=OP.TEMPLATE_RENDER, description=_get_template_name_description(template_name), ) as span: diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py index 2e3d539a62..1fd53462b3 100644 --- a/sentry_sdk/integrations/django/views.py +++ b/sentry_sdk/integrations/django/views.py @@ -1,7 +1,8 @@ import functools +import sentry_sdk +from sentry_sdk import Scope from sentry_sdk.consts import OP -from sentry_sdk.hub import Hub from sentry_sdk._types import TYPE_CHECKING if TYPE_CHECKING: @@ -32,8 +33,7 @@ def patch_views(): def sentry_patched_render(self): # type: (SimpleTemplateResponse) -> Any - hub = Hub.current - with hub.start_span( + with sentry_sdk.start_span( op=OP.VIEW_RESPONSE_RENDER, description="serialize response" ): return old_render(self) @@ -46,8 +46,7 @@ def sentry_patched_make_view_atomic(self, *args, **kwargs): # XXX: The wrapper function is created for every request. Find more # efficient way to wrap views (or build a cache?) - hub = Hub.current - integration = hub.get_integration(DjangoIntegration) + integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is not None and integration.middleware_spans: is_async_view = ( iscoroutinefunction is not None @@ -55,9 +54,9 @@ def sentry_patched_make_view_atomic(self, *args, **kwargs): and iscoroutinefunction(callback) ) if is_async_view: - sentry_wrapped_callback = wrap_async_view(hub, callback) + sentry_wrapped_callback = wrap_async_view(callback) else: - sentry_wrapped_callback = _wrap_sync_view(hub, callback) + sentry_wrapped_callback = _wrap_sync_view(callback) else: sentry_wrapped_callback = callback @@ -68,20 +67,20 @@ def sentry_patched_make_view_atomic(self, *args, **kwargs): BaseHandler.make_view_atomic = sentry_patched_make_view_atomic -def _wrap_sync_view(hub, callback): - # type: (Hub, Any) -> Any +def _wrap_sync_view(callback): + # type: (Any) -> Any @functools.wraps(callback) def sentry_wrapped_callback(request, *args, **kwargs): # type: (Any, *Any, **Any) -> Any - with hub.configure_scope() as sentry_scope: - # set the active thread id to the handler thread for sync views - # this isn't necessary for async views since that runs on main - if sentry_scope.profile is not None: - sentry_scope.profile.update_active_thread_id() - - with hub.start_span( - op=OP.VIEW_RENDER, description=request.resolver_match.view_name - ): - return callback(request, *args, **kwargs) + sentry_scope = Scope.get_isolation_scope() + # set the active thread id to the handler thread for sync views + # this isn't necessary for async views since that runs on main + if sentry_scope.profile is not None: + sentry_scope.profile.update_active_thread_id() + + with sentry_sdk.start_span( + op=OP.VIEW_RENDER, description=request.resolver_match.view_name + ): + return callback(request, *args, **kwargs) return sentry_wrapped_callback diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 109c73b2e8..c766019e68 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -1,7 +1,7 @@ +import sentry_sdk from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.consts import SPANDATA from sentry_sdk.db.explain_plan.sqlalchemy import attach_explain_plan_to_span -from sentry_sdk.hub import Hub from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.tracing_utils import add_query_source, record_sql_queries from sentry_sdk.utils import capture_internal_exceptions, parse_version @@ -47,12 +47,10 @@ def _before_cursor_execute( conn, cursor, statement, parameters, context, executemany, *args ): # type: (Any, Any, Any, Any, Any, bool, *Any) -> None - hub = Hub.current - if hub.get_integration(SqlalchemyIntegration) is None: + if sentry_sdk.get_client().get_integration(SqlalchemyIntegration) is None: return ctx_mgr = record_sql_queries( - hub, cursor, statement, parameters, @@ -65,23 +63,23 @@ def _before_cursor_execute( if span is not None: _set_db_data(span, conn) - if hub.client: - options = hub.client.options["_experiments"].get("attach_explain_plans") - if options is not None: - attach_explain_plan_to_span( - span, - conn, - statement, - parameters, - options, - ) + options = ( + sentry_sdk.get_client().options["_experiments"].get("attach_explain_plans") + ) + if options is not None: + attach_explain_plan_to_span( + span, + conn, + statement, + parameters, + options, + ) context._sentry_sql_span = span def _after_cursor_execute(conn, cursor, statement, parameters, context, *args): # type: (Any, Any, Any, Any, Any, *Any) -> None - hub = Hub.current - if hub.get_integration(SqlalchemyIntegration) is None: + if sentry_sdk.get_client().get_integration(SqlalchemyIntegration) is None: return ctx_mgr = getattr( @@ -95,7 +93,7 @@ def _after_cursor_execute(conn, cursor, statement, parameters, context, *args): span = getattr(context, "_sentry_sql_span", None) # type: Optional[Span] if span is not None: with capture_internal_exceptions(): - add_query_source(hub, span) + add_query_source(span) def _handle_error(context, *args): diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index b2df88479a..d39e261497 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -105,7 +105,6 @@ def has_tracing_enabled(options): @contextlib.contextmanager def record_sql_queries( - hub, # type: sentry_sdk.Hub cursor, # type: Any query, # type: Any params_list, # type: Any @@ -116,9 +115,7 @@ def record_sql_queries( # type: (...) -> Generator[sentry_sdk.tracing.Span, None, None] # TODO: Bring back capturing of params by default - if hub.client and hub.client.options["_experiments"].get( - "record_sql_params", False - ): + if sentry_sdk.get_client().options["_experiments"].get("record_sql_params", False): if not params_list or params_list == [None]: params_list = None @@ -141,9 +138,9 @@ def record_sql_queries( data["db.cursor"] = cursor with capture_internal_exceptions(): - hub.add_breadcrumb(message=query, category="query", data=data) + sentry_sdk.add_breadcrumb(message=query, category="query", data=data) - with hub.start_span(op=OP.DB, description=query) as span: + with sentry_sdk.start_span(op=OP.DB, description=query) as span: for k, v in data.items(): span.set_data(k, v) yield span @@ -167,12 +164,12 @@ def maybe_create_breadcrumbs_from_span(scope, span): ) -def add_query_source(hub, span): - # type: (sentry_sdk.Hub, sentry_sdk.tracing.Span) -> None +def add_query_source(span): + # type: (sentry_sdk.tracing.Span) -> None """ Adds OTel compatible source code information to the span """ - client = sentry_sdk.Scope.get_client() + client = sentry_sdk.get_client() if not client.is_active(): return diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index 5bce71a367..a2b0595eb7 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -177,10 +177,17 @@ def template_test2(request, *args, **kwargs): @csrf_exempt def template_test3(request, *args, **kwargs): - from sentry_sdk import Hub + from sentry_sdk import Scope - hub = Hub.current - capture_message(hub.get_traceparent() + "\n" + hub.get_baggage()) + traceparent = Scope.get_current_scope().get_traceparent() + if traceparent is None: + traceparent = Scope.get_isolation_scope().get_traceparent() + + baggage = Scope.get_current_scope().get_baggage() + if baggage is None: + baggage = Scope.get_isolation_scope().get_baggage() + + capture_message(traceparent + "\n" + baggage.serialize()) return render(request, "trace_meta.html", {})