From c256355f6b0906188b56cd74401a25c720b92a15 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 12:10:50 +0200 Subject: [PATCH 01/13] Avoid adding complex Django object to spans --- sentry_sdk/integrations/django/templates.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 10e8a924b7..db2b821f04 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -73,7 +73,15 @@ def rendered_content(self): name=_get_template_name_description(self.template_name), origin=DjangoIntegration.origin, ) as span: - span.set_data("context", self.context_data) + context_data = {} + for k, v in self.context_data.items(): + # Only include primitive types to avoid + # large payloads and long serialization times + if type(v) in (str, int, float, bool, list, dict): + context_data[k] = v + + span.set_data("context", context_data) + return real_rendered_content.fget(self) SimpleTemplateResponse.rendered_content = rendered_content From bb9bf6f9ee3c4d68726e9aee4c39f6f756c11c89 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 13:20:26 +0200 Subject: [PATCH 02/13] Tests --- sentry_sdk/integrations/django/templates.py | 10 +++++- tests/integrations/django/myapp/urls.py | 1 + tests/integrations/django/myapp/views.py | 10 ++++++ tests/integrations/django/test_basic.py | 35 +++++++++++++++++++-- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index db2b821f04..51abb9149e 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -109,7 +109,15 @@ def render(request, template_name, context=None, *args, **kwargs): name=_get_template_name_description(template_name), origin=DjangoIntegration.origin, ) as span: - span.set_data("context", context) + new_context = {} + for k, v in context.items(): + # Only include primitive types to avoid + # large payloads and long serialization times + if type(v) in (str, int, float, bool, list, dict): + new_context[k] = v + + span.set_data("context", new_context) + return real_render(request, template_name, context, *args, **kwargs) django.shortcuts.render = render 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..53ffdb0f28 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -1,6 +1,7 @@ import asyncio import json import threading +import time from django.contrib.auth import login from django.contrib.auth.models import User @@ -208,6 +209,15 @@ def template_test3(request, *args, **kwargs): return render(request, "trace_meta.html", {}) +@csrf_exempt +def template_test4(request, *args, **kwargs): + return TemplateResponse( + request, + "user_name.html", + {"user_age": 25, "complex_context": lambda x: time.sleep(10)}, + ) + + @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..552deef4c3 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 +import time 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,36 @@ 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") +def test_render_spans_complex_context(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() + + begin = time.time() + client.get(reverse("template_test4")) + + (transaction,) = events + end = time.time() + + # evaluating the complex context takes 10 seconds, (see lambda in template_test4) + # so we expect the total time to be way less, because the complex context is not evaluated + assert end - begin < 10 / 5 + + assert transaction["spans"][-1]["data"]["context"] == { + "user_age": 25, + # The "complex_context" is not included because it is not a primitive type + } + + if DJANGO_VERSION >= (1, 10): EXPECTED_MIDDLEWARE_SPANS = """\ - op="http.server": description=null From f2bdbfe24bf3f61a23f5e1325b7ca172b0f9a7d9 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 13:22:00 +0200 Subject: [PATCH 03/13] consistency --- sentry_sdk/integrations/django/templates.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 51abb9149e..6cd1e7fcf3 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -73,14 +73,14 @@ def rendered_content(self): name=_get_template_name_description(self.template_name), origin=DjangoIntegration.origin, ) as span: - context_data = {} + new_context = {} for k, v in self.context_data.items(): # Only include primitive types to avoid # large payloads and long serialization times if type(v) in (str, int, float, bool, list, dict): - context_data[k] = v + new_context[k] = v - span.set_data("context", context_data) + span.set_data("context", new_context) return real_rendered_content.fget(self) From 7f8d785457996f2862e3f0e0c433467a05e8d702 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 13:53:09 +0200 Subject: [PATCH 04/13] better code --- sentry_sdk/integrations/django/templates.py | 41 ++++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 6cd1e7fcf3..6f54214abe 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -57,6 +57,31 @@ def _get_template_name_description(template_name): return template_name +def _normalize_context(context): + # type: (Dict[str, Any]) -> Dict[str, Any] + """ + Filter out non-primitive types from `context`. + """ + new_context = {} + for key, value in context.items(): + if isinstance(value, list): + new_context[key] = [ + item + for item in value + if isinstance(item, (str, int, float, bool, type(None))) + ] + elif isinstance(value, dict): + new_context[key] = { + k: v + for k, v in value.items() + if isinstance(v, (str, int, float, bool, type(None))) + } + elif isinstance(value, (str, int, float, bool, type(None))): + new_context[key] = value + + return new_context + + def patch_templates(): # type: () -> None from django.template.response import SimpleTemplateResponse @@ -73,13 +98,7 @@ def rendered_content(self): name=_get_template_name_description(self.template_name), origin=DjangoIntegration.origin, ) as span: - new_context = {} - for k, v in self.context_data.items(): - # Only include primitive types to avoid - # large payloads and long serialization times - if type(v) in (str, int, float, bool, list, dict): - new_context[k] = v - + new_context = _normalize_context(self.context_data) span.set_data("context", new_context) return real_rendered_content.fget(self) @@ -109,13 +128,7 @@ def render(request, template_name, context=None, *args, **kwargs): name=_get_template_name_description(template_name), origin=DjangoIntegration.origin, ) as span: - new_context = {} - for k, v in context.items(): - # Only include primitive types to avoid - # large payloads and long serialization times - if type(v) in (str, int, float, bool, list, dict): - new_context[k] = v - + new_context = _normalize_context(context) span.set_data("context", new_context) return real_render(request, template_name, context, *args, **kwargs) From 535a9e89b7d00783ac5f3f8080ad225605a164af Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 13:55:04 +0200 Subject: [PATCH 05/13] typing --- sentry_sdk/integrations/django/templates.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 6f54214abe..237a7add55 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -16,6 +16,7 @@ from typing import Optional from typing import Iterator from typing import Tuple + from typing import Union try: # support Django 1.9 @@ -58,11 +59,13 @@ def _get_template_name_description(template_name): def _normalize_context(context): - # type: (Dict[str, Any]) -> Dict[str, Any] + # type: (Dict[str, Any]) -> Dict[str, Union[str, int, float, bool, type(None), list[Union[str, int, float, bool, type(None)]], dict[str, Union[str, int, float, bool, type(None)]]]] """ Filter out non-primitive types from `context`. """ - new_context = {} + new_context = ( + {} + ) # type: Dict[str, Union[str, int, float, bool, type(None), list[Union[str, int, float, bool, type(None)]], dict[str, Union[str, int, float, bool, type(None)]]]] for key, value in context.items(): if isinstance(value, list): new_context[key] = [ From e7efa195bb6e131141f320537c967505be9d9087 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 13:57:59 +0200 Subject: [PATCH 06/13] better --- sentry_sdk/integrations/django/templates.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 237a7add55..002918d759 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -67,20 +67,25 @@ def _normalize_context(context): {} ) # type: Dict[str, Union[str, int, float, bool, type(None), list[Union[str, int, float, bool, type(None)]], dict[str, Union[str, int, float, bool, type(None)]]]] for key, value in context.items(): + if isinstance(value, (str, int, float, bool, type(None))): + new_context[key] = value + continue + if isinstance(value, list): new_context[key] = [ item for item in value if isinstance(item, (str, int, float, bool, type(None))) ] - elif isinstance(value, dict): + continue + + if isinstance(value, dict): new_context[key] = { k: v for k, v in value.items() if isinstance(v, (str, int, float, bool, type(None))) } - elif isinstance(value, (str, int, float, bool, type(None))): - new_context[key] = value + continue return new_context From 83680ad9d07a3ae339ed0bb1ec35a19258a7fb7e Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 14:02:46 +0200 Subject: [PATCH 07/13] better tests --- tests/integrations/django/myapp/views.py | 11 ++++++++++- tests/integrations/django/test_basic.py | 7 ++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index 53ffdb0f28..332e0a44ac 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -214,7 +214,16 @@ def template_test4(request, *args, **kwargs): return TemplateResponse( request, "user_name.html", - {"user_age": 25, "complex_context": lambda x: time.sleep(10)}, + { + "user_age": 25, + "complex_context": lambda x: time.sleep(10), + "complex_list": [1, 2, 3, lambda x: time.sleep(10)], + "complex_dict": { + "a": 1, + "d": lambda x: time.sleep(10), + }, + "none_context": None, + }, ) diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 552deef4c3..78acab32e9 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -981,9 +981,14 @@ def test_render_spans_complex_context(sentry_init, client, capture_events): # so we expect the total time to be way less, because the complex context is not evaluated assert end - begin < 10 / 5 + # Make sure complex items are not put into the span.data assert transaction["spans"][-1]["data"]["context"] == { "user_age": 25, - # The "complex_context" is not included because it is not a primitive type + "complex_dict": { + "a": 1, + }, + "complex_list": [1, 2, 3], + "none_context": None, } From c3afe8dff475b734a21c57193a81531d7a5778f3 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 14:04:05 +0200 Subject: [PATCH 08/13] better readable test --- tests/integrations/django/myapp/views.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index 332e0a44ac..e8d4602860 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -211,19 +211,21 @@ def template_test3(request, *args, **kwargs): @csrf_exempt def template_test4(request, *args, **kwargs): + template_context = { + "user_age": 25, + "complex_context": lambda x: time.sleep(10), + "complex_list": [1, 2, 3, lambda x: time.sleep(10)], + "complex_dict": { + "a": 1, + "d": lambda x: time.sleep(10), + }, + "none_context": None, + } + return TemplateResponse( request, "user_name.html", - { - "user_age": 25, - "complex_context": lambda x: time.sleep(10), - "complex_list": [1, 2, 3, lambda x: time.sleep(10)], - "complex_dict": { - "a": 1, - "d": lambda x: time.sleep(10), - }, - "none_context": None, - }, + template_context, ) From ea9fdd2c1462a741673f11bd43c5723d9549ad2c Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 16 Sep 2025 14:12:14 +0200 Subject: [PATCH 09/13] linting --- sentry_sdk/integrations/django/templates.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 002918d759..08d95eda73 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -59,13 +59,13 @@ def _get_template_name_description(template_name): def _normalize_context(context): - # type: (Dict[str, Any]) -> Dict[str, Union[str, int, float, bool, type(None), list[Union[str, int, float, bool, type(None)]], dict[str, Union[str, int, float, bool, type(None)]]]] + # type: (Dict[str, Any]) -> Dict[str, Union[str, int, float, bool, None, list[Union[str, int, float, bool, None]], dict[str, Union[str, int, float, bool, None]]]] """ Filter out non-primitive types from `context`. """ new_context = ( {} - ) # type: Dict[str, Union[str, int, float, bool, type(None), list[Union[str, int, float, bool, type(None)]], dict[str, Union[str, int, float, bool, type(None)]]]] + ) # type: Dict[str, Union[str, int, float, bool, None, list[Union[str, int, float, bool, None]], dict[str, Union[str, int, float, bool, None]]]] for key, value in context.items(): if isinstance(value, (str, int, float, bool, type(None))): new_context[key] = value From f46e3a037f3e8bc4f3cf371d6e3202dbce080f81 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 17 Sep 2025 11:30:53 +0200 Subject: [PATCH 10/13] Do the correct serialization in serialize() --- sentry_sdk/integrations/django/templates.py | 39 ++------------------- sentry_sdk/serializer.py | 3 ++ tests/integrations/django/myapp/views.py | 10 +++--- tests/integrations/django/test_basic.py | 36 ++++++++++--------- 4 files changed, 30 insertions(+), 58 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 08d95eda73..cf2c0cfd76 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -16,7 +16,6 @@ from typing import Optional from typing import Iterator from typing import Tuple - from typing import Union try: # support Django 1.9 @@ -58,38 +57,6 @@ def _get_template_name_description(template_name): return template_name -def _normalize_context(context): - # type: (Dict[str, Any]) -> Dict[str, Union[str, int, float, bool, None, list[Union[str, int, float, bool, None]], dict[str, Union[str, int, float, bool, None]]]] - """ - Filter out non-primitive types from `context`. - """ - new_context = ( - {} - ) # type: Dict[str, Union[str, int, float, bool, None, list[Union[str, int, float, bool, None]], dict[str, Union[str, int, float, bool, None]]]] - for key, value in context.items(): - if isinstance(value, (str, int, float, bool, type(None))): - new_context[key] = value - continue - - if isinstance(value, list): - new_context[key] = [ - item - for item in value - if isinstance(item, (str, int, float, bool, type(None))) - ] - continue - - if isinstance(value, dict): - new_context[key] = { - k: v - for k, v in value.items() - if isinstance(v, (str, int, float, bool, type(None))) - } - continue - - return new_context - - def patch_templates(): # type: () -> None from django.template.response import SimpleTemplateResponse @@ -106,8 +73,7 @@ def rendered_content(self): name=_get_template_name_description(self.template_name), origin=DjangoIntegration.origin, ) as span: - new_context = _normalize_context(self.context_data) - span.set_data("context", new_context) + span.set_data("context", self.context_data) return real_rendered_content.fget(self) @@ -136,8 +102,7 @@ def render(request, template_name, context=None, *args, **kwargs): name=_get_template_name_description(template_name), origin=DjangoIntegration.origin, ) as span: - new_context = _normalize_context(context) - span.set_data("context", new_context) + span.set_data("context", context) return real_render(request, template_name, context, *args, **kwargs) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 04df9857bd..dbc7d6d19f 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -182,6 +182,9 @@ def _is_databag(): if p0 == "extra": return True + if p0 == "spans" and path[2] == "data": + return True + except IndexError: return None diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index e8d4602860..9c14bc27d7 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -1,7 +1,6 @@ import asyncio import json import threading -import time from django.contrib.auth import login from django.contrib.auth.models import User @@ -211,13 +210,16 @@ def template_test3(request, *args, **kwargs): @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": lambda x: time.sleep(10), - "complex_list": [1, 2, 3, lambda x: time.sleep(10)], + "complex_context": my_queryset, + "complex_list": [1, 2, 3, my_queryset], "complex_dict": { "a": 1, - "d": lambda x: time.sleep(10), + "d": my_queryset, }, "none_context": None, } diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 78acab32e9..53e1a5dc28 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -4,7 +4,7 @@ import pytest import re import sys -import time + from functools import partial from unittest.mock import patch @@ -958,7 +958,8 @@ def test_render_spans(sentry_init, client, capture_events, render_span_tree): @pytest.mark.skipif(DJANGO_VERSION < (1, 9), reason="Requires Django >= 1.9") -def test_render_spans_complex_context(sentry_init, client, capture_events): +@pytest_mark_django_db_decorator() +def test_render_spans_queryset_in_data(sentry_init, client, capture_events): sentry_init( integrations=[ DjangoIntegration( @@ -971,25 +972,26 @@ def test_render_spans_complex_context(sentry_init, client, capture_events): ) events = capture_events() - begin = time.time() client.get(reverse("template_test4")) (transaction,) = events - end = time.time() + template_context = transaction["spans"][-1]["data"]["context"] - # evaluating the complex context takes 10 seconds, (see lambda in template_test4) - # so we expect the total time to be way less, because the complex context is not evaluated - assert end - begin < 10 / 5 - - # Make sure complex items are not put into the span.data - assert transaction["spans"][-1]["data"]["context"] == { - "user_age": 25, - "complex_dict": { - "a": 1, - }, - "complex_list": [1, 2, 3], - "none_context": None, - } + assert template_context["user_age"] == 25 + assert template_context["complex_context"].startswith( + "= (1, 10): From 390358d027516ddd20ac8a93180e508428d4b344 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 17 Sep 2025 11:32:52 +0200 Subject: [PATCH 11/13] clenaup --- sentry_sdk/integrations/django/templates.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index cf2c0cfd76..10e8a924b7 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -74,7 +74,6 @@ def rendered_content(self): origin=DjangoIntegration.origin, ) as span: span.set_data("context", self.context_data) - return real_rendered_content.fget(self) SimpleTemplateResponse.rendered_content = rendered_content @@ -103,7 +102,6 @@ def render(request, template_name, context=None, *args, **kwargs): origin=DjangoIntegration.origin, ) as span: span.set_data("context", context) - return real_render(request, template_name, context, *args, **kwargs) django.shortcuts.render = render From c561eba3fd6e3769f8654cbc543c3d4edd0d83a5 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 17 Sep 2025 12:22:03 +0200 Subject: [PATCH 12/13] another try --- sentry_sdk/serializer.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index dbc7d6d19f..6bde5c08bd 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -182,9 +182,16 @@ def _is_databag(): if p0 == "extra": return True - if p0 == "spans" and path[2] == "data": - return True + except IndexError: + return None + + return False + def _is_span_attribute(): + # type: () -> Optional[bool] + try: + if path[0] == "spans" and path[2] == "data": + return True except IndexError: return None @@ -285,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) From 42d15f9fb1f2bd504b66846410ebed3de6babe94 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 17 Sep 2025 12:30:35 +0200 Subject: [PATCH 13/13] Fork test for isolation --- tests/integrations/django/test_basic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 53e1a5dc28..bbe29c7238 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -958,6 +958,7 @@ def test_render_spans(sentry_init, client, capture_events, render_span_tree): @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(