diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 7dc574311d..dafc152071 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -21,11 +21,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 ( @@ -86,7 +84,6 @@ ) 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") @@ -350,27 +347,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 @@ -513,13 +504,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: @@ -765,11 +754,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) @@ -791,11 +775,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) @@ -806,27 +785,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) @@ -834,27 +803,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) @@ -862,27 +822,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 @@ -893,22 +844,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` @@ -941,28 +886,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..99229aaba8 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.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 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 be950030cb..a567ec5045 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -10,16 +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, ) 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]) @@ -68,7 +66,7 @@ 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 @@ -78,25 +76,17 @@ def _check_middleware_span( 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, - ) + 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 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 0424c965ec..8844601e55 100644 --- a/tests/integrations/django/asgi/test_asgi.py +++ b/tests/integrations/django/asgi/test_asgi.py @@ -45,104 +45,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() + else: + 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) + assert response["status"] == 500 - (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() + (event,) = (item.payload for item in items) - assert response["status"] == 500 + (exception,) = event["exception"]["values"] + assert exception["type"] == "ZeroDivisionError" - (event,) = events + # 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", + } - (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 = events[-1] + capture_message("hi") + event = items[-1].payload assert "request" not in event @@ -152,39 +107,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"] == { @@ -278,14 +220,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 = [ @@ -297,7 +236,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, }, @@ -306,24 +245,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__" @@ -331,131 +269,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") - - response = await comm.get_response() - await comm.wait() - - assert response["status"] == 500 + items = capture_items("event") - ( - 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"] @@ -472,17 +351,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" @@ -495,55 +371,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" @@ -556,24 +415,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() - - assert response["status"] == 500 - - (msg_event, error_event) = (item.payload for item in items) - else: - events = capture_events() + items = capture_items("event") - 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 @@ -682,10 +531,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, @@ -694,12 +541,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( @@ -710,28 +556,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 @@ -969,39 +803,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) @@ -1009,13 +830,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. @@ -1023,45 +841,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") + 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() - - 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) @@ -1069,13 +867,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=[ @@ -1087,48 +882,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") + 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() - - 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 9a6cad64f1..28aa6ae2ab 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -57,6 +57,7 @@ def test_view_exceptions( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", ) exceptions = capture_exceptions() items = capture_items("event") @@ -86,6 +87,7 @@ 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", ) exceptions = capture_exceptions() items = capture_items("event") @@ -112,6 +114,7 @@ def test_ensures_x_forwarded_header_is_not_honored_when_unenabled_in_django( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", ) exceptions = capture_exceptions() items = capture_items("event") @@ -133,18 +136,15 @@ 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", ) items = capture_items("event") content, status, headers = unpack_werkzeug_response(client.get(reverse("message"))) @@ -164,49 +164,33 @@ def test_request_captured( } -@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=[ @@ -215,80 +199,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") + items = capture_items("event", "span") + client.head(reverse("view_exc_with_msg")) - 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 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"] - == spans[3]["trace_id"] - ) - else: - events = capture_events() - client.head(reverse("view_exc_with_msg")) - - (msg_event, error_event, transaction_event) = events + ( + msg_event, + error_event, + ) = (item.payload for item in items if item.type == "event") - 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")) - - ( - msg_event, - error_event, - ) = (item.payload for item in items) - else: - events = capture_events() - client.head(reverse("view_exc_with_msg")) + items = capture_items("event") + 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"] @@ -302,13 +256,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=[ @@ -317,66 +268,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=[ @@ -384,29 +311,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"] @@ -420,50 +339,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", @@ -512,6 +408,7 @@ def test_queryset_repr( ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword") @@ -541,6 +438,7 @@ def test_context_nested_queryset_repr( ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword") items = capture_items("event") @@ -566,6 +464,7 @@ def test_custom_error_handler_request_context( ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) items = capture_items("event") content, status, headers = unpack_werkzeug_response(client.post("/404")) @@ -680,47 +579,32 @@ def test_sql_dict_query_params( @pytest.mark.forked -@pytest.mark.parametrize("span_streaming", [True, False]) def test_response_trace( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): pytest.importorskip("rest_framework") 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") - content, status, headers = unpack_werkzeug_response( - client.get(reverse("rest_json_response")) - ) - assert status == "200 OK" - - sentry_sdk.flush() - spans = [item.payload for item in items] + items = capture_items("span") + content, status, headers = unpack_werkzeug_response( + client.get(reverse("rest_json_response")) + ) + assert status == "200 OK" - assert ( - '- sentry.op="view.response.render": name="serialize response"' - in render_span_tree(spans) - ) - else: - events = capture_events() - content, status, headers = unpack_werkzeug_response( - client.get(reverse("rest_json_response")) - ) - assert status == "200 OK" + sentry_sdk.flush() + spans = [item.payload for item in items] - assert ( - '- op="view.response.render": description="serialize response"' - in render_span_tree(events[0]["spans"], events[0]["contexts"]["trace"]) - ) + assert ( + '- sentry.op="view.response.render": name="serialize response"' + in render_span_tree(spans) + ) @pytest.mark.parametrize( @@ -742,6 +626,7 @@ def test_sql_psycopg2_string_composition( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", _experiments={ "record_sql_params": True, }, @@ -780,6 +665,7 @@ def test_sql_psycopg2_placeholders( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", _experiments={ "record_sql_params": True, }, @@ -839,14 +725,11 @@ def test_sql_psycopg2_placeholders( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_django_connect_trace( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): """ Verify we record a span when opening a new database. @@ -855,7 +738,7 @@ def test_django_connect_trace( integrations=[DjangoIntegration()], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) from django.db import connections @@ -866,41 +749,22 @@ def test_django_connect_trace( # 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") - - content, status, headers = unpack_werkzeug_response( - client.get(reverse("postgres_select")) - ) - 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": - attributes = span.get("attributes") - assert attributes.get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - - assert '- sentry.op="db": name="connect"' in render_span_tree(spans) - else: - events = capture_events() + items = capture_items("span") - content, status, headers = unpack_werkzeug_response( - client.get(reverse("postgres_select")) - ) - assert status == "200 OK" + content, status, headers = unpack_werkzeug_response( + client.get(reverse("postgres_select")) + ) + assert status == "200 OK" - (event,) = events + sentry_sdk.flush() + spans = [item.payload for item in items] - for span in event["spans"]: - if span.get("op") == "db": - data = span.get("data") - assert data.get(SPANDATA.DB_SYSTEM) == "postgresql" + for span in spans: + if span["attributes"].get("sentry.op") == "db": + attributes = span.get("attributes") + assert attributes.get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - assert '- op="db": description="connect"' in render_span_tree( - event["spans"], event["contexts"]["trace"] - ) + assert '- sentry.op="db": name="connect"' in render_span_tree(spans) @pytest.mark.forked @@ -915,6 +779,7 @@ def test_django_connect_breadcrumbs( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", ) from django.db import connections @@ -945,19 +810,16 @@ def test_django_connect_breadcrumbs( @pytest.mark.forked @pytest_mark_django_db_decorator(transaction=True) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_db_connection_span_data( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) from django.db import connections @@ -968,57 +830,31 @@ def test_db_connection_span_data( # 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") - - content, status, headers = unpack_werkzeug_response( - client.get(reverse("postgres_select")) - ) - assert status == "200 OK" + items = capture_items("span") - sentry_sdk.flush() - spans = [item.payload for item in items] + content, status, headers = unpack_werkzeug_response( + client.get(reverse("postgres_select")) + ) + assert status == "200 OK" - for span in spans: - if span["attributes"].get("sentry.op") == "db": - attributes = span.get("attributes") - assert attributes.get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert attributes.get(SPANDATA.DB_NAMESPACE) is not None - assert attributes.get(SPANDATA.DB_NAMESPACE) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert attributes.get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert attributes.get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items] - content, status, headers = unpack_werkzeug_response( - client.get(reverse("postgres_select")) - ) - assert status == "200 OK" - - (event,) = events - - for span in event["spans"]: - if span.get("op") == "db": - data = span.get("data") - assert data.get(SPANDATA.DB_SYSTEM) == "postgresql" - conn_params = connections["postgres"].get_connection_params() - assert data.get(SPANDATA.DB_NAME) is not None - assert data.get(SPANDATA.DB_NAME) == conn_params.get( - "database" - ) or conn_params.get("dbname") - assert data.get(SPANDATA.SERVER_ADDRESS) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" - ) - assert data.get(SPANDATA.SERVER_PORT) == os.environ.get( - "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" - ) + for span in spans: + if span["attributes"].get("sentry.op") == "db": + attributes = span.get("attributes") + assert attributes.get(SPANDATA.DB_SYSTEM_NAME) == "postgresql" + conn_params = connections["postgres"].get_connection_params() + assert attributes.get(SPANDATA.DB_NAMESPACE) is not None + assert attributes.get(SPANDATA.DB_NAMESPACE) == conn_params.get( + "database" + ) or conn_params.get("dbname") + assert attributes.get(SPANDATA.SERVER_ADDRESS) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_HOST", "localhost" + ) + assert attributes.get(SPANDATA.SERVER_PORT) == os.environ.get( + "SENTRY_PYTHON_TEST_POSTGRES_PORT", "5432" + ) def test_set_db_data_custom_backend(): @@ -1053,47 +889,34 @@ def get_connection_params(self): ("url", "/404", "/404", "url", b"404"), ], ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_transaction_style( sentry_init, client, - capture_events, capture_items, transaction_style, client_url, expected_transaction, expected_source, expected_response, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(transaction_style=transaction_style)], traces_sample_rate=1.0, send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - items = capture_items("event", "span") - - content, status, headers = unpack_werkzeug_response(client.get(client_url)) - assert content == expected_response + items = capture_items("event", "span") - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] + content, status, headers = unpack_werkzeug_response(client.get(client_url)) + assert content == expected_response - assert spans[2]["is_segment"] is True - assert spans[2]["attributes"]["sentry.segment.name.source"] == expected_source - - (event,) = (item.payload for item in items if item.type == "event") - else: - events = capture_events() + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] - content, status, headers = unpack_werkzeug_response(client.get(client_url)) - assert content == expected_response + assert spans[2]["is_segment"] is True + assert spans[2]["attributes"]["sentry.segment.name.source"] == expected_source - (event, transaction) = events - assert transaction["transaction"] == expected_transaction - assert transaction["transaction_info"] == {"source": expected_source} + (event,) = (item.payload for item in items if item.type == "event") assert event["transaction"] == expected_transaction @@ -1112,51 +935,39 @@ def test_transaction_style( ("url", "/404", "/404", "url", b"404"), ], ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_transaction_style_tracing_disabled( sentry_init, client, - capture_events, capture_items, transaction_style, client_url, expected_transaction, expected_source, expected_response, - span_streaming, ): sentry_init( integrations=[DjangoIntegration(transaction_style=transaction_style)], 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(client_url)) - assert content == expected_response - - (event,) = (item.payload for item in items if item.type == "event") - else: - events = capture_events() + items = capture_items("event") - content, status, headers = unpack_werkzeug_response(client.get(client_url)) - assert content == expected_response + content, status, headers = unpack_werkzeug_response(client.get(client_url)) + assert content == expected_response - (event,) = events + (event,) = (item.payload for item in items if item.type == "event") assert event["transaction"] == expected_transaction -@pytest.mark.parametrize("span_streaming", [True, False]) def test_request_body( sentry_init, client, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) items = capture_items("event") content, status, headers = unpack_werkzeug_response( @@ -1262,29 +1073,6 @@ def test_request_body_dropped_with_form_and_files_data_collection( assert "data" not in event.get("_meta", {}).get("request", {}) -def test_transaction_request_body_data_collection(sentry_init, client, capture_events): - sentry_init( - integrations=[DjangoIntegration()], - traces_sample_rate=1.0, - _experiments={"data_collection": {"http_bodies": []}}, - ) - events = capture_events() - - content, status, headers = unpack_werkzeug_response( - client.post( - reverse("post_echo"), - data=json.dumps({"hey": 42}).encode("utf-8"), - content_type="application/json", - ) - ) - assert status.lower() == "200 ok" - - event, transaction_event = events - - assert "data" not in event["request"] - assert "data" not in transaction_event["request"] - - def test_oversized_request_body_not_annotated_data_collection( sentry_init, client, capture_items ): @@ -1319,10 +1107,10 @@ def test_read_request( sentry_init, client, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) items = capture_items("event") @@ -1348,6 +1136,7 @@ def test_request_body_already_read( ): sentry_init( integrations=[DjangoIntegration()], + trace_lifecycle="stream", ) class MockExtractor(DjangoRequestExtractor): @@ -1369,17 +1158,14 @@ def raw_data(self): assert "data" not in event["request"] -@pytest.mark.parametrize("span_streaming", [True, False]) def test_template_tracing_meta( sentry_init, client, - capture_events, capture_items, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) items = capture_items("event") @@ -1413,6 +1199,7 @@ def test_template_exception( ): sentry_init( integrations=[DjangoIntegration()] + with_executing_integration, + trace_lifecycle="stream", ) items = capture_items("event") @@ -1470,58 +1257,37 @@ def test_template_exception( ["application/x-www-form-urlencoded", {"foo": "bar"}], ], ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_rest_framework_basic( sentry_init, client, - capture_events, capture_items, capture_exceptions, ct, body, route, - span_streaming, ): pytest.importorskip("rest_framework") sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - exceptions = capture_exceptions() - items = capture_items("event") - - if ct == "application/json": - client.post( - reverse(route), data=json.dumps(body), content_type="application/json" - ) - elif ct == "application/x-www-form-urlencoded": - client.post(reverse(route), data=body) - else: - raise AssertionError("unreachable") - - (error,) = exceptions - assert isinstance(error, ZeroDivisionError) + exceptions = capture_exceptions() + items = capture_items("event") - (event,) = (item.payload for item in items) + if ct == "application/json": + client.post( + reverse(route), data=json.dumps(body), content_type="application/json" + ) + elif ct == "application/x-www-form-urlencoded": + client.post(reverse(route), data=body) else: - exceptions = capture_exceptions() - events = capture_events() + raise AssertionError("unreachable") - if ct == "application/json": - client.post( - reverse(route), data=json.dumps(body), content_type="application/json" - ) - elif ct == "application/x-www-form-urlencoded": - client.post(reverse(route), data=body) - else: - raise AssertionError("unreachable") - - (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" @@ -1529,14 +1295,11 @@ def test_rest_framework_basic( assert event["request"]["headers"]["Content-Type"] == ct -@pytest.mark.parametrize("span_streaming", [True, False]) def test_rest_framework_authentication_span( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): pytest.importorskip("rest_framework") sentry_init( @@ -1544,46 +1307,28 @@ def test_rest_framework_authentication_span( 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("span") + items = capture_items("span") - client.get(reverse("rest_authenticated_hello")) + client.get(reverse("rest_authenticated_hello")) - 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"] - assert ( - render_span_tree(spans) - == """\ + assert ( + render_span_tree(spans) + == """\ - sentry.op="http.server": name="/rest-authenticated-hello" - sentry.op="view.authenticate": name="authenticate"\ """ - ) - else: - events = capture_events() - - client.get(reverse("rest_authenticated_hello")) - - (transaction,) = events - - assert ( - render_span_tree(transaction["spans"], transaction["contexts"]["trace"]) - == """\ -- op="http.server": description=null - - op="view.authenticate": description="authenticate"\ -""" - ) + ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_rest_framework_authentication_span_without_authenticators( sentry_init, client, - capture_events, capture_items, - span_streaming, ): pytest.importorskip("rest_framework") sentry_init( @@ -1591,49 +1336,37 @@ def test_rest_framework_authentication_span_without_authenticators( 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("span") - - client.get(reverse("rest_unauthenticated_hello")) - - sentry_sdk.flush() - spans = [item.payload for item in items if item.type == "span"] - - # only the root span - assert len(spans) == 1 - else: - events = capture_events() + items = capture_items("span") - client.get(reverse("rest_unauthenticated_hello")) + client.get(reverse("rest_unauthenticated_hello")) - (transaction,) = events + sentry_sdk.flush() + spans = [item.payload for item in items if item.type == "span"] - assert transaction["spans"] == [] + # only the root span + assert len(spans) == 1 @pytest.mark.parametrize( "endpoint", ["rest_permission_denied_exc", "permission_denied_exc"] ) -@pytest.mark.parametrize("span_streaming", [True, False]) def test_does_not_capture_403( sentry_init, client, - capture_events, capture_items, endpoint, - span_streaming, ): if endpoint == "rest_permission_denied_exc": pytest.importorskip("rest_framework") sentry_init( integrations=[DjangoIntegration()], - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - items = capture_items("event", "transaction", "span") + items = capture_items("event", "span") _, status, _ = unpack_werkzeug_response(client.get(reverse(endpoint))) assert status.lower() == "403 forbidden" @@ -1731,63 +1464,37 @@ def test_failed_request_status_codes_unhandled_exception( assert exception["mechanism"]["handled"] is False -@pytest.mark.parametrize("span_streaming", [True, False]) def test_render_spans( sentry_init, client, - capture_events, capture_items, render_span_tree, - span_streaming, ): sentry_init( integrations=[DjangoIntegration()], traces_sample_rate=1.0, - trace_lifecycle="stream" if span_streaming else "static", + trace_lifecycle="stream", ) - if span_streaming: - views_tests = [ - ( - reverse("template_test2"), - '- sentry.op="template.render": name="[user_name.html, ...]"', - ), - ] - if DJANGO_VERSION >= (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 @@ -1827,35 +1534,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__" @@ -1865,8 +1568,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" @@ -1877,196 +1580,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")) - - (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")) - client.get(reverse("message")) + (message,) = (item.payload for item in items if item.type == "event") - message, transaction = events + assert message["message"] == "hi" - 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")) - - sentry_sdk.flush() - (message,) = (item.payload for item in items if item.type == "event") + client.get(reverse("message")) - 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=[ @@ -2078,65 +1689,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")) - - (transaction,) = events - - 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 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" - 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): @@ -2177,16 +1755,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. @@ -2200,85 +1775,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") + 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" + try: + content, status, _headers = unpack_werkzeug_response(client.get("/custom/ok")) + assert status.lower() == "200 ok" + assert content == b"custom ok" - 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 middleware_spans: - assert spans[10]["name"] == "/custom/ok" - assert "custom_urlconf_middleware" in render_span_tree(spans) - else: - assert spans[2]["name"] == "/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" - _content, status, _headers = unpack_werkzeug_response( - client.get("/custom/exc") - ) - assert status.lower() == "500 internal server error" + _content, status, _headers = unpack_werkzeug_response(client.get("/custom/exc")) + assert status.lower() == "500 internal server error" - (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" - ) + (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" - 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() - - 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(): @@ -2300,13 +1833,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=[ @@ -2317,47 +1847,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. @@ -2365,39 +1878,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=[ @@ -2409,37 +1907,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 e1efba4f60..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( @@ -575,14 +392,11 @@ def test_cache_spans_get_span_name(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=[ @@ -593,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")) + 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://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=[ @@ -646,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") + 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: - if span["is_segment"] is True: - continue + 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() - - client.get(reverse("cached_view")) - client.get(reverse("cached_view")) - - 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=[ @@ -695,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") - - 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: - # 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")) + sentry_sdk.flush() + spans = [item.payload for item in items] - 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=[ @@ -743,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=[ @@ -822,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=[ @@ -935,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 - - 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[0]["attributes"]["sentry.op"] == "cache.get" - assert spans[0]["name"] == f"S{id}" - assert not spans[0]["attributes"]["cache.hit"] - - 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[3]["attributes"]["sentry.op"] == "cache.put" - assert spans[3]["name"] == f"S{id}" + items = capture_items("span") - assert spans[6]["attributes"]["sentry.op"] == "cache.get" - assert spans[6]["name"] == f"S{id}, S{id + 1}" - assert spans[6]["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[4]["attributes"]["sentry.op"] == "cache.get" - assert spans[4]["name"] == f"S{id}" - assert spans[4]["attributes"]["cache.hit"] + sentry_sdk.flush() + spans = [item.payload for item in items] + assert len(spans) == 8 - 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() - - 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}"]) - - (transaction,) = events - assert len(transaction["spans"]) == 7 - - 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[2]["attributes"]["sentry.op"] == "cache.get" + assert spans[2]["name"] == f"S{id}, S{id + 1}" + assert not spans[2]["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[0]["attributes"]["sentry.op"] == "cache.get" + assert spans[0]["name"] == f"S{id}" + assert not spans[0]["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 spans[1]["attributes"]["sentry.op"] == "cache.get" + assert spans[1]["name"] == f"S{id + 1}" + assert not spans[1]["attributes"]["cache.hit"] - assert transaction["spans"][3]["op"] == "cache.put" - assert transaction["spans"][3]["description"] == f"S{id}" + assert spans[3]["attributes"]["sentry.op"] == "cache.put" + assert spans[3]["name"] == 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 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"][5]["op"] == "cache.get" - assert transaction["spans"][5]["description"] == f"S{id}" - assert transaction["spans"][5]["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"][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=[ @@ -1038,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=[ @@ -1110,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 fa60302850..bbf2be23f1 100644 --- a/tests/integrations/django/test_data_scrubbing.py +++ b/tests/integrations/django/test_data_scrubbing.py @@ -30,6 +30,7 @@ def test_scrub_django_session_cookies_removed( sentry_init( integrations=[DjangoIntegration()], send_default_pii=False, + trace_lifecycle="stream", ) items = capture_items("event") werkzeug_set_cookie(client, "localhost", "sessionid", "123") @@ -51,6 +52,7 @@ def test_scrub_django_session_cookies_filtered( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + trace_lifecycle="stream", ) items = capture_items("event") werkzeug_set_cookie(client, "localhost", "sessionid", "123") @@ -80,6 +82,7 @@ def test_scrub_django_custom_session_cookies_filtered( sentry_init( integrations=[DjangoIntegration()], send_default_pii=True, + 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 7456ff9ccb..1bd9dcd8b0 100644 --- a/tests/integrations/django/test_tasks.py +++ b/tests/integrations/django/test_tasks.py @@ -54,60 +54,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( @@ -131,71 +107,44 @@ 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( @@ -204,109 +153,65 @@ def test_task_error_reporting( LoggingIntegration(event_level=logging.ERROR), ], 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