diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 04df9857bd..6bde5c08bd 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -187,6 +187,16 @@ def _is_databag(): return False + def _is_span_attribute(): + # type: () -> Optional[bool] + try: + if path[0] == "spans" and path[2] == "data": + return True + except IndexError: + return None + + return False + def _is_request_body(): # type: () -> Optional[bool] try: @@ -282,7 +292,8 @@ def _serialize_node_impl( ) return None - if is_databag and global_repr_processors: + is_span_attribute = _is_span_attribute() + if (is_databag or is_span_attribute) and global_repr_processors: hints = {"memo": memo, "remaining_depth": remaining_depth} for processor in global_repr_processors: result = processor(obj, hints) diff --git a/tests/integrations/django/myapp/urls.py b/tests/integrations/django/myapp/urls.py index 79dd4edd52..fbc9e6032e 100644 --- a/tests/integrations/django/myapp/urls.py +++ b/tests/integrations/django/myapp/urls.py @@ -58,6 +58,7 @@ def path(path, *args, **kwargs): path("template-test", views.template_test, name="template_test"), path("template-test2", views.template_test2, name="template_test2"), path("template-test3", views.template_test3, name="template_test3"), + path("template-test4", views.template_test4, name="template_test4"), path("postgres-select", views.postgres_select, name="postgres_select"), path("postgres-select-slow", views.postgres_select_orm, name="postgres_select_orm"), path( diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index 5e8cc39053..9c14bc27d7 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -208,6 +208,29 @@ def template_test3(request, *args, **kwargs): return render(request, "trace_meta.html", {}) +@csrf_exempt +def template_test4(request, *args, **kwargs): + User.objects.create_user("john", "lennon@thebeatles.com", "johnpassword") + my_queryset = User.objects.all() # noqa + + template_context = { + "user_age": 25, + "complex_context": my_queryset, + "complex_list": [1, 2, 3, my_queryset], + "complex_dict": { + "a": 1, + "d": my_queryset, + }, + "none_context": None, + } + + return TemplateResponse( + request, + "user_name.html", + template_context, + ) + + @csrf_exempt def postgres_select(request, *args, **kwargs): from django.db import connections diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index e96cd09e4f..bbe29c7238 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -1,9 +1,10 @@ import inspect import json import os +import pytest import re import sys -import pytest + from functools import partial from unittest.mock import patch @@ -15,8 +16,8 @@ from django.core.management import execute_from_command_line from django.db.utils import OperationalError, ProgrammingError, DataError from django.http.request import RawPostDataException -from django.utils.functional import SimpleLazyObject from django.template.context import make_context +from django.utils.functional import SimpleLazyObject try: from django.urls import reverse @@ -956,6 +957,44 @@ def test_render_spans(sentry_init, client, capture_events, render_span_tree): assert expected_line in render_span_tree(transaction) +@pytest.mark.skipif(DJANGO_VERSION < (1, 9), reason="Requires Django >= 1.9") +@pytest.mark.forked +@pytest_mark_django_db_decorator() +def test_render_spans_queryset_in_data(sentry_init, client, capture_events): + sentry_init( + integrations=[ + DjangoIntegration( + cache_spans=False, + middleware_spans=False, + signals_spans=False, + ) + ], + traces_sample_rate=1.0, + ) + events = capture_events() + + client.get(reverse("template_test4")) + + (transaction,) = events + template_context = transaction["spans"][-1]["data"]["context"] + + assert template_context["user_age"] == 25 + assert template_context["complex_context"].startswith( + "= (1, 10): EXPECTED_MIDDLEWARE_SPANS = """\ - op="http.server": description=null