From ebe3b90fe3d8cfc5e2b8b323a0e54118d976f84d Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 13 Aug 2026 13:11:19 +0200 Subject: [PATCH 1/2] . --- sentry_sdk/integrations/django/__init__.py | 185 ++++++------------ sentry_sdk/integrations/django/asgi.py | 44 ++--- sentry_sdk/integrations/django/caching.py | 163 ++++++--------- sentry_sdk/integrations/django/middleware.py | 41 ++-- .../integrations/django/signals_handlers.py | 36 ++-- sentry_sdk/integrations/django/tasks.py | 29 ++- 6 files changed, 167 insertions(+), 331 deletions(-) diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 40ccdae73b..998901530e 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -15,11 +15,9 @@ from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.scope import add_global_event_processor, should_send_default_pii from sentry_sdk.serializer import add_global_repr_processor, add_repr_sequence_type -from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.tracing_utils import ( add_query_source, - has_span_streaming_enabled, record_sql_queries, ) from sentry_sdk.utils import ( @@ -73,7 +71,6 @@ from sentry_sdk._types import Event, EventProcessor, Hint, NotImplementedType from sentry_sdk.integrations.wsgi import _ScopedResponse from sentry_sdk.traces import StreamedSpan - from sentry_sdk.tracing import Span TRANSACTION_STYLE_VALUES = ("function_name", "url") @@ -326,27 +323,21 @@ def sentry_patched_drf_authenticate(self: "Request") -> "Any": integration = client.get_integration(DjangoIntegration) # Nothing to time if there are no authenticators configured # for this view. - if integration is None or not getattr(self, "authenticators", None): + if ( + integration is None + or not getattr(self, "authenticators", None) + or sentry_sdk.traces.get_current_span() is None + ): return old_drf_authenticate(self) - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - return old_drf_authenticate(self) - with sentry_sdk.traces.start_span( - name="authenticate", - attributes={ - "sentry.op": OP.VIEW_AUTHENTICATE, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return old_drf_authenticate(self) - else: - with sentry_sdk.start_span( - op=OP.VIEW_AUTHENTICATE, - name="authenticate", - origin=DjangoIntegration.origin, - ): - return old_drf_authenticate(self) + with sentry_sdk.traces.start_span( + name="authenticate", + attributes={ + "sentry.op": OP.VIEW_AUTHENTICATE, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return old_drf_authenticate(self) Request._authenticate = sentry_patched_drf_authenticate @@ -489,13 +480,11 @@ def _after_get_response(request: "WSGIRequest") -> None: scope = sentry_sdk.get_current_scope() _attempt_resolve_again(request, scope, integration.transaction_style) - span_streaming = has_span_streaming_enabled(client.options) - if span_streaming: - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - _get_user_from_request_and_set_on_scope(request) - elif should_send_default_pii(): + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: _get_user_from_request_and_set_on_scope(request) + elif should_send_default_pii(): + _get_user_from_request_and_set_on_scope(request) def _patch_get_response() -> None: @@ -670,11 +659,6 @@ def execute( _set_db_data(span, self) result = real_execute(self, sql, params) - if isinstance(span, StreamedSpan): - with capture_internal_exceptions(): - add_query_source(span) - - if not isinstance(span, StreamedSpan): with capture_internal_exceptions(): add_query_source(span) @@ -696,11 +680,6 @@ def executemany( result = real_executemany(self, sql, param_list) - if isinstance(span, StreamedSpan): - with capture_internal_exceptions(): - add_query_source(span) - - if not isinstance(span, StreamedSpan): with capture_internal_exceptions(): add_query_source(span) @@ -711,27 +690,17 @@ def connect(self: "BaseDatabaseWrapper") -> None: with capture_internal_exceptions(): sentry_sdk.add_breadcrumb(message="connect", category="query") - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_connect(self) - with sentry_sdk.traces.start_span( - name="connect", - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self) - return real_connect(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name="connect", - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self) - return real_connect(self) + if sentry_sdk.traces.get_current_span() is None: + return real_connect(self) + with sentry_sdk.traces.start_span( + name="connect", + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self) + return real_connect(self) def _commit(self: "BaseDatabaseWrapper") -> None: integration = sentry_sdk.get_client().get_integration(DjangoIntegration) @@ -739,27 +708,18 @@ def _commit(self: "BaseDatabaseWrapper") -> None: if integration is None or not integration.db_transaction_spans: return real_commit(self) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_commit(self) - with sentry_sdk.traces.start_span( - name=SPANNAME.DB_COMMIT, - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self, SPANNAME.DB_COMMIT) - return real_commit(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name=SPANNAME.DB_COMMIT, - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self, SPANNAME.DB_COMMIT) - return real_commit(self) + if sentry_sdk.traces.get_current_span() is None: + return real_commit(self) + + with sentry_sdk.traces.start_span( + name=SPANNAME.DB_COMMIT, + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self, SPANNAME.DB_COMMIT) + return real_commit(self) def _rollback(self: "BaseDatabaseWrapper") -> None: integration = sentry_sdk.get_client().get_integration(DjangoIntegration) @@ -767,27 +727,18 @@ def _rollback(self: "BaseDatabaseWrapper") -> None: if integration is None or not integration.db_transaction_spans: return real_rollback(self) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_rollback(self) - with sentry_sdk.traces.start_span( - name=SPANNAME.DB_ROLLBACK, - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self, SPANNAME.DB_ROLLBACK) - return real_rollback(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name=SPANNAME.DB_ROLLBACK, - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self, SPANNAME.DB_ROLLBACK) - return real_rollback(self) + if sentry_sdk.traces.get_current_span() is None: + return real_rollback(self) + + with sentry_sdk.traces.start_span( + name=SPANNAME.DB_ROLLBACK, + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self, SPANNAME.DB_ROLLBACK) + return real_rollback(self) CursorWrapper.execute = execute CursorWrapper.executemany = executemany @@ -798,22 +749,16 @@ def _rollback(self: "BaseDatabaseWrapper") -> None: def _set_db_data( - span: "Union[Span, StreamedSpan]", + span: "StreamedSpan", cursor_or_db: "Any", db_operation: "Optional[str]" = None, ) -> None: db = cursor_or_db.db if hasattr(cursor_or_db, "db") else cursor_or_db vendor = db.vendor - if isinstance(span, StreamedSpan): - span.set_attribute(SPANDATA.DB_SYSTEM_NAME, vendor) - - if db_operation is not None: - span.set_attribute(SPANDATA.DB_OPERATION_NAME, db_operation) - else: - span.set_data(SPANDATA.DB_SYSTEM, vendor) + span.set_attribute(SPANDATA.DB_SYSTEM_NAME, vendor) - if db_operation is not None: - span.set_data(SPANDATA.DB_OPERATION, db_operation) + if db_operation is not None: + span.set_attribute(SPANDATA.DB_OPERATION_NAME, db_operation) # Some custom backends override `__getattr__`, making it look like `cursor_or_db` # actually has a `connection` and the `connection` has a `get_dsn_parameters` @@ -846,28 +791,20 @@ def _set_db_data( db_name = connection_params.get("dbname") or connection_params.get("database") - if isinstance(span, StreamedSpan): - if db_name is not None: - span.set_attribute(SPANDATA.DB_NAMESPACE, db_name) - - set_on_span = span.set_attribute - else: - if db_name is not None: - span.set_data(SPANDATA.DB_NAME, db_name) - - set_on_span = span.set_data + if db_name is not None: + span.set_attribute(SPANDATA.DB_NAMESPACE, db_name) server_address = connection_params.get("host") if server_address is not None: - set_on_span(SPANDATA.SERVER_ADDRESS, server_address) + span.set_attribute(SPANDATA.SERVER_ADDRESS, server_address) server_port = connection_params.get("port") if server_port is not None: - set_on_span(SPANDATA.SERVER_PORT, str(server_port)) + span.set_attribute(SPANDATA.SERVER_PORT, str(server_port)) server_socket_address = connection_params.get("unix_socket") if server_socket_address is not None: - set_on_span(SPANDATA.SERVER_SOCKET_ADDRESS, server_socket_address) + span.set_attribute(SPANDATA.SERVER_SOCKET_ADDRESS, server_socket_address) def add_template_context_repr_sequence() -> None: diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index 4c5ac57175..fe7857f3b2 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -18,7 +18,6 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -175,39 +174,26 @@ async def sentry_wrapped_callback( request: "Any", *args: "Any", **kwargs: "Any" ) -> "Any": client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - current_scope = sentry_sdk.get_current_scope() - if span_streaming: - current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - segment = current_span._segment - segment._update_active_thread() - else: - if current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + current_span = sentry_sdk.get_current_span() + if type(current_span) is StreamedSpan: + segment = current_span._segment + segment._update_active_thread() integration = client.get_integration(DjangoIntegration) if not integration or not integration.middleware_spans: return await callback(request, *args, **kwargs) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return await callback(request, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=request.resolver_match.view_name, - attributes={ - "sentry.op": OP.VIEW_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return await callback(request, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RENDER, - name=request.resolver_match.view_name, - origin=DjangoIntegration.origin, - ): - return await callback(request, *args, **kwargs) + if current_span is None: + return await callback(request, *args, **kwargs) + + with sentry_sdk.traces.start_span( + name=request.resolver_match.view_name, + attributes={ + "sentry.op": OP.VIEW_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + 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 2cfc0cd2e1..00270097f2 100644 --- a/sentry_sdk/integrations/django/caching.py +++ b/sentry_sdk/integrations/django/caching.py @@ -8,7 +8,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations.redis.utils import _get_safe_key, _key_as_string -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -59,113 +58,61 @@ def _instrument_call( op = OP.CACHE_PUT if is_set_operation else OP.CACHE_GET description = _get_span_description(method_name, args, kwargs) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return original_method(*args, **kwargs) - with sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": op, - "sentry.origin": DjangoIntegration.origin, - }, - ) as span: - value = original_method(*args, **kwargs) - - with capture_internal_exceptions(): - if address is not None: - span.set_attribute(SPANDATA.NETWORK_PEER_ADDRESS, address) - - if port is not None: - span.set_attribute(SPANDATA.NETWORK_PEER_PORT, port) - - key = _get_safe_key(method_name, args, kwargs) - if key is not None: - span.set_attribute(SPANDATA.CACHE_KEY, key) - - item_size = None - if is_get_many_method: - if value != {}: - item_size = len(str(value)) - span.set_attribute(SPANDATA.CACHE_HIT, True) - else: - span.set_attribute(SPANDATA.CACHE_HIT, False) - elif is_get_method: - default_value = None - if len(args) >= 2: - default_value = args[1] - elif "default" in kwargs: - default_value = kwargs["default"] - - if value != default_value: - item_size = len(str(value)) - span.set_attribute(SPANDATA.CACHE_HIT, True) - else: - span.set_attribute(SPANDATA.CACHE_HIT, False) - else: # TODO: We don't handle `get_or_set` which we should - arg_count = len(args) - if arg_count >= 2: - # 'set' command - item_size = len(str(args[1])) - elif arg_count == 1: - # 'set_many' command - item_size = len(str(args[0])) - - if item_size is not None: - span.set_attribute(SPANDATA.CACHE_ITEM_SIZE, item_size) - - return value - else: - with sentry_sdk.start_span( - op=op, - name=description, - origin=DjangoIntegration.origin, - ) as span: - value = original_method(*args, **kwargs) - - with capture_internal_exceptions(): - if address is not None: - span.set_data(SPANDATA.NETWORK_PEER_ADDRESS, address) - - if port is not None: - span.set_data(SPANDATA.NETWORK_PEER_PORT, port) - - key = _get_safe_key(method_name, args, kwargs) - if key is not None: - span.set_data(SPANDATA.CACHE_KEY, key) - - item_size = None - if is_get_many_method: - if value != {}: - item_size = len(str(value)) - span.set_data(SPANDATA.CACHE_HIT, True) - else: - span.set_data(SPANDATA.CACHE_HIT, False) - elif is_get_method: - default_value = None - if len(args) >= 2: - default_value = args[1] - elif "default" in kwargs: - default_value = kwargs["default"] - - if value != default_value: - item_size = len(str(value)) - span.set_data(SPANDATA.CACHE_HIT, True) - else: - span.set_data(SPANDATA.CACHE_HIT, False) - else: # TODO: We don't handle `get_or_set` which we should - arg_count = len(args) - if arg_count >= 2: - # 'set' command - item_size = len(str(args[1])) - elif arg_count == 1: - # 'set_many' command - item_size = len(str(args[0])) - - if item_size is not None: - span.set_data(SPANDATA.CACHE_ITEM_SIZE, item_size) - - return value + if sentry_sdk.traces.get_current_span() is None: + return original_method(*args, **kwargs) + + with sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": op, + "sentry.origin": DjangoIntegration.origin, + }, + ) as span: + value = original_method(*args, **kwargs) + + with capture_internal_exceptions(): + if address is not None: + span.set_attribute(SPANDATA.NETWORK_PEER_ADDRESS, address) + + if port is not None: + span.set_attribute(SPANDATA.NETWORK_PEER_PORT, port) + + key = _get_safe_key(method_name, args, kwargs) + if key is not None: + span.set_attribute(SPANDATA.CACHE_KEY, key) + + item_size = None + if is_get_many_method: + if value != {}: + item_size = len(str(value)) + span.set_attribute(SPANDATA.CACHE_HIT, True) + else: + span.set_attribute(SPANDATA.CACHE_HIT, False) + elif is_get_method: + default_value = None + if len(args) >= 2: + default_value = args[1] + elif "default" in kwargs: + default_value = kwargs["default"] + + if value != default_value: + item_size = len(str(value)) + span.set_attribute(SPANDATA.CACHE_HIT, True) + else: + span.set_attribute(SPANDATA.CACHE_HIT, False) + else: # TODO: We don't handle `get_or_set` which we should + arg_count = len(args) + if arg_count >= 2: + # 'set' command + item_size = len(str(args[1])) + elif arg_count == 1: + # 'set_many' command + item_size = len(str(args[0])) + + if item_size is not None: + span.set_attribute(SPANDATA.CACHE_ITEM_SIZE, item_size) + + return value @functools.wraps(original_method) def sentry_method(*args: "Any", **kwargs: "Any") -> "Any": diff --git a/sentry_sdk/integrations/django/middleware.py b/sentry_sdk/integrations/django/middleware.py index dcd114e795..a567ec5045 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -10,17 +10,14 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, - transaction_from_function, ) if TYPE_CHECKING: - from typing import Any, Callable, Optional, TypeVar, Union + from typing import Any, Callable, Optional, TypeVar from sentry_sdk.traces import StreamedSpan - from sentry_sdk.tracing import Span F = TypeVar("F", bound=Callable[..., Any]) @@ -69,39 +66,27 @@ def _wrap_middleware(middleware: "Any", middleware_name: str) -> "Any": def _check_middleware_span( old_method: "Callable[..., Any]", - ) -> "Optional[Union[Span, StreamedSpan]]": + ) -> "Optional[StreamedSpan]": integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is None or not integration.middleware_spans: return None - function_name = transaction_from_function(old_method) - description = middleware_name function_basename = getattr(old_method, "__name__", None) if function_basename: description = "{}.{}".format(description, function_basename) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - middleware_span: "Union[Span, StreamedSpan]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return None - middleware_span = sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": OP.MIDDLEWARE_DJANGO, - "sentry.origin": DjangoIntegration.origin, - SPANDATA.MIDDLEWARE_NAME: middleware_name, - }, - ) - else: - middleware_span = sentry_sdk.start_span( - op=OP.MIDDLEWARE_DJANGO, - name=description, - origin=DjangoIntegration.origin, - ) - middleware_span.set_tag("django.function_name", function_name) - middleware_span.set_tag("django.middleware_name", middleware_name) + if sentry_sdk.traces.get_current_span() is None: + return None + + middleware_span = sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": OP.MIDDLEWARE_DJANGO, + "sentry.origin": DjangoIntegration.origin, + SPANDATA.MIDDLEWARE_NAME: middleware_name, + }, + ) return middleware_span diff --git a/sentry_sdk/integrations/django/signals_handlers.py b/sentry_sdk/integrations/django/signals_handlers.py index 711e74b441..832eb60824 100644 --- a/sentry_sdk/integrations/django/signals_handlers.py +++ b/sentry_sdk/integrations/django/signals_handlers.py @@ -6,7 +6,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations.django import DJANGO_VERSION -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from collections.abc import Callable @@ -64,29 +63,18 @@ def sentry_sync_receiver_wrapper( def wrapper(*args: "Any", **kwargs: "Any") -> "Any": signal_name = _get_receiver_name(receiver) - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return receiver(*args, **kwargs) - with sentry_sdk.traces.start_span( - name=signal_name, - attributes={ - "sentry.op": OP.EVENT_DJANGO, - "sentry.origin": DjangoIntegration.origin, - SPANDATA.CODE_FUNCTION_NAME: signal_name, - }, - ): - return receiver(*args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.EVENT_DJANGO, - name=signal_name, - origin=DjangoIntegration.origin, - ) as span: - span.set_data("signal", signal_name) - return receiver(*args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return receiver(*args, **kwargs) + + with sentry_sdk.traces.start_span( + name=signal_name, + attributes={ + "sentry.op": OP.EVENT_DJANGO, + "sentry.origin": DjangoIntegration.origin, + SPANDATA.CODE_FUNCTION_NAME: signal_name, + }, + ): + return receiver(*args, **kwargs) return wrapper diff --git a/sentry_sdk/integrations/django/tasks.py b/sentry_sdk/integrations/django/tasks.py index 303040d042..be4989e620 100644 --- a/sentry_sdk/integrations/django/tasks.py +++ b/sentry_sdk/integrations/django/tasks.py @@ -2,7 +2,6 @@ import sentry_sdk from sentry_sdk.consts import OP -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import qualname_from_function try: @@ -33,22 +32,16 @@ def _sentry_enqueue(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": name = qualname_from_function(self.func) or "" - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_task_enqueue(self, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_DJANGO, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return old_task_enqueue(self, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_DJANGO, name=name, origin=DjangoIntegration.origin - ): - return old_task_enqueue(self, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return old_task_enqueue(self, *args, **kwargs) + + with sentry_sdk.traces.start_span( + name=name, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_DJANGO, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return old_task_enqueue(self, *args, **kwargs) Task.enqueue = _sentry_enqueue From d18f3069107ecf539781e7975990c1bdad4550c8 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 13 Aug 2026 13:41:07 +0200 Subject: [PATCH 2/2] chore(django): Remove transaction-based tracing --- sentry_sdk/integrations/django/asgi.py | 2 +- sentry_sdk/integrations/django/templates.py | 65 +- sentry_sdk/integrations/django/views.py | 75 +- tests/integrations/django/asgi/test_asgi.py | 512 ++--- tests/integrations/django/test_basic.py | 1701 ++++----------- .../integrations/django/test_cache_module.py | 962 +++----- .../django/test_data_scrubbing.py | 12 +- .../integrations/django/test_db_query_data.py | 895 +++----- .../django/test_db_transactions.py | 1932 +++++------------ tests/integrations/django/test_tasks.py | 245 +-- 10 files changed, 1818 insertions(+), 4583 deletions(-) diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index fe7857f3b2..99229aaba8 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -174,7 +174,7 @@ async def sentry_wrapped_callback( request: "Any", *args: "Any", **kwargs: "Any" ) -> "Any": client = sentry_sdk.get_client() - current_span = sentry_sdk.get_current_span() + current_span = sentry_sdk.traces.get_current_span() if type(current_span) is StreamedSpan: segment = current_span._segment segment._update_active_thread() diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 7b1dc438d9..d2eed17972 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -7,7 +7,6 @@ import sentry_sdk from sentry_sdk.consts import OP -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ensure_integration_enabled if TYPE_CHECKING: @@ -55,26 +54,17 @@ def patch_templates() -> None: @property # type: ignore @ensure_integration_enabled(DjangoIntegration, real_rendered_content.fget) def rendered_content(self: "SimpleTemplateResponse") -> str: - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_rendered_content.fget(self) - with sentry_sdk.traces.start_span( - name=_get_template_name_description(self.template_name), - attributes={ - "sentry.op": OP.TEMPLATE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return real_rendered_content.fget(self) - else: - with sentry_sdk.start_span( - op=OP.TEMPLATE_RENDER, - name=_get_template_name_description(self.template_name), - origin=DjangoIntegration.origin, - ) as span: - span.set_data("context", self.context_data) - return real_rendered_content.fget(self) + if sentry_sdk.traces.get_current_span() is None: + return real_rendered_content.fget(self) + + with sentry_sdk.traces.start_span( + name=_get_template_name_description(self.template_name), + attributes={ + "sentry.op": OP.TEMPLATE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return real_rendered_content.fget(self) SimpleTemplateResponse.rendered_content = rendered_content @@ -98,28 +88,17 @@ def render( sentry_sdk.get_current_scope().trace_propagation_meta() ) - client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_render(request, template_name, context, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=_get_template_name_description(template_name), - attributes={ - "sentry.op": OP.TEMPLATE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return real_render(request, template_name, context, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.TEMPLATE_RENDER, - name=_get_template_name_description(template_name), - origin=DjangoIntegration.origin, - ) as span: - span.set_data("context", context) - return real_render(request, template_name, context, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return real_render(request, template_name, context, *args, **kwargs) + + with sentry_sdk.traces.start_span( + name=_get_template_name_description(template_name), + attributes={ + "sentry.op": OP.TEMPLATE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return real_render(request, template_name, context, *args, **kwargs) django.shortcuts.render = render diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py index 49eef63211..11c7adcb8e 100644 --- a/sentry_sdk/integrations/django/views.py +++ b/sentry_sdk/integrations/django/views.py @@ -4,7 +4,6 @@ import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Any @@ -22,25 +21,17 @@ def patch_views() -> None: old_render = SimpleTemplateResponse.render def sentry_patched_render(self: "SimpleTemplateResponse") -> "Any": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_render(self) - with sentry_sdk.traces.start_span( - name="serialize response", - attributes={ - "sentry.op": OP.VIEW_RESPONSE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return old_render(self) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RESPONSE_RENDER, - name="serialize response", - origin=DjangoIntegration.origin, - ): - return old_render(self) + if sentry_sdk.traces.get_current_span() is None: + return old_render(self) + + with sentry_sdk.traces.start_span( + name="serialize response", + attributes={ + "sentry.op": OP.VIEW_RESPONSE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return old_render(self) @functools.wraps(old_make_view_atomic) def sentry_patched_make_view_atomic( @@ -70,38 +61,26 @@ def _wrap_sync_view(callback: "Any") -> "Any": @functools.wraps(callback) def sentry_wrapped_callback(request: "Any", *args: "Any", **kwargs: "Any") -> "Any": client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - current_scope = sentry_sdk.get_current_scope() - if span_streaming: - current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - segment = current_span._segment - segment._update_active_thread() - else: - if current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + + current_span = sentry_sdk.traces.get_current_span() + if type(current_span) is StreamedSpan: + segment = current_span._segment + segment._update_active_thread() integration = client.get_integration(DjangoIntegration) if not integration or not integration.middleware_spans: return callback(request, *args, **kwargs) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return callback(request, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=request.resolver_match.view_name, - attributes={ - "sentry.op": OP.VIEW_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return callback(request, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RENDER, - name=request.resolver_match.view_name, - origin=DjangoIntegration.origin, - ): - return callback(request, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return callback(request, *args, **kwargs) + + with sentry_sdk.traces.start_span( + name=request.resolver_match.view_name, + attributes={ + "sentry.op": OP.VIEW_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return callback(request, *args, **kwargs) return sentry_wrapped_callback diff --git a/tests/integrations/django/asgi/test_asgi.py b/tests/integrations/django/asgi/test_asgi.py index 7690f01ffb..3e27fbdf33 100644 --- a/tests/integrations/django/asgi/test_asgi.py +++ b/tests/integrations/django/asgi/test_asgi.py @@ -44,104 +44,59 @@ def make_asgi_application(): @pytest.mark.skipif( django.VERSION < (3, 0), reason="Django ASGI support shipped in 3.0" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_basic( sentry_init, - capture_events, capture_items, application, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) import channels # type: ignore[import-not-found] - if span_streaming: - items = capture_items("event") - - if ( - sys.version_info < (3, 9) - and channels.__version__ < "4.0.0" - and django.VERSION >= (3, 0) - and django.VERSION < (4, 0) - ): - # We emit a UserWarning for channels 2.x and 3.x on Python 3.8 and older - # because the async support was not really good back then and there is a known issue. - # See the TreadingIntegration for details. - with pytest.warns(UserWarning): - comm = HttpCommunicator(application, "GET", "/view-exc?test=query") - response = await comm.get_response() - await comm.wait() - else: + items = capture_items("event") + + if ( + sys.version_info < (3, 9) + and channels.__version__ < "4.0.0" + and django.VERSION >= (3, 0) + and django.VERSION < (4, 0) + ): + # We emit a UserWarning for channels 2.x and 3.x on Python 3.8 and older + # because the async support was not really good back then and there is a known issue. + # See the TreadingIntegration for details. + with pytest.warns(UserWarning): comm = HttpCommunicator(application, "GET", "/view-exc?test=query") response = await comm.get_response() await comm.wait() - - assert response["status"] == 500 - - (event,) = (item.payload for item in items) - - (exception,) = event["exception"]["values"] - assert exception["type"] == "ZeroDivisionError" - - # Test that the ASGI middleware got set up correctly. Right now this needs - # to be installed manually (see myapp/asgi.py) - assert event["transaction"] == "/view-exc" - assert event["request"] == { - "cookies": {}, - "headers": {}, - "method": "GET", - "query_string": "test=query", - "url": "/view-exc", - } - - capture_message("hi") - event = items[-1].payload else: - events = capture_events() - - if ( - sys.version_info < (3, 9) - and channels.__version__ < "4.0.0" - and django.VERSION >= (3, 0) - and django.VERSION < (4, 0) - ): - # We emit a UserWarning for channels 2.x and 3.x on Python 3.8 and older - # because the async support was not really good back then and there is a known issue. - # See the TreadingIntegration for details. - with pytest.warns(UserWarning): - comm = HttpCommunicator(application, "GET", "/view-exc?test=query") - response = await comm.get_response() - await comm.wait() - else: - comm = HttpCommunicator(application, "GET", "/view-exc?test=query") - response = await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "GET", "/view-exc?test=query") + response = await comm.get_response() + await comm.wait() - assert response["status"] == 500 + assert response["status"] == 500 - (event,) = events + (event,) = (item.payload for item in items) - (exception,) = event["exception"]["values"] - assert exception["type"] == "ZeroDivisionError" + (exception,) = event["exception"]["values"] + assert exception["type"] == "ZeroDivisionError" - # Test that the ASGI middleware got set up correctly. Right now this needs - # to be installed manually (see myapp/asgi.py) - assert event["transaction"] == "/view-exc" - assert event["request"] == { - "cookies": {}, - "headers": {}, - "method": "GET", - "query_string": "test=query", - "url": "/view-exc", - } + # Test that the ASGI middleware got set up correctly. Right now this needs + # to be installed manually (see myapp/asgi.py) + assert event["transaction"] == "/view-exc" + assert event["request"] == { + "cookies": {}, + "headers": {}, + "method": "GET", + "query_string": "test=query", + "url": "/view-exc", + } - capture_message("hi") - event = events[-1] + capture_message("hi") + event = items[-1].payload assert "request" not in event @@ -151,39 +106,26 @@ async def test_basic( @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_async_views( sentry_init, - capture_events, capture_items, application, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) comm = HttpCommunicator(application, "GET", "/async_message") - if span_streaming: - items = capture_items("event") - - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 200 + items = capture_items("event") - (event,) = (item.payload for item in items) - else: - events = capture_events() - - response = await comm.get_response() - await comm.wait() + response = await comm.get_response() + await comm.wait() - assert response["status"] == 200 + assert response["status"] == 200 - (event,) = events + (event,) = (item.payload for item in items) assert event["transaction"] == "/async_message" assert event["request"] == { @@ -277,14 +219,11 @@ async def test_async_middleware_that_is_function_concurrent_execution( @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_async_middleware_spans( sentry_init, render_span_tree, - capture_events, capture_items, settings, - span_streaming, make_asgi_application, ): settings.MIDDLEWARE = [ @@ -296,7 +235,7 @@ async def test_async_middleware_spans( sentry_init( integrations=[DjangoIntegration(middleware_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", _experiments={ "record_sql_params": True, }, @@ -305,24 +244,23 @@ async def test_async_middleware_spans( application = make_asgi_application() comm = HttpCommunicator(application, "GET", "/simple_async_view") - if span_streaming: - items = capture_items("span") + items = capture_items("span") - response = await comm.get_response() - await comm.wait() + response = await comm.get_response() + await comm.wait() - assert response["status"] == 200 + assert response["status"] == 200 - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - # Filter out signal-receiver spans — their ordering depends on Django - # module import order and is not what this middleware test verifies. - spans = [s for s in spans if s["attributes"].get("sentry.op") != "event.django"] + # Filter out signal-receiver spans — their ordering depends on Django + # module import order and is not what this middleware test verifies. + spans = [s for s in spans if s["attributes"].get("sentry.op") != "event.django"] - assert ( - render_span_tree(spans) - == """\ + assert ( + render_span_tree(spans) + == """\ - sentry.op="http.server": name="/simple_async_view" - sentry.op="middleware.django": name="django.contrib.sessions.middleware.SessionMiddleware.__acall__" - sentry.op="middleware.django": name="django.contrib.auth.middleware.AuthenticationMiddleware.__acall__" @@ -330,131 +268,72 @@ async def test_async_middleware_spans( - sentry.op="middleware.django": name="tests.integrations.django.myapp.settings.TestMiddleware.__acall__" - sentry.op="middleware.django": name="django.middleware.csrf.CsrfViewMiddleware.process_view" - sentry.op="view.render": name="simple_async_view\"""" - ) - else: - events = capture_events() - - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 200 - - (transaction,) = events - - assert transaction["type"] == "transaction" - - # Filter out signal-receiver spans — their ordering depends on Django - # module import order and is not what this middleware test verifies. - spans = [s for s in transaction["spans"] if s.get("op") != "event.django"] - - assert ( - render_span_tree(spans, transaction["contexts"]["trace"]) - == """\ -- op="http.server": description=null - - op="middleware.django": description="django.contrib.sessions.middleware.SessionMiddleware.__acall__" - - op="middleware.django": description="django.contrib.auth.middleware.AuthenticationMiddleware.__acall__" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.__acall__" - - op="middleware.django": description="tests.integrations.django.myapp.settings.TestMiddleware.__acall__" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.process_view" - - op="view.render": description="simple_async_view\"""" - ) + ) @pytest.mark.asyncio @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_has_trace_if_performance_enabled( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) comm = HttpCommunicator(asgi_application, "GET", "/view-exc-with-msg") - if span_streaming: - items = capture_items("event", "span") + items = capture_items("event", "span") - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 500 - - ( - msg_event, - error_event, - ) = (item.payload for item in items if item.type == "event") - - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert spans[6]["is_segment"] is True - - assert ( - msg_event["contexts"]["trace"]["trace_id"] - == error_event["contexts"]["trace"]["trace_id"] - == spans[6]["trace_id"] - ) - else: - events = capture_events() + response = await comm.get_response() + await comm.wait() - response = await comm.get_response() - await comm.wait() + assert response["status"] == 500 - assert response["status"] == 500 + ( + msg_event, + error_event, + ) = (item.payload for item in items if item.type == "event") - (msg_event, error_event, transaction_event) = events + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert spans[6]["is_segment"] is True - assert ( - msg_event["contexts"]["trace"]["trace_id"] - == error_event["contexts"]["trace"]["trace_id"] - == transaction_event["contexts"]["trace"]["trace_id"] - ) + assert ( + msg_event["contexts"]["trace"]["trace_id"] + == error_event["contexts"]["trace"]["trace_id"] + == spans[6]["trace_id"] + ) @pytest.mark.asyncio @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_has_trace_if_performance_disabled( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) comm = HttpCommunicator(asgi_application, "GET", "/view-exc-with-msg") - if span_streaming: - items = capture_items("event") + items = capture_items("event") - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 500 - - ( - msg_event, - error_event, - ) = (item.payload for item in items) - else: - events = capture_events() - - response = await comm.get_response() - await comm.wait() + response = await comm.get_response() + await comm.wait() - assert response["status"] == 500 + assert response["status"] == 500 - (msg_event, error_event) = events + ( + msg_event, + error_event, + ) = (item.payload for item in items) assert msg_event["contexts"]["trace"] assert "trace_id" in msg_event["contexts"]["trace"] @@ -471,17 +350,14 @@ async def test_has_trace_if_performance_disabled( @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_trace_from_headers_if_performance_enabled( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) trace_id = "582b43a4192642f0b136d5159a501701" @@ -494,55 +370,38 @@ async def test_trace_from_headers_if_performance_enabled( headers=[(b"sentry-trace", sentry_trace_header.encode())], ) - if span_streaming: - items = capture_items("event", "span") - - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 500 - - ( - msg_event, - error_event, - ) = (item.payload for item in items if item.type == "event") - - assert msg_event["contexts"]["trace"]["trace_id"] == trace_id - assert error_event["contexts"]["trace"]["trace_id"] == trace_id + items = capture_items("event", "span") - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert spans[6]["is_segment"] is True - assert spans[6]["trace_id"] == trace_id - else: - events = capture_events() + response = await comm.get_response() + await comm.wait() - response = await comm.get_response() - await comm.wait() + assert response["status"] == 500 - assert response["status"] == 500 + ( + msg_event, + error_event, + ) = (item.payload for item in items if item.type == "event") - (msg_event, error_event, transaction_event) = events + assert msg_event["contexts"]["trace"]["trace_id"] == trace_id + assert error_event["contexts"]["trace"]["trace_id"] == trace_id - assert msg_event["contexts"]["trace"]["trace_id"] == trace_id - assert error_event["contexts"]["trace"]["trace_id"] == trace_id - assert transaction_event["contexts"]["trace"]["trace_id"] == trace_id + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert spans[6]["is_segment"] is True + assert spans[6]["trace_id"] == trace_id @pytest.mark.asyncio @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_trace_from_headers_if_performance_disabled( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) trace_id = "582b43a4192642f0b136d5159a501701" @@ -555,24 +414,14 @@ async def test_trace_from_headers_if_performance_disabled( headers=[(b"sentry-trace", sentry_trace_header.encode())], ) - if span_streaming: - items = capture_items("event") - - response = await comm.get_response() - await comm.wait() + items = capture_items("event") - assert response["status"] == 500 - - (msg_event, error_event) = (item.payload for item in items) - else: - events = capture_events() - - response = await comm.get_response() - await comm.wait() + response = await comm.get_response() + await comm.wait() - assert response["status"] == 500 + assert response["status"] == 500 - (msg_event, error_event) = events + (msg_event, error_event) = (item.payload for item in items) assert msg_event["contexts"]["trace"]["trace_id"] == trace_id assert error_event["contexts"]["trace"]["trace_id"] == trace_id @@ -681,10 +530,8 @@ async def test_trace_from_headers_if_performance_disabled( @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_asgi_request_body( sentry_init, - capture_envelopes, capture_items, application, send_default_pii, @@ -693,12 +540,11 @@ async def test_asgi_request_body( url_name, body, expected_data, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=send_default_pii, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) comm = HttpCommunicator( @@ -709,28 +555,16 @@ async def test_asgi_request_body( body=body, ) - if span_streaming: - items = capture_items("event") + items = capture_items("event") - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 200 - assert response["body"] == body - - sentry_sdk.flush() - (event,) = (item.payload for item in items) - else: - envelopes = capture_envelopes() - - response = await comm.get_response() - await comm.wait() + response = await comm.get_response() + await comm.wait() - assert response["status"] == 200 - assert response["body"] == body + assert response["status"] == 200 + assert response["body"] == body - (envelope,) = envelopes - event = envelope.get_event() + sentry_sdk.flush() + (event,) = (item.payload for item in items) if expected_data is not None: assert event["request"]["data"] == expected_data @@ -808,39 +642,26 @@ def get_response(): ... @pytest.mark.skipif( django.VERSION < (3, 1), reason="async views have been introduced in Django 3.1" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_async_view( sentry_init, - capture_events, capture_items, application, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) comm = HttpCommunicator(application, "GET", "/simple_async_view") - if span_streaming: - items = capture_items("span") + items = capture_items("span") - await comm.get_response() - await comm.wait() - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert spans[5]["name"] == "/simple_async_view" - else: - events = capture_events() - - await comm.get_response() - await comm.wait() + await comm.get_response() + await comm.wait() - (event,) = events - assert event["type"] == "transaction" - assert event["transaction"] == "/simple_async_view" + sentry_sdk.flush() + spans = [item.payload for item in items] + assert spans[5]["name"] == "/simple_async_view" @pytest.mark.parametrize("application", APPS) @@ -848,13 +669,10 @@ async def test_async_view( @pytest.mark.skipif( django.VERSION < (3, 0), reason="Django ASGI support shipped in 3.0" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_transaction_http_method_default( sentry_init, - capture_events, capture_items, application, - span_streaming, ): """ By default OPTIONS and HEAD requests do not create a transaction. @@ -862,45 +680,25 @@ async def test_transaction_http_method_default( sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - comm = HttpCommunicator(application, "GET", "/simple_async_view") - await comm.get_response() - await comm.wait() + items = capture_items("span") - comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") - await comm.get_response() - await comm.wait() - - comm = HttpCommunicator(application, "HEAD", "/simple_async_view") - await comm.get_response() - await comm.wait() - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert spans[5]["attributes"]["http.request.method"] == "GET" - else: - events = capture_events() - - comm = HttpCommunicator(application, "GET", "/simple_async_view") - await comm.get_response() - await comm.wait() - - comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") - await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "GET", "/simple_async_view") + await comm.get_response() + await comm.wait() - comm = HttpCommunicator(application, "HEAD", "/simple_async_view") - await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") + await comm.get_response() + await comm.wait() - (event,) = events + comm = HttpCommunicator(application, "HEAD", "/simple_async_view") + await comm.get_response() + await comm.wait() - assert len(events) == 1 - assert event["request"]["method"] == "GET" + sentry_sdk.flush() + spans = [item.payload for item in items] + assert spans[5]["attributes"]["http.request.method"] == "GET" @pytest.mark.parametrize("application", APPS) @@ -908,13 +706,10 @@ async def test_transaction_http_method_default( @pytest.mark.skipif( django.VERSION < (3, 0), reason="Django ASGI support shipped in 3.0" ) -@pytest.mark.parametrize("span_streaming", [True, False]) async def test_transaction_http_method_custom( sentry_init, - capture_events, capture_items, application, - span_streaming, ): sentry_init( integrations=[ @@ -926,48 +721,27 @@ async def test_transaction_http_method_custom( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - comm = HttpCommunicator(application, "GET", "/simple_async_view") - await comm.get_response() - await comm.wait() - - comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") - await comm.get_response() - await comm.wait() - - comm = HttpCommunicator(application, "HEAD", "/simple_async_view") - await comm.get_response() - await comm.wait() + items = capture_items("span") - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[5]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "OPTIONS" - assert spans[11]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "HEAD" - else: - events = capture_events() - - comm = HttpCommunicator(application, "GET", "/simple_async_view") - await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "GET", "/simple_async_view") + await comm.get_response() + await comm.wait() - comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") - await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "OPTIONS", "/simple_async_view") + await comm.get_response() + await comm.wait() - comm = HttpCommunicator(application, "HEAD", "/simple_async_view") - await comm.get_response() - await comm.wait() + comm = HttpCommunicator(application, "HEAD", "/simple_async_view") + await comm.get_response() + await comm.wait() - assert len(events) == 2 + sentry_sdk.flush() + spans = [item.payload for item in items] - (event1, event2) = events - assert event1["request"]["method"] == "OPTIONS" - assert event2["request"]["method"] == "HEAD" + assert spans[5]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "OPTIONS" + assert spans[11]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "HEAD" @pytest.mark.asyncio diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 9591ac36c3..d705908a63 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -47,50 +47,35 @@ def client(): return Client(application) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_view_exceptions( sentry_init, client, capture_exceptions, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) exceptions = capture_exceptions() - if span_streaming: - items = capture_items("event") - client.get(reverse("view_exc")) - - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) - - (event,) = (item.payload for item in items) - else: - events = capture_events() - client.get(reverse("view_exc")) + items = capture_items("event") + client.get(reverse("view_exc")) - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) + (error,) = exceptions + assert isinstance(error, ZeroDivisionError) - (event,) = events + (event,) = (item.payload for item in items) assert event["exception"]["values"][0]["mechanism"]["type"] == "django" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_ensures_x_forwarded_header_is_honored_in_sdk_when_enabled_in_django( sentry_init, client, capture_exceptions, - capture_events, capture_items, settings, - span_streaming, ): """ Test that ensures if django settings.USE_X_FORWARDED_HOST is set to True @@ -101,37 +86,25 @@ def test_ensures_x_forwarded_header_is_honored_in_sdk_when_enabled_in_django( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) exceptions = capture_exceptions() - if span_streaming: - items = capture_items("event") - client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) + items = capture_items("event") + client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) - - (event,) = (item.payload for item in items) - else: - events = capture_events() - client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) - - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) + (error,) = exceptions + assert isinstance(error, ZeroDivisionError) - (event,) = events + (event,) = (item.payload for item in items) assert event["request"]["url"] == "http://example.com/view-exc" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_ensures_x_forwarded_header_is_not_honored_when_unenabled_in_django( sentry_init, client, capture_exceptions, - capture_events, capture_items, - span_streaming, ): """ Test that ensures if django settings.USE_X_FORWARDED_HOST is set to False @@ -140,23 +113,15 @@ def test_ensures_x_forwarded_header_is_not_honored_when_unenabled_in_django( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) exceptions = capture_exceptions() - if span_streaming: - items = capture_items("event") - client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) + items = capture_items("event") + client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) - (event,) = (item.payload for item in items) - else: - events = capture_events() - client.get(reverse("view_exc"), headers={"X_FORWARDED_HOST": "example.com"}) - - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) - (event,) = events + (error,) = exceptions + assert isinstance(error, ZeroDivisionError) + (event,) = (item.payload for item in items) assert event["request"]["url"] == "http://localhost/view-exc" @@ -170,101 +135,61 @@ def test_middleware_exceptions(sentry_init, client, capture_exceptions): assert isinstance(error, ZeroDivisionError) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_request_captured( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event") - content, status, headers = unpack_werkzeug_response( - client.get(reverse("message")) - ) - - assert content == b"ok" + items = capture_items("event") + content, status, headers = unpack_werkzeug_response(client.get(reverse("message"))) - (event,) = (item.payload for item in items) - - assert event["transaction"] == "/message" - assert event["request"] == { - "cookies": {}, - "env": {"SERVER_NAME": "localhost", "SERVER_PORT": "80"}, - "headers": {"Host": "localhost"}, - "method": "GET", - "query_string": "", - "url": "http://localhost/message", - } - else: - events = capture_events() - content, status, headers = unpack_werkzeug_response( - client.get(reverse("message")) - ) + assert content == b"ok" - assert content == b"ok" + (event,) = (item.payload for item in items) - (event,) = events - assert event["transaction"] == "/message" - assert event["request"] == { - "cookies": {}, - "env": {"SERVER_NAME": "localhost", "SERVER_PORT": "80"}, - "headers": {"Host": "localhost"}, - "method": "GET", - "query_string": "", - "url": "http://localhost/message", - } + assert event["transaction"] == "/message" + assert event["request"] == { + "cookies": {}, + "env": {"SERVER_NAME": "localhost", "SERVER_PORT": "80"}, + "headers": {"Host": "localhost"}, + "method": "GET", + "query_string": "", + "url": "http://localhost/message", + } -@pytest.mark.parametrize("span_streaming", [True, False]) def test_transaction_with_class_view( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(transaction_style="function_name")], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event") - content, status, headers = unpack_werkzeug_response( - client.head(reverse("classbased")) - ) - assert status.lower() == "200 ok" - - (event,) = (item.payload for item in items) - else: - events = capture_events() - content, status, headers = unpack_werkzeug_response( - client.head(reverse("classbased")) - ) - assert status.lower() == "200 ok" - - (event,) = events + items = capture_items("event") + content, status, headers = unpack_werkzeug_response( + client.head(reverse("classbased")) + ) + assert status.lower() == "200 ok" + (event,) = (item.payload for item in items) assert ( event["transaction"] == "tests.integrations.django.myapp.views.ClassBasedView" ) assert event["message"] == "hi" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_has_trace_if_performance_enabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ @@ -273,80 +198,50 @@ def test_has_trace_if_performance_enabled( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") - client.head(reverse("view_exc_with_msg")) - - ( - msg_event, - error_event, - ) = (item.payload for item in items if item.type == "event") - - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert spans[3]["is_segment"] is True - assert "trace_id" in spans[3] - - assert msg_event["contexts"]["trace"] - assert "trace_id" in msg_event["contexts"]["trace"] + items = capture_items("event", "span") + client.head(reverse("view_exc_with_msg")) - assert error_event["contexts"]["trace"] - assert "trace_id" in error_event["contexts"]["trace"] + ( + msg_event, + error_event, + ) = (item.payload for item in items if item.type == "event") - assert ( - msg_event["contexts"]["trace"]["trace_id"] - == error_event["contexts"]["trace"]["trace_id"] - == spans[3]["trace_id"] - ) - else: - events = capture_events() - client.head(reverse("view_exc_with_msg")) - - (msg_event, error_event, transaction_event) = events - - assert transaction_event["contexts"]["trace"] - assert "trace_id" in transaction_event["contexts"]["trace"] + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert spans[3]["is_segment"] is True + assert "trace_id" in spans[3] - assert msg_event["contexts"]["trace"] - assert "trace_id" in msg_event["contexts"]["trace"] + assert msg_event["contexts"]["trace"] + assert "trace_id" in msg_event["contexts"]["trace"] - assert error_event["contexts"]["trace"] - assert "trace_id" in error_event["contexts"]["trace"] + assert error_event["contexts"]["trace"] + assert "trace_id" in error_event["contexts"]["trace"] - assert ( - msg_event["contexts"]["trace"]["trace_id"] - == error_event["contexts"]["trace"]["trace_id"] - == transaction_event["contexts"]["trace"]["trace_id"] - ) + assert ( + msg_event["contexts"]["trace"]["trace_id"] + == error_event["contexts"]["trace"]["trace_id"] + == spans[3]["trace_id"] + ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_has_trace_if_performance_disabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event") - client.head(reverse("view_exc_with_msg")) + items = capture_items("event") + client.head(reverse("view_exc_with_msg")) - ( - msg_event, - error_event, - ) = (item.payload for item in items) - else: - events = capture_events() - client.head(reverse("view_exc_with_msg")) - - (msg_event, error_event) = events + ( + msg_event, + error_event, + ) = (item.payload for item in items) assert msg_event["contexts"]["trace"] assert "trace_id" in msg_event["contexts"]["trace"] @@ -360,13 +255,10 @@ def test_has_trace_if_performance_disabled( ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_trace_from_headers_if_performance_enabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ @@ -375,66 +267,42 @@ def test_trace_from_headers_if_performance_enabled( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) trace_id = "582b43a4192642f0b136d5159a501701" sentry_trace_header = "{}-{}-{}".format(trace_id, "6e8f22c393e68f19", 1) - if span_streaming: - items = capture_items("event", "span") - client.head( - reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} - ) - - ( - msg_event, - error_event, - ) = (item.payload for item in items if item.type == "event") - - assert msg_event["contexts"]["trace"] - assert "trace_id" in msg_event["contexts"]["trace"] - - assert error_event["contexts"]["trace"] - assert "trace_id" in error_event["contexts"]["trace"] - - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert spans[3]["is_segment"] is True - assert "trace_id" in spans[3] - - assert msg_event["contexts"]["trace"]["trace_id"] == trace_id - assert error_event["contexts"]["trace"]["trace_id"] == trace_id - assert spans[3]["trace_id"] == trace_id - else: - events = capture_events() - client.head( - reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} - ) + items = capture_items("event", "span") + client.head( + reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} + ) - (msg_event, error_event, transaction_event) = events + ( + msg_event, + error_event, + ) = (item.payload for item in items if item.type == "event") - assert msg_event["contexts"]["trace"] - assert "trace_id" in msg_event["contexts"]["trace"] + assert msg_event["contexts"]["trace"] + assert "trace_id" in msg_event["contexts"]["trace"] - assert error_event["contexts"]["trace"] - assert "trace_id" in error_event["contexts"]["trace"] + assert error_event["contexts"]["trace"] + assert "trace_id" in error_event["contexts"]["trace"] - assert transaction_event["contexts"]["trace"] - assert "trace_id" in transaction_event["contexts"]["trace"] + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert spans[3]["is_segment"] is True + assert "trace_id" in spans[3] - assert msg_event["contexts"]["trace"]["trace_id"] == trace_id - assert error_event["contexts"]["trace"]["trace_id"] == trace_id - assert transaction_event["contexts"]["trace"]["trace_id"] == trace_id + assert msg_event["contexts"]["trace"]["trace_id"] == trace_id + assert error_event["contexts"]["trace"]["trace_id"] == trace_id + assert spans[3]["trace_id"] == trace_id -@pytest.mark.parametrize("span_streaming", [True, False]) def test_trace_from_headers_if_performance_disabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ @@ -442,29 +310,21 @@ def test_trace_from_headers_if_performance_disabled( http_methods_to_capture=("HEAD",), ) ], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) trace_id = "582b43a4192642f0b136d5159a501701" sentry_trace_header = "{}-{}-{}".format(trace_id, "6e8f22c393e68f19", 1) - if span_streaming: - items = capture_items("event") - client.head( - reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} - ) - - ( - msg_event, - error_event, - ) = (item.payload for item in items) - else: - events = capture_events() - client.head( - reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} - ) + items = capture_items("event") + client.head( + reverse("view_exc_with_msg"), headers={"sentry-trace": sentry_trace_header} + ) - (msg_event, error_event) = events + ( + msg_event, + error_event, + ) = (item.payload for item in items) assert msg_event["contexts"]["trace"] assert "trace_id" in msg_event["contexts"]["trace"] @@ -478,50 +338,27 @@ def test_trace_from_headers_if_performance_disabled( @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_user_captured( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event") - content, status, headers = unpack_werkzeug_response( - client.get(reverse("mylogin")) - ) - assert content == b"ok" - - sentry_sdk.flush() - assert not items - - content, status, headers = unpack_werkzeug_response( - client.get(reverse("message")) - ) - assert content == b"ok" - - (event,) = (item.payload for item in items) - else: - events = capture_events() - content, status, headers = unpack_werkzeug_response( - client.get(reverse("mylogin")) - ) - assert content == b"ok" + items = capture_items("event") + content, status, headers = unpack_werkzeug_response(client.get(reverse("mylogin"))) + assert content == b"ok" - assert not events + sentry_sdk.flush() + assert not items - content, status, headers = unpack_werkzeug_response( - client.get(reverse("message")) - ) - assert content == b"ok" + content, status, headers = unpack_werkzeug_response(client.get(reverse("message"))) + assert content == b"ok" - (event,) = events + (event,) = (item.payload for item in items) assert event["user"] == { "email": "lennon@thebeatles.com", @@ -564,39 +401,25 @@ def test_materialized_user_captured( @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_queryset_repr( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword") - if span_streaming: - items = capture_items("event") + items = capture_items("event") - try: - my_queryset = User.objects.all() # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = (item.payload for item in items) - else: - events = capture_events() - - try: - my_queryset = User.objects.all() # noqa - 1 / 0 - except Exception: - capture_exception() + try: + my_queryset = User.objects.all() # noqa + 1 / 0 + except Exception: + capture_exception() - (event,) = events + (event,) = (item.payload for item in items) (exception,) = event["exception"]["values"] assert exception["type"] == "ZeroDivisionError" @@ -608,38 +431,24 @@ def test_queryset_repr( @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_context_nested_queryset_repr( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword") - if span_streaming: - items = capture_items("event") - - try: - context = make_context({"entries": User.objects.all()}) # noqa - 1 / 0 - except Exception: - capture_exception() - - (event,) = (item.payload for item in items) - else: - events = capture_events() + items = capture_items("event") - try: - context = make_context({"entries": User.objects.all()}) # noqa - 1 / 0 - except Exception: - capture_exception() + try: + context = make_context({"entries": User.objects.all()}) # noqa + 1 / 0 + except Exception: + capture_exception() - (event,) = events + (event,) = (item.payload for item in items) (exception,) = event["exception"]["values"] assert exception["type"] == "ZeroDivisionError" @@ -647,30 +456,20 @@ def test_context_nested_queryset_repr( assert "= (1, 7): - views_tests.append( - ( - reverse("template_test"), - '- sentry.op="template.render": name="user_name.html"', - ), - ) - - for url, expected_line in views_tests: - items = capture_items("span") - client.get(url) - sentry_sdk.flush() - spans = [item.payload for item in items] - assert expected_line in render_span_tree(spans) - else: - views_tests = [ + views_tests = [ + ( + reverse("template_test2"), + '- sentry.op="template.render": name="[user_name.html, ...]"', + ), + ] + if DJANGO_VERSION >= (1, 7): + views_tests.append( ( - reverse("template_test2"), - '- op="template.render": description="[user_name.html, ...]"', + reverse("template_test"), + '- sentry.op="template.render": name="user_name.html"', ), - ] - if DJANGO_VERSION >= (1, 7): - views_tests.append( - ( - reverse("template_test"), - '- op="template.render": description="user_name.html"', - ), - ) + ) - for url, expected_line in views_tests: - events = capture_events() - client.get(url) - transaction = events[0] - assert expected_line in render_span_tree( - transaction["spans"], transaction["contexts"]["trace"] - ) + for url, expected_line in views_tests: + items = capture_items("span") + client.get(url) + sentry_sdk.flush() + spans = [item.payload for item in items] + assert expected_line in render_span_tree(spans) @pytest.mark.forked @@ -1904,35 +1341,31 @@ def test_render_spans_queryset_in_data(sentry_init, client, capture_events): ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_middleware_spans( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): sentry_init( integrations=[ DjangoIntegration(middleware_spans=True, signals_spans=False), ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") + items = capture_items("event", "span") - client.get(reverse("message")) + client.get(reverse("message")) - (message,) = (item.payload for item in items if item.type == "event") - assert message["message"] == "hi" + (message,) = (item.payload for item in items if item.type == "event") + assert message["message"] == "hi" - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] - if DJANGO_VERSION >= (1, 10): - EXPECTED_MIDDLEWARE_SPANS = """\ + if DJANGO_VERSION >= (1, 10): + EXPECTED_MIDDLEWARE_SPANS = """\ - sentry.op="http.server": name="/message" - sentry.op="middleware.django": name="django.contrib.sessions.middleware.SessionMiddleware.__call__" - sentry.op="middleware.django": name="django.contrib.auth.middleware.AuthenticationMiddleware.__call__" @@ -1942,8 +1375,8 @@ def test_middleware_spans( - sentry.op="middleware.django": name="django.middleware.csrf.CsrfViewMiddleware.process_view" - sentry.op="view.render": name="message"\ """ - else: - EXPECTED_MIDDLEWARE_SPANS = """\ + else: + EXPECTED_MIDDLEWARE_SPANS = """\ - sentry.op="http.server": name="/message" - sentry.op="middleware.django": name="django.contrib.sessions.middleware.SessionMiddleware.process_request" - sentry.op="middleware.django": name="django.contrib.auth.middleware.AuthenticationMiddleware.process_request" @@ -1954,196 +1387,104 @@ def test_middleware_spans( - sentry.op="middleware.django": name="django.middleware.csrf.CsrfViewMiddleware.process_response" - sentry.op="middleware.django": name="django.contrib.sessions.middleware.SessionMiddleware.process_response"\ """ - assert render_span_tree(spans) == EXPECTED_MIDDLEWARE_SPANS - else: - events = capture_events() - - client.get(reverse("message")) - - message, transaction = events - - assert message["message"] == "hi" - if DJANGO_VERSION >= (1, 10): - EXPECTED_MIDDLEWARE_SPANS = """\ -- op="http.server": description=null - - op="middleware.django": description="django.contrib.sessions.middleware.SessionMiddleware.__call__" - - op="middleware.django": description="django.contrib.auth.middleware.AuthenticationMiddleware.__call__" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.__call__" - - op="middleware.django": description="tests.integrations.django.myapp.settings.TestMiddleware.__call__" - - op="middleware.django": description="tests.integrations.django.myapp.settings.TestFunctionMiddleware.__call__" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.process_view" - - op="view.render": description="message"\ -""" - else: - EXPECTED_MIDDLEWARE_SPANS = """\ -- op="http.server": description=null - - op="middleware.django": description="django.contrib.sessions.middleware.SessionMiddleware.process_request" - - op="middleware.django": description="django.contrib.auth.middleware.AuthenticationMiddleware.process_request" - - op="middleware.django": description="tests.integrations.django.myapp.settings.TestMiddleware.process_request" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.process_view" - - op="view.render": description="message" - - op="middleware.django": description="tests.integrations.django.myapp.settings.TestMiddleware.process_response" - - op="middleware.django": description="django.middleware.csrf.CsrfViewMiddleware.process_response" - - op="middleware.django": description="django.contrib.sessions.middleware.SessionMiddleware.process_response"\ -""" - assert ( - render_span_tree(transaction["spans"], transaction["contexts"]["trace"]) - == EXPECTED_MIDDLEWARE_SPANS - ) + assert render_span_tree(spans) == EXPECTED_MIDDLEWARE_SPANS -@pytest.mark.parametrize("span_streaming", [True, False]) def test_middleware_spans_disabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ DjangoIntegration(signals_spans=False), ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") + items = capture_items("event", "span") - client.get(reverse("message")) + client.get(reverse("message")) - (message,) = (item.payload for item in items if item.type == "event") + (message,) = (item.payload for item in items if item.type == "event") - assert message["message"] == "hi" + assert message["message"] == "hi" - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert len(spans) == 1 - else: - events = capture_events() - - client.get(reverse("message")) - - message, transaction = events - - assert message["message"] == "hi" - assert not len(transaction["spans"]) + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert len(spans) == 1 -@pytest.mark.parametrize("span_streaming", [True, False]) def test_signals_spans( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): sentry_init( integrations=[ DjangoIntegration(middleware_spans=False), ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") + items = capture_items("event", "span") - client.get(reverse("message")) + client.get(reverse("message")) - (message,) = (item.payload for item in items if item.type == "event") + (message,) = (item.payload for item in items if item.type == "event") - assert message["message"] == "hi" + assert message["message"] == "hi" - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert ( - render_span_tree(spans) - == """\ + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert ( + render_span_tree(spans) + == """\ - sentry.op="http.server": name="/message" - sentry.op="event.django": name="django.db.reset_queries" - sentry.op="event.django": name="django.db.close_old_connections"\ """ - ) - - assert spans[0]["attributes"]["sentry.op"] == "event.django" - assert spans[0]["name"] == "django.db.reset_queries" - - assert spans[1]["attributes"]["sentry.op"] == "event.django" - assert spans[1]["name"] == "django.db.close_old_connections" - else: - events = capture_events() - - client.get(reverse("message")) - - message, transaction = events - - assert message["message"] == "hi" - assert ( - render_span_tree(transaction["spans"], transaction["contexts"]["trace"]) - == """\ -- op="http.server": description=null - - op="event.django": description="django.db.reset_queries" - - op="event.django": description="django.db.close_old_connections"\ -""" - ) + ) - assert transaction["spans"][0]["op"] == "event.django" - assert transaction["spans"][0]["description"] == "django.db.reset_queries" + assert spans[0]["attributes"]["sentry.op"] == "event.django" + assert spans[0]["name"] == "django.db.reset_queries" - assert transaction["spans"][1]["op"] == "event.django" - assert ( - transaction["spans"][1]["description"] == "django.db.close_old_connections" - ) + assert spans[1]["attributes"]["sentry.op"] == "event.django" + assert spans[1]["name"] == "django.db.close_old_connections" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_signals_spans_disabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ DjangoIntegration(middleware_spans=False, signals_spans=False), ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") + items = capture_items("event", "span") - client.get(reverse("message")) + client.get(reverse("message")) - sentry_sdk.flush() - (message,) = (item.payload for item in items if item.type == "event") - - assert message["message"] == "hi" - - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - assert len(spans) == 1 - else: - events = capture_events() - - client.get(reverse("message")) + sentry_sdk.flush() + (message,) = (item.payload for item in items if item.type == "event") - message, transaction = events + assert message["message"] == "hi" - assert message["message"] == "hi" - assert not transaction["spans"] + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] + assert len(spans) == 1 -@pytest.mark.parametrize("span_streaming", [True, False]) def test_signals_spans_filtering( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): sentry_init( integrations=[ @@ -2155,65 +1496,32 @@ def test_signals_spans_filtering( ), ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - client.get(reverse("send_myapp_custom_signal")) + client.get(reverse("send_myapp_custom_signal")) - sentry_sdk.flush() - spans = [item.payload for item in items] - assert ( - render_span_tree(spans) - == """\ + sentry_sdk.flush() + spans = [item.payload for item in items] + assert ( + render_span_tree(spans) + == """\ - sentry.op="http.server": name="/send-myapp-custom-signal" - sentry.op="event.django": name="django.db.reset_queries" - sentry.op="event.django": name="django.db.close_old_connections" - sentry.op="event.django": name="tests.integrations.django.myapp.signals.signal_handler"\ """ - ) - - assert spans[0]["attributes"]["sentry.op"] == "event.django" - assert spans[0]["name"] == "django.db.reset_queries" - - assert spans[1]["attributes"]["sentry.op"] == "event.django" - assert spans[1]["name"] == "django.db.close_old_connections" - - assert spans[2]["attributes"]["sentry.op"] == "event.django" - assert ( - spans[2]["name"] == "tests.integrations.django.myapp.signals.signal_handler" - ) - else: - events = capture_events() + ) - client.get(reverse("send_myapp_custom_signal")) + assert spans[0]["attributes"]["sentry.op"] == "event.django" + assert spans[0]["name"] == "django.db.reset_queries" - (transaction,) = events + assert spans[1]["attributes"]["sentry.op"] == "event.django" + assert spans[1]["name"] == "django.db.close_old_connections" - assert ( - render_span_tree(transaction["spans"], transaction["contexts"]["trace"]) - == """\ -- op="http.server": description=null - - op="event.django": description="django.db.reset_queries" - - op="event.django": description="django.db.close_old_connections" - - op="event.django": description="tests.integrations.django.myapp.signals.signal_handler"\ -""" - ) - - assert transaction["spans"][0]["op"] == "event.django" - assert transaction["spans"][0]["description"] == "django.db.reset_queries" - - assert transaction["spans"][1]["op"] == "event.django" - assert ( - transaction["spans"][1]["description"] == "django.db.close_old_connections" - ) - - assert transaction["spans"][2]["op"] == "event.django" - assert ( - transaction["spans"][2]["description"] - == "tests.integrations.django.myapp.signals.signal_handler" - ) + assert spans[2]["attributes"]["sentry.op"] == "event.django" + assert spans[2]["name"] == "tests.integrations.django.myapp.signals.signal_handler" def test_csrf(sentry_init, client): @@ -2254,16 +1562,13 @@ def test_csrf(sentry_init, client): @pytest.mark.parametrize("middleware_spans", [False, True]) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_custom_urlconf_middleware( settings, sentry_init, client, - capture_events, capture_items, render_span_tree, middleware_spans, - span_streaming, ): """ Some middlewares (for instance in django-tenants) overwrite request.urlconf. @@ -2277,85 +1582,43 @@ def test_custom_urlconf_middleware( sentry_init( integrations=[DjangoIntegration(middleware_spans=middleware_spans)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") - - try: - content, status, _headers = unpack_werkzeug_response( - client.get("/custom/ok") - ) - assert status.lower() == "200 ok" - assert content == b"custom ok" + items = capture_items("event", "span") - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] + try: + content, status, _headers = unpack_werkzeug_response(client.get("/custom/ok")) + assert status.lower() == "200 ok" + assert content == b"custom ok" - if middleware_spans: - assert spans[10]["name"] == "/custom/ok" - assert "custom_urlconf_middleware" in render_span_tree(spans) - else: - assert spans[2]["name"] == "/custom/ok" + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] - _content, status, _headers = unpack_werkzeug_response( - client.get("/custom/exc") - ) - assert status.lower() == "500 internal server error" + if middleware_spans: + assert spans[10]["name"] == "/custom/ok" + assert "custom_urlconf_middleware" in render_span_tree(spans) + else: + assert spans[2]["name"] == "/custom/ok" - (error_event,) = (item.payload for item in items if item.type == "event") - assert error_event["transaction"] == "/custom/exc" - assert ( - error_event["exception"]["values"][-1]["mechanism"]["type"] == "django" - ) + _content, status, _headers = unpack_werkzeug_response(client.get("/custom/exc")) + assert status.lower() == "500 internal server error" - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - - if middleware_spans: - assert spans[22]["name"] == "/custom/exc" - assert "custom_urlconf_middleware" in render_span_tree(spans) - else: - assert spans[6]["name"] == "/custom/exc" - finally: - settings.MIDDLEWARE.pop(0) - client.application.load_middleware() - else: - events = capture_events() + (error_event,) = (item.payload for item in items if item.type == "event") + assert error_event["transaction"] == "/custom/exc" + assert error_event["exception"]["values"][-1]["mechanism"]["type"] == "django" - try: - content, status, _headers = unpack_werkzeug_response( - client.get("/custom/ok") - ) - assert status.lower() == "200 ok" - assert content == b"custom ok" - - event = events.pop(0) - assert event["transaction"] == "/custom/ok" - if middleware_spans: - assert "custom_urlconf_middleware" in render_span_tree( - event["spans"], event["contexts"]["trace"] - ) - - _content, status, _headers = unpack_werkzeug_response( - client.get("/custom/exc") - ) - assert status.lower() == "500 internal server error" + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] - error_event, transaction_event = events - assert error_event["transaction"] == "/custom/exc" - assert ( - error_event["exception"]["values"][-1]["mechanism"]["type"] == "django" - ) - assert transaction_event["transaction"] == "/custom/exc" - if middleware_spans: - assert "custom_urlconf_middleware" in render_span_tree( - transaction_event["spans"], transaction_event["contexts"]["trace"] - ) - finally: - settings.MIDDLEWARE.pop(0) - client.application.load_middleware() + if middleware_spans: + assert spans[22]["name"] == "/custom/exc" + assert "custom_urlconf_middleware" in render_span_tree(spans) + else: + assert spans[6]["name"] == "/custom/exc" + finally: + settings.MIDDLEWARE.pop(0) + client.application.load_middleware() def test_get_receiver_name(): @@ -2377,13 +1640,10 @@ def dummy(a, b): assert name == "partial()" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_span_origin( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ @@ -2394,47 +1654,30 @@ def test_span_origin( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) signal_span_found = False - if span_streaming: - items = capture_items("span") - - client.get(reverse("view_with_signal")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[-1]["attributes"]["sentry.origin"] == "auto.http.django" - - for span in spans: - assert span["attributes"]["sentry.origin"] == "auto.http.django" - if span["attributes"]["sentry.op"] == "event.django": - signal_span_found = True - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("view_with_signal")) + client.get(reverse("view_with_signal")) - (transaction,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - assert transaction["contexts"]["trace"]["origin"] == "auto.http.django" + assert spans[-1]["attributes"]["sentry.origin"] == "auto.http.django" - for span in transaction["spans"]: - assert span["origin"] == "auto.http.django" - if span["op"] == "event.django": - signal_span_found = True + for span in spans: + assert span["attributes"]["sentry.origin"] == "auto.http.django" + if span["attributes"]["sentry.op"] == "event.django": + signal_span_found = True assert signal_span_found -@pytest.mark.parametrize("span_streaming", [True, False]) def test_transaction_http_method_default( sentry_init, client, - capture_events, capture_items, - span_streaming, ): """ By default OPTIONS and HEAD requests do not create a transaction. @@ -2442,39 +1685,24 @@ def test_transaction_http_method_default( sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get("/nomessage") - client.options("/nomessage") - client.head("/nomessage") - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[2]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "GET" - else: - events = capture_events() + items = capture_items("span") - client.get("/nomessage") - client.options("/nomessage") - client.head("/nomessage") + client.get("/nomessage") + client.options("/nomessage") + client.head("/nomessage") - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - assert len(events) == 1 - assert event["request"]["method"] == "GET" + assert spans[2]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "GET" -@pytest.mark.parametrize("span_streaming", [True, False]) def test_transaction_http_method_custom( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[ @@ -2486,37 +1714,24 @@ def test_transaction_http_method_custom( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get("/nomessage") - client.options("/nomessage") - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[2]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "OPTIONS" + items = capture_items("span") - client.head("/nomessage") + client.get("/nomessage") + client.options("/nomessage") - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - assert spans[5]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "HEAD" - else: - events = capture_events() + assert spans[2]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "OPTIONS" - client.get("/nomessage") - client.options("/nomessage") - client.head("/nomessage") + client.head("/nomessage") - assert len(events) == 2 + sentry_sdk.flush() + spans = [item.payload for item in items] - (event1, event2) = events - assert event1["request"]["method"] == "OPTIONS" - assert event2["request"]["method"] == "HEAD" + assert spans[5]["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "HEAD" def test_get_frame_name_when_in_lazy_object(): diff --git a/tests/integrations/django/test_cache_module.py b/tests/integrations/django/test_cache_module.py index 608adf6e26..61f061a678 100644 --- a/tests/integrations/django/test_cache_module.py +++ b/tests/integrations/django/test_cache_module.py @@ -91,14 +91,11 @@ def use_django_caching_with_cluster(settings): @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_disabled_middleware( sentry_init, client, - capture_events, capture_items, use_django_caching_with_middlewares, - span_streaming, ): sentry_init( integrations=[ @@ -109,38 +106,25 @@ def test_cache_spans_disabled_middleware( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - client.get(reverse("not_cached_view")) - client.get(reverse("not_cached_view")) + client.get(reverse("not_cached_view")) + client.get(reverse("not_cached_view")) - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 2 - else: - events = capture_events() - - client.get(reverse("not_cached_view")) - client.get(reverse("not_cached_view")) - - (first_event, second_event) = events - assert len(first_event["spans"]) == 0 - assert len(second_event["spans"]) == 0 + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 2 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_disabled_decorator( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -151,38 +135,25 @@ def test_cache_spans_disabled_decorator( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 2 - else: - events = capture_events() + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - (first_event, second_event) = events - assert len(first_event["spans"]) == 0 - assert len(second_event["spans"]) == 0 + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 2 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_disabled_templatetag( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -193,38 +164,25 @@ def test_cache_spans_disabled_templatetag( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("view_with_cached_template_fragment")) - client.get(reverse("view_with_cached_template_fragment")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 2 - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("view_with_cached_template_fragment")) - client.get(reverse("view_with_cached_template_fragment")) + client.get(reverse("view_with_cached_template_fragment")) + client.get(reverse("view_with_cached_template_fragment")) - (first_event, second_event) = events - assert len(first_event["spans"]) == 0 - assert len(second_event["spans"]) == 0 + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 2 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_middleware( sentry_init, client, - capture_events, capture_items, use_django_caching_with_middlewares, - span_streaming, ): sentry_init( integrations=[ @@ -235,121 +193,66 @@ def test_cache_spans_middleware( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) client.application.load_middleware() - if span_streaming: - items = capture_items("span") - - client.get(reverse("not_cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - # first_event - cache.get - assert spans[0]["attributes"]["sentry.op"] == "cache.get" - assert spans[0]["name"].startswith("views.decorators.cache.cache_header.") - assert spans[0]["attributes"]["network.peer.address"] is not None - assert spans[0]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert not spans[0]["attributes"]["cache.hit"] - assert "cache.item_size" not in spans[0]["attributes"] - # first_event - cache.put - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert spans[1]["name"].startswith("views.decorators.cache.cache_header.") - assert spans[1]["attributes"]["network.peer.address"] is not None - assert spans[1]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert "cache.hit" not in spans[1]["attributes"] - assert spans[1]["attributes"]["cache.item_size"] == 2 - - client.get(reverse("not_cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - # second_event - cache.get - assert spans[4]["attributes"]["sentry.op"] == "cache.get" - assert spans[4]["name"].startswith("views.decorators.cache.cache_header.") - assert spans[4]["attributes"]["network.peer.address"] is not None - assert spans[4]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert spans[4]["attributes"]["cache.hit"] - assert spans[4]["attributes"]["cache.item_size"] == 2 - # second_event - cache.get 2 - assert spans[5]["attributes"]["sentry.op"] == "cache.get" - assert spans[5]["name"].startswith("views.decorators.cache.cache_page.") - assert spans[5]["attributes"]["network.peer.address"] is not None - assert spans[5]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_page." - ) - assert spans[5]["attributes"]["cache.hit"] - assert spans[5]["attributes"]["cache.item_size"] == 58 - else: - events = capture_events() - - client.get(reverse("not_cached_view")) - client.get(reverse("not_cached_view")) - - (first_event, second_event) = events - # first_event - cache.get - assert first_event["spans"][0]["op"] == "cache.get" - assert first_event["spans"][0]["description"].startswith( - "views.decorators.cache.cache_header." - ) - assert first_event["spans"][0]["data"]["network.peer.address"] is not None - assert first_event["spans"][0]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert not first_event["spans"][0]["data"]["cache.hit"] - assert "cache.item_size" not in first_event["spans"][0]["data"] - # first_event - cache.put - assert first_event["spans"][1]["op"] == "cache.put" - assert first_event["spans"][1]["description"].startswith( - "views.decorators.cache.cache_header." - ) - assert first_event["spans"][1]["data"]["network.peer.address"] is not None - assert first_event["spans"][1]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert "cache.hit" not in first_event["spans"][1]["data"] - assert first_event["spans"][1]["data"]["cache.item_size"] == 2 - # second_event - cache.get - assert second_event["spans"][0]["op"] == "cache.get" - assert second_event["spans"][0]["description"].startswith( - "views.decorators.cache.cache_header." - ) - assert second_event["spans"][0]["data"]["network.peer.address"] is not None - assert second_event["spans"][0]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert second_event["spans"][0]["data"]["cache.hit"] - assert second_event["spans"][0]["data"]["cache.item_size"] == 2 - # second_event - cache.get 2 - assert second_event["spans"][1]["op"] == "cache.get" - assert second_event["spans"][1]["description"].startswith( - "views.decorators.cache.cache_page." - ) - assert second_event["spans"][1]["data"]["network.peer.address"] is not None - assert second_event["spans"][1]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_page." - ) - assert second_event["spans"][1]["data"]["cache.hit"] - assert second_event["spans"][1]["data"]["cache.item_size"] == 58 + items = capture_items("span") + + client.get(reverse("not_cached_view")) + + sentry_sdk.flush() + spans = [item.payload for item in items] + # first_event - cache.get + assert spans[0]["attributes"]["sentry.op"] == "cache.get" + assert spans[0]["name"].startswith("views.decorators.cache.cache_header.") + assert spans[0]["attributes"]["network.peer.address"] is not None + assert spans[0]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_header." + ) + assert not spans[0]["attributes"]["cache.hit"] + assert "cache.item_size" not in spans[0]["attributes"] + # first_event - cache.put + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert spans[1]["name"].startswith("views.decorators.cache.cache_header.") + assert spans[1]["attributes"]["network.peer.address"] is not None + assert spans[1]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_header." + ) + assert "cache.hit" not in spans[1]["attributes"] + assert spans[1]["attributes"]["cache.item_size"] == 2 + + client.get(reverse("not_cached_view")) + + sentry_sdk.flush() + spans = [item.payload for item in items] + # second_event - cache.get + assert spans[4]["attributes"]["sentry.op"] == "cache.get" + assert spans[4]["name"].startswith("views.decorators.cache.cache_header.") + assert spans[4]["attributes"]["network.peer.address"] is not None + assert spans[4]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_header." + ) + assert spans[4]["attributes"]["cache.hit"] + assert spans[4]["attributes"]["cache.item_size"] == 2 + # second_event - cache.get 2 + assert spans[5]["attributes"]["sentry.op"] == "cache.get" + assert spans[5]["name"].startswith("views.decorators.cache.cache_page.") + assert spans[5]["attributes"]["network.peer.address"] is not None + assert spans[5]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_page." + ) + assert spans[5]["attributes"]["cache.hit"] + assert spans[5]["attributes"]["cache.item_size"] == 58 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_decorator( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -360,95 +263,51 @@ def test_cache_spans_decorator( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - # first_event - cache.get - assert spans[0]["attributes"]["sentry.op"] == "cache.get" - assert spans[0]["name"].startswith("views.decorators.cache.cache_header.") - assert spans[0]["attributes"]["network.peer.address"] is not None - assert spans[0]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert not spans[0]["attributes"]["cache.hit"] - assert "cache.item_size" not in spans[0]["attributes"] - # first_event - cache.put - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert spans[1]["name"].startswith("views.decorators.cache.cache_header.") - assert spans[1]["attributes"]["network.peer.address"] is not None - assert spans[1]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert "cache.hit" not in spans[1]["attributes"] - assert spans[1]["attributes"]["cache.item_size"] == 2 - # second_event - cache.get - assert spans[5]["attributes"]["sentry.op"] == "cache.get" - assert spans[5]["name"].startswith("views.decorators.cache.cache_page.") - assert spans[5]["attributes"]["network.peer.address"] is not None - assert spans[5]["attributes"]["cache.key"][0].startswith( - "views.decorators.cache.cache_page." - ) - assert spans[5]["attributes"]["cache.hit"] - assert spans[5]["attributes"]["cache.item_size"] == 58 - else: - events = capture_events() - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - (first_event, second_event) = events - # first_event - cache.get - assert first_event["spans"][0]["op"] == "cache.get" - assert first_event["spans"][0]["description"].startswith( - "views.decorators.cache.cache_header." - ) - assert first_event["spans"][0]["data"]["network.peer.address"] is not None - assert first_event["spans"][0]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert not first_event["spans"][0]["data"]["cache.hit"] - assert "cache.item_size" not in first_event["spans"][0]["data"] - # first_event - cache.put - assert first_event["spans"][1]["op"] == "cache.put" - assert first_event["spans"][1]["description"].startswith( - "views.decorators.cache.cache_header." - ) - assert first_event["spans"][1]["data"]["network.peer.address"] is not None - assert first_event["spans"][1]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_header." - ) - assert "cache.hit" not in first_event["spans"][1]["data"] - assert first_event["spans"][1]["data"]["cache.item_size"] == 2 - # second_event - cache.get - assert second_event["spans"][1]["op"] == "cache.get" - assert second_event["spans"][1]["description"].startswith( - "views.decorators.cache.cache_page." - ) - assert second_event["spans"][1]["data"]["network.peer.address"] is not None - assert second_event["spans"][1]["data"]["cache.key"][0].startswith( - "views.decorators.cache.cache_page." - ) - assert second_event["spans"][1]["data"]["cache.hit"] - assert second_event["spans"][1]["data"]["cache.item_size"] == 58 + items = capture_items("span") + + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) + + sentry_sdk.flush() + spans = [item.payload for item in items] + # first_event - cache.get + assert spans[0]["attributes"]["sentry.op"] == "cache.get" + assert spans[0]["name"].startswith("views.decorators.cache.cache_header.") + assert spans[0]["attributes"]["network.peer.address"] is not None + assert spans[0]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_header." + ) + assert not spans[0]["attributes"]["cache.hit"] + assert "cache.item_size" not in spans[0]["attributes"] + # first_event - cache.put + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert spans[1]["name"].startswith("views.decorators.cache.cache_header.") + assert spans[1]["attributes"]["network.peer.address"] is not None + assert spans[1]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_header." + ) + assert "cache.hit" not in spans[1]["attributes"] + assert spans[1]["attributes"]["cache.item_size"] == 2 + # second_event - cache.get + assert spans[5]["attributes"]["sentry.op"] == "cache.get" + assert spans[5]["name"].startswith("views.decorators.cache.cache_page.") + assert spans[5]["attributes"]["network.peer.address"] is not None + assert spans[5]["attributes"]["cache.key"][0].startswith( + "views.decorators.cache.cache_page." + ) + assert spans[5]["attributes"]["cache.hit"] + assert spans[5]["attributes"]["cache.item_size"] == 58 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_templatetag( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -459,85 +318,43 @@ def test_cache_spans_templatetag( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("view_with_cached_template_fragment")) - client.get(reverse("view_with_cached_template_fragment")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 5 - # first_event - cache.get - assert spans[0]["attributes"]["sentry.op"] == "cache.get" - assert spans[0]["name"].startswith("template.cache.some_identifier.") - assert spans[0]["attributes"]["network.peer.address"] is not None - assert spans[0]["attributes"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert not spans[0]["attributes"]["cache.hit"] - assert "cache.item_size" not in spans[0]["attributes"] - # first_event - cache.put - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert spans[1]["name"].startswith("template.cache.some_identifier.") - assert spans[1]["attributes"]["network.peer.address"] is not None - assert spans[1]["attributes"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert "cache.hit" not in spans[1]["attributes"] - assert spans[1]["attributes"]["cache.item_size"] == 51 - # second_event - cache.get - assert spans[3]["attributes"]["sentry.op"] == "cache.get" - assert spans[3]["name"].startswith("template.cache.some_identifier.") - assert spans[3]["attributes"]["network.peer.address"] is not None - assert spans[3]["attributes"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert spans[3]["attributes"]["cache.hit"] - assert spans[3]["attributes"]["cache.item_size"] == 51 - else: - events = capture_events() - - client.get(reverse("view_with_cached_template_fragment")) - client.get(reverse("view_with_cached_template_fragment")) - - (first_event, second_event) = events - assert len(first_event["spans"]) == 2 - # first_event - cache.get - assert first_event["spans"][0]["op"] == "cache.get" - assert first_event["spans"][0]["description"].startswith( - "template.cache.some_identifier." - ) - assert first_event["spans"][0]["data"]["network.peer.address"] is not None - assert first_event["spans"][0]["data"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert not first_event["spans"][0]["data"]["cache.hit"] - assert "cache.item_size" not in first_event["spans"][0]["data"] - # first_event - cache.put - assert first_event["spans"][1]["op"] == "cache.put" - assert first_event["spans"][1]["description"].startswith( - "template.cache.some_identifier." - ) - assert first_event["spans"][1]["data"]["network.peer.address"] is not None - assert first_event["spans"][1]["data"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert "cache.hit" not in first_event["spans"][1]["data"] - assert first_event["spans"][1]["data"]["cache.item_size"] == 51 - # second_event - cache.get - assert second_event["spans"][0]["op"] == "cache.get" - assert second_event["spans"][0]["description"].startswith( - "template.cache.some_identifier." - ) - assert second_event["spans"][0]["data"]["network.peer.address"] is not None - assert second_event["spans"][0]["data"]["cache.key"][0].startswith( - "template.cache.some_identifier." - ) - assert second_event["spans"][0]["data"]["cache.hit"] - assert second_event["spans"][0]["data"]["cache.item_size"] == 51 + items = capture_items("span") + + client.get(reverse("view_with_cached_template_fragment")) + client.get(reverse("view_with_cached_template_fragment")) + + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 5 + # first_event - cache.get + assert spans[0]["attributes"]["sentry.op"] == "cache.get" + assert spans[0]["name"].startswith("template.cache.some_identifier.") + assert spans[0]["attributes"]["network.peer.address"] is not None + assert spans[0]["attributes"]["cache.key"][0].startswith( + "template.cache.some_identifier." + ) + assert not spans[0]["attributes"]["cache.hit"] + assert "cache.item_size" not in spans[0]["attributes"] + # first_event - cache.put + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert spans[1]["name"].startswith("template.cache.some_identifier.") + assert spans[1]["attributes"]["network.peer.address"] is not None + assert spans[1]["attributes"]["cache.key"][0].startswith( + "template.cache.some_identifier." + ) + assert "cache.hit" not in spans[1]["attributes"] + assert spans[1]["attributes"]["cache.item_size"] == 51 + # second_event - cache.get + assert spans[3]["attributes"]["sentry.op"] == "cache.get" + assert spans[3]["name"].startswith("template.cache.some_identifier.") + assert spans[3]["attributes"]["network.peer.address"] is not None + assert spans[3]["attributes"]["cache.key"][0].startswith( + "template.cache.some_identifier." + ) + assert spans[3]["attributes"]["cache.hit"] + assert spans[3]["attributes"]["cache.item_size"] == 51 @pytest.mark.parametrize( @@ -569,23 +386,17 @@ def test_cache_spans_templatetag( ), # this case should never happen, just making sure that we are not raising an exception in that case. ], ) -@pytest.mark.parametrize("span_streaming", [True, False]) -def test_cache_spans_get_span_name( - method_name, args, kwargs, expected_name, span_streaming -): +def test_cache_spans_get_span_name(method_name, args, kwargs, expected_name): assert _get_span_description(method_name, args, kwargs) == expected_name @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_location_with_port( sentry_init, client, - capture_events, capture_items, use_django_caching_with_port, - span_streaming, ): sentry_init( integrations=[ @@ -596,49 +407,33 @@ def test_cache_spans_location_with_port( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] + items = capture_items("span") - for span in spans: - if span["is_segment"] is True: - continue + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - assert ( - span["attributes"]["network.peer.address"] == "redis://127.0.0.1" - ) # Note: the username/password are not included in the address - assert span["attributes"]["network.peer.port"] == 6379 - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items] - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) + for span in spans: + if span["is_segment"] is True: + continue - for event in events: - for span in event["spans"]: - assert ( - span["data"]["network.peer.address"] == "redis://127.0.0.1" - ) # Note: the username/password are not included in the address - assert span["data"]["network.peer.port"] == 6379 + assert ( + span["attributes"]["network.peer.address"] == "redis://127.0.0.1" + ) # Note: the username/password are not included in the address + assert span["attributes"]["network.peer.port"] == 6379 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_location_without_port( sentry_init, client, - capture_events, capture_items, use_django_caching_without_port, - span_streaming, ): sentry_init( integrations=[ @@ -649,45 +444,31 @@ def test_cache_spans_location_without_port( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) + items = capture_items("span") - sentry_sdk.flush() - spans = [item.payload for item in items] + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - for span in spans: - if span["is_segment"] is True: - continue - - assert span["attributes"]["network.peer.address"] == "redis://example.com" - assert "network.peer.port" not in span["attributes"] - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items] - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) + for span in spans: + if span["is_segment"] is True: + continue - for event in events: - for span in event["spans"]: - assert span["data"]["network.peer.address"] == "redis://example.com" - assert "network.peer.port" not in span["data"] + assert span["attributes"]["network.peer.address"] == "redis://example.com" + assert "network.peer.port" not in span["attributes"] @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_location_with_cluster( sentry_init, client, - capture_events, capture_items, use_django_caching_with_cluster, - span_streaming, ): sentry_init( integrations=[ @@ -698,44 +479,29 @@ def test_cache_spans_location_with_cluster( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - for span in spans: - # because it is a cluster we do not know what host is actually accessed, so we omit the data - assert "network.peer.address" not in span["attributes"].keys() - assert "network.peer.port" not in span["attributes"].keys() - else: - events = capture_events() - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - for event in events: - for span in event["spans"]: - # because it is a cluster we do not know what host is actually accessed, so we omit the data - assert "network.peer.address" not in span["data"].keys() - assert "network.peer.port" not in span["data"].keys() + for span in spans: + # because it is a cluster we do not know what host is actually accessed, so we omit the data + assert "network.peer.address" not in span["attributes"].keys() + assert "network.peer.port" not in span["attributes"].keys() @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_item_size( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -746,75 +512,43 @@ def test_cache_spans_item_size( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 7 - assert spans[0]["attributes"]["sentry.op"] == "cache.get" - assert not spans[0]["attributes"]["cache.hit"] - assert "cache.item_size" not in spans[0]["attributes"] - - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert "cache.hit" not in spans[1]["attributes"] - assert spans[1]["attributes"]["cache.item_size"] == 2 - - assert spans[2]["attributes"]["sentry.op"] == "cache.put" - assert "cache.hit" not in spans[2]["attributes"] - assert spans[2]["attributes"]["cache.item_size"] == 58 - - assert spans[4]["attributes"]["sentry.op"] == "cache.get" - assert spans[4]["attributes"]["cache.hit"] - assert spans[4]["attributes"]["cache.item_size"] == 2 - - assert spans[5]["attributes"]["sentry.op"] == "cache.get" - assert spans[5]["attributes"]["cache.hit"] - assert spans[5]["attributes"]["cache.item_size"] == 58 - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) + client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - (first_event, second_event) = events - assert len(first_event["spans"]) == 3 - assert first_event["spans"][0]["op"] == "cache.get" - assert not first_event["spans"][0]["data"]["cache.hit"] - assert "cache.item_size" not in first_event["spans"][0]["data"] + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 7 + assert spans[0]["attributes"]["sentry.op"] == "cache.get" + assert not spans[0]["attributes"]["cache.hit"] + assert "cache.item_size" not in spans[0]["attributes"] - assert first_event["spans"][1]["op"] == "cache.put" - assert "cache.hit" not in first_event["spans"][1]["data"] - assert first_event["spans"][1]["data"]["cache.item_size"] == 2 + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert "cache.hit" not in spans[1]["attributes"] + assert spans[1]["attributes"]["cache.item_size"] == 2 - assert first_event["spans"][2]["op"] == "cache.put" - assert "cache.hit" not in first_event["spans"][2]["data"] - assert first_event["spans"][2]["data"]["cache.item_size"] == 58 + assert spans[2]["attributes"]["sentry.op"] == "cache.put" + assert "cache.hit" not in spans[2]["attributes"] + assert spans[2]["attributes"]["cache.item_size"] == 58 - assert len(second_event["spans"]) == 2 - assert second_event["spans"][0]["op"] == "cache.get" - assert second_event["spans"][0]["data"]["cache.hit"] - assert second_event["spans"][0]["data"]["cache.item_size"] == 2 + assert spans[4]["attributes"]["sentry.op"] == "cache.get" + assert spans[4]["attributes"]["cache.hit"] + assert spans[4]["attributes"]["cache.item_size"] == 2 - assert second_event["spans"][1]["op"] == "cache.get" - assert second_event["spans"][1]["data"]["cache.hit"] - assert second_event["spans"][1]["data"]["cache.item_size"] == 58 + assert spans[5]["attributes"]["sentry.op"] == "cache.get" + assert spans[5]["attributes"]["cache.hit"] + assert spans[5]["attributes"]["cache.item_size"] == 58 @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_get_custom_default( sentry_init, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -825,109 +559,63 @@ def test_cache_spans_get_custom_default( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) id = os.getpid() from django.core.cache import cache - if span_streaming: - items = capture_items("span") + items = capture_items("span") - with sentry_sdk.traces.start_span(name="custom parent"): - cache.set(f"S{id}", "Sensitive1") - cache.set(f"S{id + 1}", "") + with sentry_sdk.traces.start_span(name="custom parent"): + cache.set(f"S{id}", "Sensitive1") + cache.set(f"S{id + 1}", "") - cache.get(f"S{id}", "null") - cache.get(f"S{id}", default="null") + cache.get(f"S{id}", "null") + cache.get(f"S{id}", default="null") - cache.get(f"S{id + 1}", "null") - cache.get(f"S{id + 1}", default="null") + cache.get(f"S{id + 1}", "null") + cache.get(f"S{id + 1}", default="null") - cache.get(f"S{id + 2}", "null") - cache.get(f"S{id + 2}", default="null") + cache.get(f"S{id + 2}", "null") + cache.get(f"S{id + 2}", default="null") - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 9 + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 9 - assert spans[0]["attributes"]["sentry.op"] == "cache.put" - assert spans[0]["name"] == f"S{id}" + assert spans[0]["attributes"]["sentry.op"] == "cache.put" + assert spans[0]["name"] == f"S{id}" - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert spans[1]["name"] == f"S{id + 1}" + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert spans[1]["name"] == f"S{id + 1}" - for span in (spans[2], spans[3]): - assert span["attributes"]["sentry.op"] == "cache.get" - assert span["name"] == f"S{id}" - assert span["attributes"]["cache.hit"] - assert span["attributes"]["cache.item_size"] == 10 + for span in (spans[2], spans[3]): + assert span["attributes"]["sentry.op"] == "cache.get" + assert span["name"] == f"S{id}" + assert span["attributes"]["cache.hit"] + assert span["attributes"]["cache.item_size"] == 10 - for span in (spans[4], spans[5]): - assert span["attributes"]["sentry.op"] == "cache.get" - assert span["name"] == f"S{id + 1}" - assert span["attributes"]["cache.hit"] - assert span["attributes"]["cache.item_size"] == 0 + for span in (spans[4], spans[5]): + assert span["attributes"]["sentry.op"] == "cache.get" + assert span["name"] == f"S{id + 1}" + assert span["attributes"]["cache.hit"] + assert span["attributes"]["cache.item_size"] == 0 - for span in (spans[6], spans[7]): - assert span["attributes"]["sentry.op"] == "cache.get" - assert span["name"] == f"S{id + 2}" - assert not span["attributes"]["cache.hit"] - assert "cache.item_size" not in span["attributes"] - else: - events = capture_events() - - with sentry_sdk.start_transaction(): - cache.set(f"S{id}", "Sensitive1") - cache.set(f"S{id + 1}", "") - - cache.get(f"S{id}", "null") - cache.get(f"S{id}", default="null") - - cache.get(f"S{id + 1}", "null") - cache.get(f"S{id + 1}", default="null") - - cache.get(f"S{id + 2}", "null") - cache.get(f"S{id + 2}", default="null") - - (transaction,) = events - assert len(transaction["spans"]) == 8 - - assert transaction["spans"][0]["op"] == "cache.put" - assert transaction["spans"][0]["description"] == f"S{id}" - - assert transaction["spans"][1]["op"] == "cache.put" - assert transaction["spans"][1]["description"] == f"S{id + 1}" - - for span in (transaction["spans"][2], transaction["spans"][3]): - assert span["op"] == "cache.get" - assert span["description"] == f"S{id}" - assert span["data"]["cache.hit"] - assert span["data"]["cache.item_size"] == 10 - - for span in (transaction["spans"][4], transaction["spans"][5]): - assert span["op"] == "cache.get" - assert span["description"] == f"S{id + 1}" - assert span["data"]["cache.hit"] - assert span["data"]["cache.item_size"] == 0 - - for span in (transaction["spans"][6], transaction["spans"][7]): - assert span["op"] == "cache.get" - assert span["description"] == f"S{id + 2}" - assert not span["data"]["cache.hit"] - assert "cache.item_size" not in span["data"] + for span in (spans[6], spans[7]): + assert span["attributes"]["sentry.op"] == "cache.get" + assert span["name"] == f"S{id + 2}" + assert not span["attributes"]["cache.hit"] + assert "cache.item_size" not in span["attributes"] @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_get_many( sentry_init, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -938,99 +626,58 @@ def test_cache_spans_get_many( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) id = os.getpid() from django.core.cache import cache - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - cache.get_many([f"S{id}", f"S{id + 1}"]) - cache.set(f"S{id}", "Sensitive1") - cache.get_many([f"S{id}", f"S{id + 1}"]) - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 8 + items = capture_items("span") - assert spans[2]["attributes"]["sentry.op"] == "cache.get" - assert spans[2]["name"] == f"S{id}, S{id + 1}" - assert not spans[2]["attributes"]["cache.hit"] + with sentry_sdk.traces.start_span(name="custom parent"): + cache.get_many([f"S{id}", f"S{id + 1}"]) + cache.set(f"S{id}", "Sensitive1") + cache.get_many([f"S{id}", f"S{id + 1}"]) - assert spans[0]["attributes"]["sentry.op"] == "cache.get" - assert spans[0]["name"] == f"S{id}" - assert not spans[0]["attributes"]["cache.hit"] + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 8 - assert spans[1]["attributes"]["sentry.op"] == "cache.get" - assert spans[1]["name"] == f"S{id + 1}" - assert not spans[1]["attributes"]["cache.hit"] + assert spans[2]["attributes"]["sentry.op"] == "cache.get" + assert spans[2]["name"] == f"S{id}, S{id + 1}" + assert not spans[2]["attributes"]["cache.hit"] - assert spans[3]["attributes"]["sentry.op"] == "cache.put" - assert spans[3]["name"] == f"S{id}" - - assert spans[6]["attributes"]["sentry.op"] == "cache.get" - assert spans[6]["name"] == f"S{id}, S{id + 1}" - assert spans[6]["attributes"]["cache.hit"] - - assert spans[4]["attributes"]["sentry.op"] == "cache.get" - assert spans[4]["name"] == f"S{id}" - assert spans[4]["attributes"]["cache.hit"] - - assert spans[5]["attributes"]["sentry.op"] == "cache.get" - assert spans[5]["name"] == f"S{id + 1}" - assert not spans[5]["attributes"]["cache.hit"] - else: - events = capture_events() + assert spans[0]["attributes"]["sentry.op"] == "cache.get" + assert spans[0]["name"] == f"S{id}" + assert not spans[0]["attributes"]["cache.hit"] - with sentry_sdk.start_transaction(): - cache.get_many([f"S{id}", f"S{id + 1}"]) - cache.set(f"S{id}", "Sensitive1") - cache.get_many([f"S{id}", f"S{id + 1}"]) + assert spans[1]["attributes"]["sentry.op"] == "cache.get" + assert spans[1]["name"] == f"S{id + 1}" + assert not spans[1]["attributes"]["cache.hit"] - (transaction,) = events - assert len(transaction["spans"]) == 7 + assert spans[3]["attributes"]["sentry.op"] == "cache.put" + assert spans[3]["name"] == f"S{id}" - assert transaction["spans"][0]["op"] == "cache.get" - assert transaction["spans"][0]["description"] == f"S{id}, S{id + 1}" - assert not transaction["spans"][0]["data"]["cache.hit"] + assert spans[6]["attributes"]["sentry.op"] == "cache.get" + assert spans[6]["name"] == f"S{id}, S{id + 1}" + assert spans[6]["attributes"]["cache.hit"] - assert transaction["spans"][1]["op"] == "cache.get" - assert transaction["spans"][1]["description"] == f"S{id}" - assert not transaction["spans"][1]["data"]["cache.hit"] + assert spans[4]["attributes"]["sentry.op"] == "cache.get" + assert spans[4]["name"] == f"S{id}" + assert spans[4]["attributes"]["cache.hit"] - assert transaction["spans"][2]["op"] == "cache.get" - assert transaction["spans"][2]["description"] == f"S{id + 1}" - assert not transaction["spans"][2]["data"]["cache.hit"] - - assert transaction["spans"][3]["op"] == "cache.put" - assert transaction["spans"][3]["description"] == f"S{id}" - - assert transaction["spans"][4]["op"] == "cache.get" - assert transaction["spans"][4]["description"] == f"S{id}, S{id + 1}" - assert transaction["spans"][4]["data"]["cache.hit"] - - assert transaction["spans"][5]["op"] == "cache.get" - assert transaction["spans"][5]["description"] == f"S{id}" - assert transaction["spans"][5]["data"]["cache.hit"] - - assert transaction["spans"][6]["op"] == "cache.get" - assert transaction["spans"][6]["description"] == f"S{id + 1}" - assert not transaction["spans"][6]["data"]["cache.hit"] + assert spans[5]["attributes"]["sentry.op"] == "cache.get" + assert spans[5]["name"] == f"S{id + 1}" + assert not spans[5]["attributes"]["cache.hit"] @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_cache_spans_set_many( sentry_init, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -1041,68 +688,43 @@ def test_cache_spans_set_many( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) id = os.getpid() from django.core.cache import cache - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - cache.set_many({f"S{id}": "Sensitive1", f"S{id + 1}": "Sensitive2"}) - cache.get(f"S{id}") - - sentry_sdk.flush() - spans = [item.payload for item in items] - assert len(spans) == 5 - - assert spans[2]["attributes"]["sentry.op"] == "cache.put" - assert spans[2]["name"] == f"S{id}, S{id + 1}" - - assert spans[0]["attributes"]["sentry.op"] == "cache.put" - assert spans[0]["name"] == f"S{id}" + items = capture_items("span") - assert spans[1]["attributes"]["sentry.op"] == "cache.put" - assert spans[1]["name"] == f"S{id + 1}" + with sentry_sdk.traces.start_span(name="custom parent"): + cache.set_many({f"S{id}": "Sensitive1", f"S{id + 1}": "Sensitive2"}) + cache.get(f"S{id}") - assert spans[3]["attributes"]["sentry.op"] == "cache.get" - assert spans[3]["name"] == f"S{id}" - else: - events = capture_events() - - with sentry_sdk.start_transaction(): - cache.set_many({f"S{id}": "Sensitive1", f"S{id + 1}": "Sensitive2"}) - cache.get(f"S{id}") + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 5 - (transaction,) = events - assert len(transaction["spans"]) == 4 + assert spans[2]["attributes"]["sentry.op"] == "cache.put" + assert spans[2]["name"] == f"S{id}, S{id + 1}" - assert transaction["spans"][0]["op"] == "cache.put" - assert transaction["spans"][0]["description"] == f"S{id}, S{id + 1}" + assert spans[0]["attributes"]["sentry.op"] == "cache.put" + assert spans[0]["name"] == f"S{id}" - assert transaction["spans"][1]["op"] == "cache.put" - assert transaction["spans"][1]["description"] == f"S{id}" + assert spans[1]["attributes"]["sentry.op"] == "cache.put" + assert spans[1]["name"] == f"S{id + 1}" - assert transaction["spans"][2]["op"] == "cache.put" - assert transaction["spans"][2]["description"] == f"S{id + 1}" - - assert transaction["spans"][3]["op"] == "cache.get" - assert transaction["spans"][3]["description"] == f"S{id}" + assert spans[3]["attributes"]["sentry.op"] == "cache.get" + assert spans[3]["name"] == f"S{id}" @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_span_origin_cache( sentry_init, client, - capture_events, capture_items, use_django_caching, - span_streaming, ): sentry_init( integrations=[ @@ -1113,35 +735,21 @@ def test_span_origin_cache( ) ], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) cache_span_found = False - if span_streaming: - items = capture_items("span") - - client.get(reverse("cached_view")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[1]["attributes"]["sentry.origin"] == "auto.http.django" - - for span in spans: - assert span["attributes"]["sentry.origin"] == "auto.http.django" - if span["attributes"]["sentry.op"].startswith("cache."): - cache_span_found = True - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("cached_view")) + client.get(reverse("cached_view")) - (transaction,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - assert transaction["contexts"]["trace"]["origin"] == "auto.http.django" + assert spans[1]["attributes"]["sentry.origin"] == "auto.http.django" - for span in transaction["spans"]: - assert span["origin"] == "auto.http.django" - if span["op"].startswith("cache."): - cache_span_found = True + for span in spans: + assert span["attributes"]["sentry.origin"] == "auto.http.django" + if span["attributes"]["sentry.op"].startswith("cache."): + cache_span_found = True assert cache_span_found diff --git a/tests/integrations/django/test_data_scrubbing.py b/tests/integrations/django/test_data_scrubbing.py index 919aa932c3..bbf2be23f1 100644 --- a/tests/integrations/django/test_data_scrubbing.py +++ b/tests/integrations/django/test_data_scrubbing.py @@ -22,17 +22,15 @@ def client(): @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_scrub_django_session_cookies_removed( sentry_init, client, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=False, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) items = capture_items("event") werkzeug_set_cookie(client, "localhost", "sessionid", "123") @@ -46,17 +44,15 @@ def test_scrub_django_session_cookies_removed( @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_scrub_django_session_cookies_filtered( sentry_init, client, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) items = capture_items("event") werkzeug_set_cookie(client, "localhost", "sessionid", "123") @@ -74,13 +70,11 @@ def test_scrub_django_session_cookies_filtered( @pytest.mark.forked @pytest_mark_django_db_decorator() -@pytest.mark.parametrize("span_streaming", [True, False]) def test_scrub_django_custom_session_cookies_filtered( sentry_init, client, capture_items, settings, - span_streaming, ): settings.SESSION_COOKIE_NAME = "my_sess" settings.CSRF_COOKIE_NAME = "csrf_secret" @@ -88,7 +82,7 @@ def test_scrub_django_custom_session_cookies_filtered( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) items = capture_items("event") werkzeug_set_cookie(client, "localhost", "my_sess", "123") diff --git a/tests/integrations/django/test_db_query_data.py b/tests/integrations/django/test_db_query_data.py index 0739b0992b..d7a2bdda34 100644 --- a/tests/integrations/django/test_db_query_data.py +++ b/tests/integrations/django/test_db_query_data.py @@ -14,7 +14,6 @@ from werkzeug.test import Client import sentry_sdk -from sentry_sdk import start_transaction from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.tracing_utils import ( @@ -32,13 +31,10 @@ def client(): @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_disabled( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_options = { "integrations": [DjangoIntegration()], @@ -46,7 +42,7 @@ def test_query_source_disabled( "traces_sample_rate": 1.0, "enable_db_query_source": False, "db_query_source_threshold_ms": 0, - "trace_lifecycle": "stream" if span_streaming else "static", + "trace_lifecycle": "stream", } sentry_init(**sentry_options) @@ -57,70 +53,44 @@ def test_query_source_disabled( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - sentry_sdk.flush() - spans = [item.payload for item in items] - - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) - - assert SPANDATA.CODE_LINE_NUMBER not in attributes - assert SPANDATA.CODE_NAMESPACE not in attributes - assert SPANDATA.CODE_FILE_PATH not in attributes - assert SPANDATA.CODE_FUNCTION not in attributes - break - else: - raise AssertionError("No db span found") - else: - events = capture_events() + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO not in data - assert SPANDATA.CODE_NAMESPACE not in data - assert SPANDATA.CODE_FILEPATH not in data - assert SPANDATA.CODE_FUNCTION not in data - break - else: - raise AssertionError("No db span found") + sentry_sdk.flush() + spans = [item.payload for item in items] + + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) + + assert SPANDATA.CODE_LINE_NUMBER not in attributes + assert SPANDATA.CODE_NAMESPACE not in attributes + assert SPANDATA.CODE_FILE_PATH not in attributes + assert SPANDATA.CODE_FUNCTION not in attributes + break + else: + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) @pytest.mark.parametrize("enable_db_query_source", [None, True]) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_enabled( sentry_init, client, - capture_events, capture_items, enable_db_query_source, - span_streaming, ): sentry_options = { "integrations": [DjangoIntegration()], "send_default_pii": True, "traces_sample_rate": 1.0, "db_query_source_threshold_ms": 0, - "trace_lifecycle": "stream" if span_streaming else "static", + "trace_lifecycle": "stream", } if enable_db_query_source is not None: @@ -134,61 +104,35 @@ def test_query_source_enabled( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - sentry_sdk.flush() - spans = [item.payload for item in items] - - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) - - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes - break - else: - raise AssertionError("No db span found") - else: - events = capture_events() + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data - break - else: - raise AssertionError("No db span found") + sentry_sdk.flush() + spans = [item.payload for item in items] + + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) + + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes + break + else: + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], @@ -196,7 +140,7 @@ def test_query_source( traces_sample_rate=1.0, enable_db_query_source=True, db_query_source_threshold_ms=0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -205,93 +149,51 @@ def test_query_source( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes - assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int - assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 + assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int + assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - assert ( - attributes.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.views" - ) - assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( - "tests/integrations/django/myapp/views.py" - ) + assert ( + attributes.get(SPANDATA.CODE_NAMESPACE) + == "tests.integrations.django.myapp.views" + ) + assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( + "tests/integrations/django/myapp/views.py" + ) - is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep - assert is_relative_path + is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep + assert is_relative_path - assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") + assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" + break else: - events = capture_events() - - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data - - assert type(data.get(SPANDATA.CODE_LINENO)) == int - assert data.get(SPANDATA.CODE_LINENO) > 0 - - assert ( - data.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.views" - ) - assert data.get(SPANDATA.CODE_FILEPATH).endswith( - "tests/integrations/django/myapp/views.py" - ) - - is_relative_path = data.get(SPANDATA.CODE_FILEPATH)[0] != os.sep - assert is_relative_path - - assert data.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_with_module_in_search_path( sentry_init, client, - capture_events, capture_items, - span_streaming, ): """ Test that query source is relative to the path of the module it ran in @@ -304,7 +206,7 @@ def test_query_source_with_module_in_search_path( traces_sample_rate=1.0, enable_db_query_source=True, db_query_source_threshold_ms=0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -313,83 +215,47 @@ def test_query_source_with_module_in_search_path( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_slow_from_supplement")) - ) - assert status == "200 OK" + _, status, _ = unpack_werkzeug_response( + client.get(reverse("postgres_select_slow_from_supplement")) + ) + assert status == "200 OK" - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes - assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int - assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - assert attributes.get(SPANDATA.CODE_NAMESPACE) == "django_helpers.views" - assert ( - attributes.get(SPANDATA.CODE_FILE_PATH) == "django_helpers/views.py" - ) + assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int + assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 + assert attributes.get(SPANDATA.CODE_NAMESPACE) == "django_helpers.views" + assert attributes.get(SPANDATA.CODE_FILE_PATH) == "django_helpers/views.py" - is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep - assert is_relative_path + is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep + assert is_relative_path - assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") + assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" + break else: - events = capture_events() - - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_slow_from_supplement")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data - - assert type(data.get(SPANDATA.CODE_LINENO)) == int - assert data.get(SPANDATA.CODE_LINENO) > 0 - assert data.get(SPANDATA.CODE_NAMESPACE) == "django_helpers.views" - assert data.get(SPANDATA.CODE_FILEPATH) == "django_helpers/views.py" - - is_relative_path = data.get(SPANDATA.CODE_FILEPATH)[0] != os.sep - assert is_relative_path - - assert data.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_with_in_app_exclude( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], @@ -398,7 +264,7 @@ def test_query_source_with_in_app_exclude( enable_db_query_source=True, db_query_source_threshold_ms=0, in_app_exclude=["tests.integrations.django.myapp.views"], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -407,111 +273,60 @@ def test_query_source_with_in_app_exclude( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - sentry_sdk.flush() - spans = [item.payload for item in items] - - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) - - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes - - assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int - assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - - if DJANGO_VERSION >= (1, 11): - assert ( - attributes.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.settings" - ) - assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( - "tests/integrations/django/myapp/settings.py" - ) - assert attributes.get(SPANDATA.CODE_FUNCTION) == "middleware" - else: - assert ( - attributes.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.test_db_query_data" - ) - assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( - "tests/integrations/django/test_db_query_data.py" - ) - assert ( - attributes.get(SPANDATA.CODE_FUNCTION) - == "test_query_source_with_in_app_exclude" - ) - break - else: - raise AssertionError("No db span found") - else: - events = capture_events() + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data - - assert type(data.get(SPANDATA.CODE_LINENO)) == int - assert data.get(SPANDATA.CODE_LINENO) > 0 - - if DJANGO_VERSION >= (1, 11): - assert ( - data.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.settings" - ) - assert data.get(SPANDATA.CODE_FILEPATH).endswith( - "tests/integrations/django/myapp/settings.py" - ) - assert data.get(SPANDATA.CODE_FUNCTION) == "middleware" - else: - assert ( - data.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.test_db_query_data" - ) - assert data.get(SPANDATA.CODE_FILEPATH).endswith( - "tests/integrations/django/test_db_query_data.py" - ) - assert ( - data.get(SPANDATA.CODE_FUNCTION) - == "test_query_source_with_in_app_exclude" - ) - break - else: - raise AssertionError("No db span found") + sentry_sdk.flush() + spans = [item.payload for item in items] + + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) + + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes + + assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int + assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 + + if DJANGO_VERSION >= (1, 11): + assert ( + attributes.get(SPANDATA.CODE_NAMESPACE) + == "tests.integrations.django.myapp.settings" + ) + assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( + "tests/integrations/django/myapp/settings.py" + ) + assert attributes.get(SPANDATA.CODE_FUNCTION) == "middleware" + else: + assert ( + attributes.get(SPANDATA.CODE_NAMESPACE) + == "tests.integrations.django.test_db_query_data" + ) + assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( + "tests/integrations/django/test_db_query_data.py" + ) + assert ( + attributes.get(SPANDATA.CODE_FUNCTION) + == "test_query_source_with_in_app_exclude" + ) + break + else: + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_with_in_app_include( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], @@ -520,7 +335,7 @@ def test_query_source_with_in_app_include( enable_db_query_source=True, db_query_source_threshold_ms=0, in_app_include=["django"], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -529,84 +344,47 @@ def test_query_source_with_in_app_include( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" + _, status, _ = unpack_werkzeug_response(client.get(reverse("postgres_select_orm"))) + assert status == "200 OK" - sentry_sdk.flush() - spans = [item.payload for item in items] + sentry_sdk.flush() + spans = [item.payload for item in items] - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" + ): + attributes = span.get("attributes", {}) - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes - assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int - assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 + assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int + assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - assert ( - attributes.get(SPANDATA.CODE_NAMESPACE) - == "django.db.models.sql.compiler" - ) - assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( - "django/db/models/sql/compiler.py" - ) - assert attributes.get(SPANDATA.CODE_FUNCTION) == "execute_sql" - break - else: - raise AssertionError("No db span found") + assert ( + attributes.get(SPANDATA.CODE_NAMESPACE) + == "django.db.models.sql.compiler" + ) + assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( + "django/db/models/sql/compiler.py" + ) + assert attributes.get(SPANDATA.CODE_FUNCTION) == "execute_sql" + break else: - events = capture_events() - - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data - - assert type(data.get(SPANDATA.CODE_LINENO)) == int - assert data.get(SPANDATA.CODE_LINENO) > 0 - - assert ( - data.get(SPANDATA.CODE_NAMESPACE) == "django.db.models.sql.compiler" - ) - assert data.get(SPANDATA.CODE_FILEPATH).endswith( - "django/db/models/sql/compiler.py" - ) - assert data.get(SPANDATA.CODE_FUNCTION) == "execute_sql" - break - else: - raise AssertionError("No db span found") + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_no_query_source_if_duration_too_short( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], @@ -614,7 +392,7 @@ def test_no_query_source_if_duration_too_short( traces_sample_rate=1.0, enable_db_query_source=True, db_query_source_threshold_ms=100, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -630,89 +408,53 @@ def __init__(self, *args, **kwargs): def __enter__(self): self.span = self._ctx_mgr.__enter__() - if span_streaming: - self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span._end_timestamp = datetime(2024, 1, 1, microsecond=99999) + self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) + self.span._end_timestamp = datetime(2024, 1, 1, microsecond=99999) return self.span def __exit__(self, type, value, traceback): - if span_streaming: - self.span._end_timestamp = None - self._ctx_mgr.__exit__(type, value, traceback) - self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span._end_timestamp = datetime(2024, 1, 1, microsecond=99999) - return - - self.span.start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span.timestamp = datetime(2024, 1, 1, microsecond=99999) + self.span._end_timestamp = None self._ctx_mgr.__exit__(type, value, traceback) + self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) + self.span._end_timestamp = datetime(2024, 1, 1, microsecond=99999) - if span_streaming: - items = capture_items("span") - - with mock.patch( - "sentry_sdk.integrations.django.record_sql_queries", - fake_record_sql_queries, - ): - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - - assert status == "200 OK" + items = capture_items("span") - sentry_sdk.flush() - spans = [item.payload for item in items] + with mock.patch( + "sentry_sdk.integrations.django.record_sql_queries", + fake_record_sql_queries, + ): + _, status, _ = unpack_werkzeug_response( + client.get(reverse("postgres_select_orm")) + ) - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) + assert status == "200 OK" - assert SPANDATA.CODE_LINE_NUMBER not in attributes - assert SPANDATA.CODE_NAMESPACE not in attributes - assert SPANDATA.CODE_FILE_PATH not in attributes - assert SPANDATA.CODE_FUNCTION not in attributes - break - else: - raise AssertionError("No db span found") - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items] - with mock.patch( - "sentry_sdk.integrations.django.record_sql_queries", - fake_record_sql_queries, + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" ): - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - - assert status == "200 OK" + attributes = span.get("attributes", {}) - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) - - assert SPANDATA.CODE_LINENO not in data - assert SPANDATA.CODE_NAMESPACE not in data - assert SPANDATA.CODE_FILEPATH not in data - assert SPANDATA.CODE_FUNCTION not in data - break - else: - raise AssertionError("No db span found") + assert SPANDATA.CODE_LINE_NUMBER not in attributes + assert SPANDATA.CODE_NAMESPACE not in attributes + assert SPANDATA.CODE_FILE_PATH not in attributes + assert SPANDATA.CODE_FUNCTION not in attributes + break + else: + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_query_source_if_duration_over_threshold( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], @@ -720,7 +462,7 @@ def test_query_source_if_duration_over_threshold( traces_sample_rate=1.0, enable_db_query_source=True, db_query_source_threshold_ms=100, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -736,126 +478,74 @@ def __init__(self, *args, **kwargs): def __enter__(self): self.span = self._ctx_mgr.__enter__() - if span_streaming: - self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span._end_timestamp = datetime(2024, 1, 1, microsecond=101000) + self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) + self.span._end_timestamp = datetime(2024, 1, 1, microsecond=101000) return self.span def __exit__(self, type, value, traceback): - if span_streaming: - self.span._end_timestamp = None - self._ctx_mgr.__exit__(type, value, traceback) - self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span._end_timestamp = datetime(2024, 1, 1, microsecond=101000) - return - - self.span.start_timestamp = datetime(2024, 1, 1, microsecond=0) - self.span.timestamp = datetime(2024, 1, 1, microsecond=101000) + self.span._end_timestamp = None self._ctx_mgr.__exit__(type, value, traceback) + self.span._start_timestamp = datetime(2024, 1, 1, microsecond=0) + self.span._end_timestamp = datetime(2024, 1, 1, microsecond=101000) - if span_streaming: - items = capture_items("span") - - with mock.patch( - "sentry_sdk.integrations.django.record_sql_queries", - fake_record_sql_queries, - ): - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - - assert status == "200 OK" - - sentry_sdk.flush() - spans = [item.payload for item in items] + items = capture_items("span") - for span in spans: - if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( - "name" - ): - attributes = span.get("attributes", {}) - - assert SPANDATA.CODE_LINE_NUMBER in attributes - assert SPANDATA.CODE_NAMESPACE in attributes - assert SPANDATA.CODE_FILE_PATH in attributes - assert SPANDATA.CODE_FUNCTION in attributes - - assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int - assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - - assert ( - attributes.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.views" - ) - assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( - "tests/integrations/django/myapp/views.py" - ) + with mock.patch( + "sentry_sdk.integrations.django.record_sql_queries", + fake_record_sql_queries, + ): + _, status, _ = unpack_werkzeug_response( + client.get(reverse("postgres_select_orm")) + ) - is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep - assert is_relative_path + assert status == "200 OK" - assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items] - with mock.patch( - "sentry_sdk.integrations.django.record_sql_queries", - fake_record_sql_queries, + for span in spans: + if span["attributes"].get("sentry.op") == "db" and "auth_user" in span.get( + "name" ): - _, status, _ = unpack_werkzeug_response( - client.get(reverse("postgres_select_orm")) - ) - - assert status == "200 OK" - - (event,) = events - for span in event["spans"]: - if span.get("op") == "db" and "auth_user" in span.get("description"): - data = span.get("data", {}) + attributes = span.get("attributes", {}) - assert SPANDATA.CODE_LINENO in data - assert SPANDATA.CODE_NAMESPACE in data - assert SPANDATA.CODE_FILEPATH in data - assert SPANDATA.CODE_FUNCTION in data + assert SPANDATA.CODE_LINE_NUMBER in attributes + assert SPANDATA.CODE_NAMESPACE in attributes + assert SPANDATA.CODE_FILE_PATH in attributes + assert SPANDATA.CODE_FUNCTION in attributes - assert type(data.get(SPANDATA.CODE_LINENO)) == int - assert data.get(SPANDATA.CODE_LINENO) > 0 + assert type(attributes.get(SPANDATA.CODE_LINE_NUMBER)) == int + assert attributes.get(SPANDATA.CODE_LINE_NUMBER) > 0 - assert ( - data.get(SPANDATA.CODE_NAMESPACE) - == "tests.integrations.django.myapp.views" - ) - assert data.get(SPANDATA.CODE_FILEPATH).endswith( - "tests/integrations/django/myapp/views.py" - ) + assert ( + attributes.get(SPANDATA.CODE_NAMESPACE) + == "tests.integrations.django.myapp.views" + ) + assert attributes.get(SPANDATA.CODE_FILE_PATH).endswith( + "tests/integrations/django/myapp/views.py" + ) - is_relative_path = data.get(SPANDATA.CODE_FILEPATH)[0] != os.sep - assert is_relative_path + is_relative_path = attributes.get(SPANDATA.CODE_FILE_PATH)[0] != os.sep + assert is_relative_path - assert data.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" - break - else: - raise AssertionError("No db span found") + assert attributes.get(SPANDATA.CODE_FUNCTION) == "postgres_select_orm" + break + else: + raise AssertionError("No db span found") @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_span_origin_execute( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -864,105 +554,60 @@ def test_db_span_origin_execute( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_select_orm")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[1]["attributes"]["sentry.origin"] == "auto.http.django" - - for span in spans: - if span["attributes"]["sentry.op"] == "db": - assert span["attributes"]["sentry.origin"] == "auto.db.django" - else: - assert span["attributes"]["sentry.origin"] == "auto.http.django" - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("postgres_select_orm")) + client.get(reverse("postgres_select_orm")) - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - assert event["contexts"]["trace"]["origin"] == "auto.http.django" + assert spans[1]["attributes"]["sentry.origin"] == "auto.http.django" - for span in event["spans"]: - if span["op"] == "db": - assert span["origin"] == "auto.db.django" - else: - assert span["origin"] == "auto.http.django" + for span in spans: + if span["attributes"]["sentry.op"] == "db": + assert span["attributes"]["sentry.origin"] == "auto.db.django" + else: + assert span["attributes"]["sentry.origin"] == "auto.http.django" @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_span_origin_executemany( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: pytest.skip("postgres tests disabled") - if span_streaming: - items = capture_items("span") - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - cursor = connection.cursor() - - query = """UPDATE auth_user SET username = %s where id = %s;""" - query_list = ( - ( - "test1", - 1, - ), - ( - "test2", - 2, - ), - ) - cursor.executemany(query, query_list) - - transaction.commit() - - sentry_sdk.flush() - spans = [item.payload for item in items] - - assert spans[1]["attributes"]["sentry.origin"] == "manual" - assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" - else: - events = capture_events() - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - cursor = connection.cursor() - - query = """UPDATE auth_user SET username = %s where id = %s;""" - query_list = ( - ( - "test1", - 1, - ), - ( - "test2", - 2, - ), - ) - cursor.executemany(query, query_list) + items = capture_items("span") + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction + + cursor = connection.cursor() + + query = """UPDATE auth_user SET username = %s where id = %s;""" + query_list = ( + ( + "test1", + 1, + ), + ( + "test2", + 2, + ), + ) + cursor.executemany(query, query_list) - transaction.commit() + transaction.commit() - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - assert event["contexts"]["trace"]["origin"] == "manual" - assert event["spans"][0]["origin"] == "auto.db.django" + assert spans[1]["attributes"]["sentry.origin"] == "manual" + assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" diff --git a/tests/integrations/django/test_db_transactions.py b/tests/integrations/django/test_db_transactions.py index 3b5dadfea7..0e51043906 100644 --- a/tests/integrations/django/test_db_transactions.py +++ b/tests/integrations/django/test_db_transactions.py @@ -1,4 +1,3 @@ -import itertools import os from datetime import datetime @@ -14,7 +13,6 @@ from werkzeug.test import Client import sentry_sdk -from sentry_sdk import start_transaction from sentry_sdk.consts import SPANDATA, SPANNAME from sentry_sdk.integrations.django import DjangoIntegration from tests.integrations.django.myapp.wsgi import application @@ -28,18 +26,15 @@ def client(): @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_transaction_spans_disabled_no_autocommit( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -48,18 +43,17 @@ def test_db_transaction_spans_disabled_no_autocommit( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") + items = capture_items("span") - client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) - client.get(reverse("postgres_insert_orm_no_autocommit")) + client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) + client.get(reverse("postgres_insert_orm_no_autocommit")) - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - cursor = connection.cursor() + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -72,34 +66,34 @@ def test_db_transaction_spans_disabled_no_autocommit( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.rollback() - transaction.set_autocommit(True) + transaction.set_autocommit(False) + cursor.executemany(query, query_list) + transaction.rollback() + transaction.set_autocommit(True) - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - cursor = connection.cursor() + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -112,65 +106,85 @@ def test_db_transaction_spans_disabled_no_autocommit( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) + + transaction.set_autocommit(False) + cursor.executemany(query, query_list) + transaction.commit() + transaction.set_autocommit(True) + + sentry_sdk.flush() + spans = [item.payload for item in items] + + postgres_rollback = spans[4] + assert postgres_rollback["is_segment"] is True + postgres_commit = spans[9] + assert postgres_commit["is_segment"] is True + sqlite_rollback = spans[11] + assert sqlite_rollback["is_segment"] is True + sqlite_commit = spans[13] + assert sqlite_commit["is_segment"] is True + + # Ensure operation is persisted + assert User.objects.using("postgres").exists() + + assert postgres_rollback["attributes"]["sentry.origin"] == "auto.http.django" + assert postgres_commit["attributes"]["sentry.origin"] == "auto.http.django" + assert sqlite_rollback["attributes"]["sentry.origin"] == "manual" + assert sqlite_commit["attributes"]["sentry.origin"] == "manual" + + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + or span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] + assert len(commit_spans) == 0 - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.commit() - transaction.set_autocommit(True) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - postgres_rollback = spans[4] - assert postgres_rollback["is_segment"] is True - postgres_commit = spans[9] - assert postgres_commit["is_segment"] is True - sqlite_rollback = spans[11] - assert sqlite_rollback["is_segment"] is True - sqlite_commit = spans[13] - assert sqlite_commit["is_segment"] is True - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() - - assert postgres_rollback["attributes"]["sentry.origin"] == "auto.http.django" - assert postgres_commit["attributes"]["sentry.origin"] == "auto.http.django" - assert sqlite_rollback["attributes"]["sentry.origin"] == "manual" - assert sqlite_commit["attributes"]["sentry.origin"] == "manual" - - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - or span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] - assert len(commit_spans) == 0 - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) - client.get(reverse("postgres_insert_orm_no_autocommit")) - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction +@pytest.mark.forked +@pytest_mark_django_db_decorator(transaction=True) +def test_db_transaction_spans_disabled_atomic( + sentry_init, + client, + capture_items, +): + sentry_init( + integrations=[DjangoIntegration()], + traces_sample_rate=1.0, + trace_lifecycle="stream", + ) + + if "postgres" not in connections: + pytest.skip("postgres tests disabled") + + # trigger Django to open a new connection by marking the existing one as None. + connections["postgres"].connection = None + + items = capture_items("span") + + client.get(reverse("postgres_insert_orm_atomic_rollback")) + client.get(reverse("postgres_insert_orm_atomic")) + + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction + + with transaction.atomic(): cursor = connection.cursor() query = """INSERT INTO auth_user ( @@ -202,15 +216,13 @@ def test_db_transaction_spans_disabled_no_autocommit( datetime(1970, 1, 1), ), ) - - transaction.set_autocommit(False) cursor.executemany(query, query_list) - transaction.rollback() - transaction.set_autocommit(True) + transaction.set_rollback(True) - with start_transaction(name="test_transaction"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction + with transaction.atomic(): cursor = connection.cursor() query = """INSERT INTO auth_user ( @@ -242,278 +254,40 @@ def test_db_transaction_spans_disabled_no_autocommit( datetime(1970, 1, 1), ), ) - - transaction.set_autocommit(False) cursor.executemany(query, query_list) - transaction.commit() - transaction.set_autocommit(True) - - (postgres_rollback, postgres_commit, sqlite_rollback, sqlite_commit) = events - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() - - assert postgres_rollback["contexts"]["trace"]["origin"] == "auto.http.django" - assert postgres_commit["contexts"]["trace"]["origin"] == "auto.http.django" - assert sqlite_rollback["contexts"]["trace"]["origin"] == "manual" - assert sqlite_commit["contexts"]["trace"]["origin"] == "manual" - - commit_spans = [ - span - for span in itertools.chain( - postgres_rollback["spans"], - postgres_commit["spans"], - sqlite_rollback["spans"], - sqlite_commit["spans"], - ) - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - or span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] - assert len(commit_spans) == 0 - - -@pytest.mark.forked -@pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) -def test_db_transaction_spans_disabled_atomic( - sentry_init, - client, - capture_events, - capture_items, - span_streaming, -): - sentry_init( - integrations=[DjangoIntegration()], - traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", - ) - - if "postgres" not in connections: - pytest.skip("postgres tests disabled") - - # trigger Django to open a new connection by marking the existing one as None. - connections["postgres"].connection = None - - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_atomic_rollback")) - client.get(reverse("postgres_insert_orm_atomic")) - - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - transaction.set_rollback(True) - - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - postgres_rollback = spans[4] - assert postgres_rollback["is_segment"] is True - postgres_commit = spans[9] - assert postgres_commit["is_segment"] is True - sqlite_rollback = spans[12] - assert sqlite_rollback["is_segment"] is True - sqlite_commit = spans[15] - assert sqlite_commit["is_segment"] is True - - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - or span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_atomic_rollback")) - client.get(reverse("postgres_insert_orm_atomic")) - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - transaction.set_rollback(True) - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - - (postgres_rollback, postgres_commit, sqlite_rollback, sqlite_commit) = events - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() - - assert postgres_rollback["contexts"]["trace"]["origin"] == "auto.http.django" - assert postgres_commit["contexts"]["trace"]["origin"] == "auto.http.django" - assert sqlite_rollback["contexts"]["trace"]["origin"] == "manual" - assert sqlite_commit["contexts"]["trace"]["origin"] == "manual" - - commit_spans = [ - span - for span in itertools.chain( - postgres_rollback["spans"], - postgres_commit["spans"], - sqlite_rollback["spans"], - sqlite_commit["spans"], - ) - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - or span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] + sentry_sdk.flush() + spans = [item.payload for item in items] + + postgres_rollback = spans[4] + assert postgres_rollback["is_segment"] is True + postgres_commit = spans[9] + assert postgres_commit["is_segment"] is True + sqlite_rollback = spans[12] + assert sqlite_rollback["is_segment"] is True + sqlite_commit = spans[15] + assert sqlite_commit["is_segment"] is True + + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + or span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] assert len(commit_spans) == 0 @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_no_autocommit_execute( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -522,89 +296,44 @@ def test_db_no_autocommit_execute( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_no_autocommit")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() - - assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - ] - - assert len(commit_spans) == 1 - commit_span = commit_spans[0] - - assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert commit_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert commit_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("postgres_insert_orm_no_autocommit")) + client.get(reverse("postgres_insert_orm_no_autocommit")) - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - # Ensure operation is persisted - assert User.objects.using("postgres").exists() + # Ensure operation is persisted + assert User.objects.using("postgres").exists() - assert event["contexts"]["trace"]["origin"] == "auto.http.django" + assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - commit_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - ] + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + ] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] + assert len(commit_spans) == 1 + commit_span = commit_spans[0] - assert commit_span["origin"] == "auto.db.django" + assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - # Verify other database attributes - assert commit_span["data"].get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert commit_span["data"].get(SPANDATA.DB_NAME) is not None - assert commit_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert commit_span["data"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert commit_span["data"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + # Verify other database attributes + assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert commit_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert commit_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] assert len(insert_spans) == 1 insert_span = insert_spans[0] @@ -614,27 +343,23 @@ def test_db_no_autocommit_execute( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_no_autocommit_executemany( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - cursor = connection.cursor() + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -647,134 +372,57 @@ def test_db_no_autocommit_executemany( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.commit() - transaction.set_autocommit(True) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is persisted - assert User.objects.exists() - - assert spans[2]["attributes"]["sentry.origin"] == "manual" - assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" - - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - ] - - assert len(commit_spans) == 1 - commit_span = commit_spans[0] - - assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" - conn_params = connection.get_connection_params() - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( - "database" - ) or conn_params.get("dbname") - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.commit() - transaction.set_autocommit(True) + transaction.set_autocommit(False) + cursor.executemany(query, query_list) + transaction.commit() + transaction.set_autocommit(True) - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - # Ensure operation is persisted - assert User.objects.exists() + # Ensure operation is persisted + assert User.objects.exists() - assert event["contexts"]["trace"]["origin"] == "manual" - assert event["spans"][0]["origin"] == "auto.db.django" + assert spans[2]["attributes"]["sentry.origin"] == "manual" + assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" - commit_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - ] + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + ] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] + assert len(commit_spans) == 1 + commit_span = commit_spans[0] - assert commit_span["origin"] == "auto.db.django" + assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - # Verify other database attributes - assert commit_span["data"].get(SPANDATA.DB_SYSTEM) == "sqlite" - conn_params = connection.get_connection_params() - assert commit_span["data"].get(SPANDATA.DB_NAME) is not None - assert commit_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") + # Verify other database attributes + assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" + conn_params = connection.get_connection_params() + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] # Verify queries and commit statements are siblings for insert_span in insert_spans: @@ -783,18 +431,15 @@ def test_db_no_autocommit_executemany( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_no_autocommit_rollback_execute( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -803,90 +448,44 @@ def test_db_no_autocommit_rollback_execute( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() - - assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] + items = capture_items("span") - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] + client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" + sentry_sdk.flush() + spans = [item.payload for item in items] - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - assert rollback_span["attributes"].get( - SPANDATA.SERVER_ADDRESS - ) == os.environ.get("SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost") - assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_no_autocommit_rollback")) + # Ensure operation is rolled back + assert not User.objects.using("postgres").exists() - (event,) = events + assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] - assert event["contexts"]["trace"]["origin"] == "auto.http.django" + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert rollback_span["data"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert rollback_span["data"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert rollback_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] assert len(insert_spans) == 1 insert_span = insert_spans[0] @@ -896,166 +495,85 @@ def test_db_no_autocommit_rollback_execute( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_no_autocommit_rollback_executemany( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) + items = capture_items("span") - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.rollback() - transaction.set_autocommit(True) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.exists() - - assert spans[2]["attributes"]["sentry.origin"] == "manual" - assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" - - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - cursor = connection.cursor() + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) + is_superuser, + username, + first_name, + last_name, + email, + is_staff, + is_active, + date_joined +) +VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - transaction.set_autocommit(False) - cursor.executemany(query, query_list) - transaction.rollback() - transaction.set_autocommit(True) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) - (event,) = events + transaction.set_autocommit(False) + cursor.executemany(query, query_list) + transaction.rollback() + transaction.set_autocommit(True) - # Ensure operation is rolled back - assert not User.objects.exists() + sentry_sdk.flush() + spans = [item.payload for item in items] - assert event["contexts"]["trace"]["origin"] == "manual" - assert event["spans"][0]["origin"] == "auto.db.django" + # Ensure operation is rolled back + assert not User.objects.exists() - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] + assert spans[2]["attributes"]["sentry.origin"] == "manual" + assert spans[0]["attributes"]["sentry.origin"] == "auto.db.django" - assert rollback_span["origin"] == "auto.db.django" + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" + conn_params = connection.get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] # Verify queries and rollback statements are siblings for insert_span in insert_spans: @@ -1064,18 +582,15 @@ def test_db_no_autocommit_rollback_executemany( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_execute( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -1084,89 +599,44 @@ def test_db_atomic_execute( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_atomic")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() + items = capture_items("span") - assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" + client.get(reverse("postgres_insert_orm_atomic")) - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - ] + sentry_sdk.flush() + spans = [item.payload for item in items] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] + # Ensure operation is persisted + assert User.objects.using("postgres").exists() - assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" + assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - # Verify other database attributes - assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert commit_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert commit_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_atomic")) - - (event,) = events - - # Ensure operation is persisted - assert User.objects.using("postgres").exists() - - assert event["contexts"]["trace"]["origin"] == "auto.http.django" - - commit_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - ] + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + ] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] + assert len(commit_spans) == 1 + commit_span = commit_spans[0] - assert commit_span["origin"] == "auto.db.django" + assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - # Verify other database attributes - assert commit_span["data"].get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert commit_span["data"].get(SPANDATA.DB_NAME) is not None - assert commit_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert commit_span["data"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert commit_span["data"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + # Verify other database attributes + assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert commit_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert commit_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] assert len(insert_spans) == 1 insert_span = insert_spans[0] @@ -1176,98 +646,25 @@ def test_db_atomic_execute( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_executemany( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - - sentry_sdk.flush() - spans = [item.payload for item in items] + items = capture_items("span") - # Ensure operation is persisted - assert User.objects.exists() + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - assert spans[3]["attributes"]["sentry.origin"] == "manual" - - commit_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT - ] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] - - assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" - conn_params = connection.get_connection_params() - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( - "database" - ) or conn_params.get("dbname") - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() + with transaction.atomic(): + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -1280,54 +677,51 @@ def test_db_atomic_executemany( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) + cursor.executemany(query, query_list) - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - # Ensure operation is persisted - assert User.objects.exists() + # Ensure operation is persisted + assert User.objects.exists() - assert event["contexts"]["trace"]["origin"] == "manual" + assert spans[3]["attributes"]["sentry.origin"] == "manual" - commit_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_COMMIT - ] - assert len(commit_spans) == 1 - commit_span = commit_spans[0] + commit_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_COMMIT + ] + assert len(commit_spans) == 1 + commit_span = commit_spans[0] - assert commit_span["origin"] == "auto.db.django" + assert commit_span["attributes"]["sentry.origin"] == "auto.db.django" - # Verify other database attributes - assert commit_span["data"].get(SPANDATA.DB_SYSTEM) == "sqlite" - conn_params = connection.get_connection_params() - assert commit_span["data"].get(SPANDATA.DB_NAME) is not None - assert commit_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") + # Verify other database attributes + assert commit_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" + conn_params = connection.get_connection_params() + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert commit_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] # Verify queries and commit statements are siblings for insert_span in insert_spans: @@ -1336,19 +730,16 @@ def test_db_atomic_executemany( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_rollback_execute( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -1357,90 +748,44 @@ def test_db_atomic_rollback_execute( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_atomic_rollback")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() + items = capture_items("span") - assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" + client.get(reverse("postgres_insert_orm_atomic_rollback")) - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] + sentry_sdk.flush() + spans = [item.payload for item in items] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] + # Ensure operation is rolled back + assert not User.objects.using("postgres").exists() - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" + assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - assert rollback_span["attributes"].get( - SPANDATA.SERVER_ADDRESS - ) == os.environ.get("SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost") - assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_atomic_rollback")) - - (event,) = events + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] - assert event["contexts"]["trace"]["origin"] == "auto.http.django" + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] - - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert rollback_span["data"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert rollback_span["data"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert rollback_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] assert len(insert_spans) == 1 insert_span = insert_spans[0] @@ -1451,101 +796,25 @@ def test_db_atomic_rollback_execute( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_rollback_executemany( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - transaction.set_rollback(True) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.exists() + items = capture_items("span") - assert spans[3]["attributes"]["sentry.origin"] == "manual" + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] - - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - with transaction.atomic(): - cursor = connection.cursor() + with transaction.atomic(): + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -1558,56 +827,53 @@ def test_db_atomic_rollback_executemany( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - transaction.set_rollback(True) + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) + cursor.executemany(query, query_list) + transaction.set_rollback(True) - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - # Ensure operation is rolled back - assert not User.objects.exists() + # Ensure operation is rolled back + assert not User.objects.exists() - assert event["contexts"]["trace"]["origin"] == "manual" + assert spans[3]["attributes"]["sentry.origin"] == "manual" - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] - assert rollback_span["origin"] == "auto.db.django" + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" + conn_params = connection.get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] # Verify queries and rollback statements are siblings for insert_span in insert_spans: @@ -1616,19 +882,16 @@ def test_db_atomic_rollback_executemany( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_execute_exception( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) if "postgres" not in connections: @@ -1637,90 +900,44 @@ def test_db_atomic_execute_exception( # trigger Django to open a new connection by marking the existing one as None. connections["postgres"].connection = None - if span_streaming: - items = capture_items("span") - - client.get(reverse("postgres_insert_orm_atomic_exception")) - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() + items = capture_items("span") - assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" + client.get(reverse("postgres_insert_orm_atomic_exception")) - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] + sentry_sdk.flush() + spans = [item.payload for item in items] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] + # Ensure operation is rolled back + assert not User.objects.using("postgres").exists() - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" + assert spans[5]["attributes"]["sentry.origin"] == "auto.http.django" - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - assert rollback_span["attributes"].get( - SPANDATA.SERVER_ADDRESS - ) == os.environ.get("SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost") - assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - client.get(reverse("postgres_insert_orm_atomic_exception")) - - (event,) = events + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] - # Ensure operation is rolled back - assert not User.objects.using("postgres").exists() + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] - assert event["contexts"]["trace"]["origin"] == "auto.http.django" + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] - - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert rollback_span["data"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert rollback_span["data"].get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert rollback_span["attributes"].get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert rollback_span["attributes"].get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] assert len(insert_spans) == 1 insert_span = insert_spans[0] @@ -1730,30 +947,26 @@ def test_db_atomic_execute_exception( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_atomic_executemany_exception( sentry_init, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(db_transaction_spans=True)], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") + items = capture_items("span") - with sentry_sdk.traces.start_span(name="custom parent"): - from django.db import connection, transaction + with sentry_sdk.traces.start_span(name="custom parent"): + from django.db import connection, transaction - try: - with transaction.atomic(): - cursor = connection.cursor() + try: + with transaction.atomic(): + cursor = connection.cursor() - query = """INSERT INTO auth_user ( + query = """INSERT INTO auth_user ( password, is_superuser, username, @@ -1766,131 +979,54 @@ def test_db_atomic_executemany_exception( ) VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - 1 / 0 - except ZeroDivisionError: - pass - - sentry_sdk.flush() - spans = [item.payload for item in items] - - # Ensure operation is rolled back - assert not User.objects.exists() - - assert spans[3]["attributes"]["sentry.origin"] == "manual" - - rollback_spans = [ - span - for span in spans - if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) - == SPANNAME.DB_ROLLBACK - ] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None - assert rollback_span["attributes"].get( - SPANDATA.DB_NAMESPACE - ) == conn_params.get("database") or conn_params.get("dbname") - - insert_spans = [ - span for span in spans if span["name"].startswith("INSERT INTO") - ] - else: - events = capture_events() - - with start_transaction(name="test_transaction"): - from django.db import connection, transaction - - try: - with transaction.atomic(): - cursor = connection.cursor() - - query = """INSERT INTO auth_user ( - password, - is_superuser, - username, - first_name, - last_name, - email, - is_staff, - is_active, - date_joined -) -VALUES ('password', false, %s, %s, %s, %s, false, true, %s);""" + query_list = ( + ( + "user1", + "John", + "Doe", + "user1@example.com", + datetime(1970, 1, 1), + ), + ( + "user2", + "Max", + "Mustermann", + "user2@example.com", + datetime(1970, 1, 1), + ), + ) + cursor.executemany(query, query_list) + 1 / 0 + except ZeroDivisionError: + pass + + sentry_sdk.flush() + spans = [item.payload for item in items] + + # Ensure operation is rolled back + assert not User.objects.exists() + + assert spans[3]["attributes"]["sentry.origin"] == "manual" + + rollback_spans = [ + span + for span in spans + if span["attributes"].get(SPANDATA.DB_OPERATION_NAME) == SPANNAME.DB_ROLLBACK + ] + assert len(rollback_spans) == 1 + rollback_span = rollback_spans[0] + + assert rollback_span["attributes"]["sentry.origin"] == "auto.db.django" + + # Verify other database attributes + assert rollback_span["attributes"].get(SPANDATA.DB_SYSTEM_NAME) == "sqlite" + conn_params = connection.get_connection_params() + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) is not None + assert rollback_span["attributes"].get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") - query_list = ( - ( - "user1", - "John", - "Doe", - "user1@example.com", - datetime(1970, 1, 1), - ), - ( - "user2", - "Max", - "Mustermann", - "user2@example.com", - datetime(1970, 1, 1), - ), - ) - cursor.executemany(query, query_list) - 1 / 0 - except ZeroDivisionError: - pass - - (event,) = events - - # Ensure operation is rolled back - assert not User.objects.exists() - - assert event["contexts"]["trace"]["origin"] == "manual" - - rollback_spans = [ - span - for span in event["spans"] - if span["data"].get(SPANDATA.DB_OPERATION) == SPANNAME.DB_ROLLBACK - ] - assert len(rollback_spans) == 1 - rollback_span = rollback_spans[0] - - assert rollback_span["origin"] == "auto.db.django" - - # Verify other database attributes - assert rollback_span["data"].get(SPANDATA.DB_SYSTEM) == "sqlite" - conn_params = connection.get_connection_params() - assert rollback_span["data"].get(SPANDATA.DB_NAME) is not None - assert rollback_span["data"].get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - - insert_spans = [ - span - for span in event["spans"] - if span["description"].startswith("INSERT INTO") - ] + insert_spans = [span for span in spans if span["name"].startswith("INSERT INTO")] # Verify queries and rollback statements are siblings for insert_span in insert_spans: diff --git a/tests/integrations/django/test_tasks.py b/tests/integrations/django/test_tasks.py index 674ef53f0e..fc388a0350 100644 --- a/tests/integrations/django/test_tasks.py +++ b/tests/integrations/django/test_tasks.py @@ -51,60 +51,36 @@ def task_two(): not HAS_DJANGO_TASKS, reason="Django tasks are only available in Django 6.0+", ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_task_span_is_created( sentry_init, - capture_events, capture_items, immediate_backend, - span_streaming, ): """Test that the queue.submit.django span is created when a task is enqueued.""" sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - simple_task.enqueue() - - sentry_sdk.flush() - spans = [item.payload for item in items] - - queue_submit_spans = [ - span - for span in spans - if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["name"] - == "tests.integrations.django.test_tasks.simple_task" - ) - assert ( - queue_submit_spans[0]["attributes"]["sentry.origin"] == "auto.http.django" - ) - else: - events = capture_events() - - with sentry_sdk.start_transaction(name="test_transaction"): - simple_task.enqueue() - - (event,) = events - assert event["type"] == "transaction" - - queue_submit_spans = [ - span for span in event["spans"] if span["op"] == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["description"] - == "tests.integrations.django.test_tasks.simple_task" - ) - assert queue_submit_spans[0]["origin"] == "auto.http.django" + items = capture_items("span") + + with sentry_sdk.traces.start_span(name="custom parent"): + simple_task.enqueue() + + sentry_sdk.flush() + spans = [item.payload for item in items] + + queue_submit_spans = [ + span + for span in spans + if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO + ] + assert len(queue_submit_spans) == 1 + assert ( + queue_submit_spans[0]["name"] + == "tests.integrations.django.test_tasks.simple_task" + ) + assert queue_submit_spans[0]["attributes"]["sentry.origin"] == "auto.http.django" @pytest.mark.skipif( @@ -128,179 +104,108 @@ def test_task_enqueue_returns_result(sentry_init, immediate_backend): not HAS_DJANGO_TASKS, reason="Django tasks are only available in Django 6.0+", ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_task_enqueue_with_kwargs( sentry_init, immediate_backend, - capture_events, capture_items, - span_streaming, ): """Test that task enqueuing works correctly with keyword arguments.""" sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - result = greet.enqueue(name="World", greeting="Hi") - - assert result.return_value == "Hi, World!" - - sentry_sdk.flush() - spans = [item.payload for item in items] - - queue_submit_spans = [ - span - for span in spans - if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["name"] - == "tests.integrations.django.test_tasks.greet" - ) - else: - events = capture_events() - - with sentry_sdk.start_transaction(name="test_transaction"): - result = greet.enqueue(name="World", greeting="Hi") - - assert result.return_value == "Hi, World!" - - (event,) = events - queue_submit_spans = [ - span for span in event["spans"] if span["op"] == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["description"] - == "tests.integrations.django.test_tasks.greet" - ) + items = capture_items("span") + + with sentry_sdk.traces.start_span(name="custom parent"): + result = greet.enqueue(name="World", greeting="Hi") + + assert result.return_value == "Hi, World!" + + sentry_sdk.flush() + spans = [item.payload for item in items] + + queue_submit_spans = [ + span + for span in spans + if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO + ] + assert len(queue_submit_spans) == 1 + assert queue_submit_spans[0]["name"] == "tests.integrations.django.test_tasks.greet" @pytest.mark.skipif( not HAS_DJANGO_TASKS, reason="Django tasks are only available in Django 6.0+", ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_task_error_reporting( sentry_init, immediate_backend, - capture_events, capture_items, - span_streaming, ): """Test that errors in tasks are correctly reported and don't break the span.""" sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - result = failing_task.enqueue() - - with pytest.raises(ValueError, match="Task failed"): - _ = result.return_value - - sentry_sdk.flush() - spans = [item.payload for item in items] + items = capture_items("span") - queue_submit_spans = [ - span - for span in spans - if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO - ] + with sentry_sdk.traces.start_span(name="custom parent"): + result = failing_task.enqueue() - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["name"] - == "tests.integrations.django.test_tasks.failing_task" - ) - else: - events = capture_events() + with pytest.raises(ValueError, match="Task failed"): + _ = result.return_value - with sentry_sdk.start_transaction(name="test_transaction"): - result = failing_task.enqueue() + sentry_sdk.flush() + spans = [item.payload for item in items] - with pytest.raises(ValueError, match="Task failed"): - _ = result.return_value + queue_submit_spans = [ + span + for span in spans + if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO + ] - assert len(events) == 2 - transaction_event = events[-1] - assert transaction_event["type"] == "transaction" - - queue_submit_spans = [ - span - for span in transaction_event["spans"] - if span["op"] == OP.QUEUE_SUBMIT_DJANGO - ] - - assert len(queue_submit_spans) == 1 - assert ( - queue_submit_spans[0]["description"] - == "tests.integrations.django.test_tasks.failing_task" - ) + assert len(queue_submit_spans) == 1 + assert ( + queue_submit_spans[0]["name"] + == "tests.integrations.django.test_tasks.failing_task" + ) @pytest.mark.skipif( not HAS_DJANGO_TASKS, reason="Django tasks are only available in Django 6.0+", ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_multiple_task_enqueues_create_multiple_spans( sentry_init, - capture_events, capture_items, immediate_backend, - span_streaming, ): """Test that enqueueing multiple tasks creates multiple spans.""" sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="custom parent"): - task_one.enqueue() - task_two.enqueue() - task_one.enqueue() - - sentry_sdk.flush() - spans = [item.payload for item in items] - - queue_submit_spans = [ - span - for span in spans - if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 3 - - span_names = [span["name"] for span in queue_submit_spans] - else: - events = capture_events() - - with sentry_sdk.start_transaction(name="test_transaction"): - task_one.enqueue() - task_two.enqueue() - task_one.enqueue() - - (event,) = events - queue_submit_spans = [ - span for span in event["spans"] if span["op"] == OP.QUEUE_SUBMIT_DJANGO - ] - assert len(queue_submit_spans) == 3 - - span_names = [span["description"] for span in queue_submit_spans] + items = capture_items("span") + + with sentry_sdk.traces.start_span(name="custom parent"): + task_one.enqueue() + task_two.enqueue() + task_one.enqueue() + + sentry_sdk.flush() + spans = [item.payload for item in items] + + queue_submit_spans = [ + span + for span in spans + if span["attributes"].get("sentry.op") == OP.QUEUE_SUBMIT_DJANGO + ] + assert len(queue_submit_spans) == 3 + + span_names = [span["name"] for span in queue_submit_spans] assert span_names.count("tests.integrations.django.test_tasks.task_one") == 2 assert span_names.count("tests.integrations.django.test_tasks.task_two") == 1