Skip to content

Commit 10ed892

Browse files
ref(django): Remove transaction_style parameter (#7799)
Inline the branches that set the route template as the segment name (i.e., `transaction_style="url"`). Closes #7763
1 parent 7f1d3f7 commit 10ed892

2 files changed

Lines changed: 24 additions & 101 deletions

File tree

‎sentry_sdk/integrations/django/__init__.py‎

Lines changed: 14 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import sys
44
import threading
55
import weakref
6-
from importlib import import_module
76

87
import sentry_sdk
98
from sentry_sdk.consts import OP, SPANDATA, SPANNAME
@@ -21,7 +20,7 @@
2120
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
2221
from sentry_sdk.scope import add_global_event_processor, should_send_default_pii
2322
from sentry_sdk.serializer import add_global_repr_processor, add_repr_sequence_type
24-
from sentry_sdk.traces import SOURCE_FOR_STYLE, SegmentNameSource
23+
from sentry_sdk.traces import SegmentNameSource
2524
from sentry_sdk.tracing_utils import (
2625
add_query_source,
2726
record_sql_queries,
@@ -33,15 +32,13 @@
3332
ensure_integration_enabled,
3433
event_from_exception,
3534
has_data_collection_enabled,
36-
transaction_from_function,
3735
walk_exception_chain,
3836
)
3937

4038
try:
4139
from django import VERSION as DJANGO_VERSION
4240
from django.conf import settings
4341
from django.core import signals
44-
from django.urls import Resolver404, resolve
4542
from django.utils.functional import SimpleLazyObject
4643

4744
# Only available in Django 3.0+
@@ -86,14 +83,10 @@
8683
from sentry_sdk.traces import Span
8784

8885

89-
TRANSACTION_STYLE_VALUES = ("function_name", "url")
90-
91-
9286
class DjangoIntegration(Integration):
9387
"""
9488
Auto instrument a Django application.
9589
96-
:param transaction_style: How to derive transaction names. Either `"function_name"` or `"url"`. Defaults to `"url"`.
9790
:param middleware_spans: Whether to create spans for middleware. Defaults to `False`.
9891
:param signals_spans: Whether to create spans for signals. Defaults to `True`.
9992
:param signals_denylist: A list of signals to ignore when creating spans.
@@ -109,15 +102,13 @@ class DjangoIntegration(Integration):
109102
origin = f"auto.http.{identifier}"
110103
origin_db = f"auto.db.{identifier}"
111104

112-
transaction_style = ""
113105
middleware_spans: "Optional[bool]" = None
114106
signals_spans: "Optional[bool]" = None
115107
cache_spans: "Optional[bool]" = None
116108
signals_denylist: "list[signals.Signal]" = []
117109

118110
def __init__(
119111
self,
120-
transaction_style: str = "url",
121112
middleware_spans: bool = False,
122113
signals_spans: bool = True,
123114
cache_spans: bool = True,
@@ -127,12 +118,6 @@ def __init__(
127118
*,
128119
failed_request_status_codes: "Set[int]" = _DEFAULT_FAILED_REQUEST_STATUS_CODES,
129120
) -> None:
130-
if transaction_style not in TRANSACTION_STYLE_VALUES:
131-
raise ValueError(
132-
"Invalid value for transaction_style: %s (must be in %s)"
133-
% (transaction_style, TRANSACTION_STYLE_VALUES)
134-
)
135-
self.transaction_style = transaction_style
136121
self.middleware_spans = middleware_spans
137122

138123
self.signals_spans = signals_spans
@@ -390,48 +375,29 @@ def _patch_django_asgi_handler() -> None:
390375

391376
def _set_transaction_name_and_source(
392377
scope: "sentry_sdk.Scope",
393-
transaction_style: str,
394378
request: "WSGIRequest",
395379
route_path: "Optional[str]",
396380
) -> None:
397381
try:
398382
transaction_name = None
399-
if transaction_style == "function_name":
400-
fn = resolve(request.path).func
401-
transaction_name = transaction_from_function(getattr(fn, "view_class", fn))
402-
403-
elif transaction_style == "url" and route_path is not None:
383+
if route_path is not None:
404384
transaction_name = route_path
405385

406386
if transaction_name is None:
407387
transaction_name = request.path_info
408388
source = SegmentNameSource.URL
409389
else:
410-
source = SOURCE_FOR_STYLE[transaction_style]
390+
source = SegmentNameSource.ROUTE
411391

412392
scope.set_transaction_name(
413393
transaction_name,
414394
source=source,
415395
)
416396

417-
if transaction_style == "url" and route_path is not None:
397+
if route_path is not None:
418398
server_span = scope._server_segment_span
419399
if server_span is not None:
420400
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)
421-
except Resolver404:
422-
urlconf = import_module(settings.ROOT_URLCONF)
423-
# This exception only gets thrown when transaction_style is `function_name`
424-
# So we don't check here what style is configured
425-
if hasattr(urlconf, "handler404"):
426-
handler = urlconf.handler404
427-
if isinstance(handler, str):
428-
scope.set_transaction_name(handler)
429-
else:
430-
name = transaction_from_function(
431-
getattr(handler, "view_class", handler)
432-
)
433-
if name:
434-
scope.set_transaction_name(name)
435401
except Exception:
436402
pass
437403

@@ -464,17 +430,16 @@ def _before_get_response(request: "WSGIRequest") -> None:
464430
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)
465431

466432
# Rely on WSGI middleware to start a trace
467-
_set_transaction_name_and_source(
468-
scope, integration.transaction_style, request, route_path=route_path
469-
)
433+
_set_transaction_name_and_source(scope, request, route_path=route_path)
470434

471435
scope.add_event_processor(
472436
_make_wsgi_request_event_processor(weakref.ref(request), integration)
473437
)
474438

475439

476440
def _attempt_resolve_again(
477-
request: "WSGIRequest", scope: "sentry_sdk.Scope", transaction_style: str
441+
request: "WSGIRequest",
442+
scope: "sentry_sdk.Scope",
478443
) -> None:
479444
"""
480445
Some django middlewares overwrite request.urlconf
@@ -502,9 +467,7 @@ def _attempt_resolve_again(
502467
if server_span is not None and route_path is not None:
503468
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)
504469

505-
_set_transaction_name_and_source(
506-
scope, transaction_style, request, route_path=route_path
507-
)
470+
_set_transaction_name_and_source(scope, request, route_path=route_path)
508471

509472

510473
def _get_user_from_request_and_set_on_scope(request: "WSGIRequest") -> None:
@@ -546,9 +509,8 @@ def _after_get_response(request: "WSGIRequest") -> None:
546509
if integration is None:
547510
return
548511

549-
if integration.transaction_style == "url":
550-
scope = sentry_sdk.get_current_scope()
551-
_attempt_resolve_again(request, scope, integration.transaction_style)
512+
scope = sentry_sdk.get_current_scope()
513+
_attempt_resolve_again(request, scope)
552514

553515
if has_data_collection_enabled(client.options):
554516
if client.options["data_collection"]["user_info"]:
@@ -625,18 +587,17 @@ def _got_request_exception(request: "WSGIRequest" = None, **kwargs: "Any") -> No
625587
with capture_internal_exceptions():
626588
request._sentry_exception_reported = True
627589

628-
_capture_exception(sys.exc_info(), request, integration, handled=False)
590+
_capture_exception(sys.exc_info(), request, handled=False)
629591

630592

631593
def _capture_exception(
632594
exc_info: "Union[BaseException, ExcInfo]",
633595
request: "Optional[WSGIRequest]",
634-
integration: "DjangoIntegration",
635596
handled: bool,
636597
) -> None:
637-
if request is not None and integration.transaction_style == "url":
598+
if request is not None:
638599
scope = sentry_sdk.get_current_scope()
639-
_attempt_resolve_again(request, scope, integration.transaction_style)
600+
_attempt_resolve_again(request, scope)
640601

641602
event, hint = event_from_exception(
642603
exc_info,
@@ -696,7 +657,7 @@ def sentry_patched_response_for_exception(
696657
if not getattr(request, "_sentry_exception_reported", False):
697658
status_code = getattr(response, "status_code", None)
698659
if status_code in integration.failed_request_status_codes:
699-
_capture_exception(exc, request, integration, handled=True)
660+
_capture_exception(exc, request, handled=True)
700661

701662
return response
702663

‎tests/integrations/django/test_basic.py‎

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -158,28 +158,6 @@ def test_request_captured(
158158
}
159159

160160

161-
def test_transaction_with_class_view(
162-
sentry_init,
163-
client,
164-
capture_items,
165-
):
166-
sentry_init(
167-
integrations=[DjangoIntegration(transaction_style="function_name")],
168-
send_default_pii=True,
169-
)
170-
items = capture_items("event")
171-
content, status, headers = unpack_werkzeug_response(
172-
client.head(reverse("classbased"))
173-
)
174-
assert status.lower() == "200 ok"
175-
176-
(event,) = (item.payload for item in items)
177-
assert (
178-
event["transaction"] == "tests.integrations.django.myapp.views.ClassBasedView"
179-
)
180-
assert event["message"] == "hi"
181-
182-
183161
def test_has_trace_if_performance_enabled(
184162
sentry_init,
185163
client,
@@ -855,31 +833,23 @@ def get_connection_params(self):
855833

856834

857835
@pytest.mark.parametrize(
858-
"transaction_style,client_url,expected_transaction,expected_source,expected_response",
836+
"client_url,expected_transaction,expected_source,expected_response",
859837
[
860-
(
861-
"function_name",
862-
"/message",
863-
"tests.integrations.django.myapp.views.message",
864-
"component",
865-
b"ok",
866-
),
867-
("url", "/message", "/message", "route", b"ok"),
868-
("url", "/404", "/404", "url", b"404"),
838+
("/message", "/message", "route", b"ok"),
839+
("/404", "/404", "url", b"404"),
869840
],
870841
)
871-
def test_transaction_style(
842+
def test_segment_name(
872843
sentry_init,
873844
client,
874845
capture_items,
875-
transaction_style,
876846
client_url,
877847
expected_transaction,
878848
expected_source,
879849
expected_response,
880850
):
881851
sentry_init(
882-
integrations=[DjangoIntegration(transaction_style=transaction_style)],
852+
integrations=[DjangoIntegration()],
883853
traces_sample_rate=1.0,
884854
send_default_pii=True,
885855
)
@@ -900,31 +870,23 @@ def test_transaction_style(
900870

901871

902872
@pytest.mark.parametrize(
903-
"transaction_style,client_url,expected_transaction,expected_source,expected_response",
873+
"client_url,expected_transaction,expected_source,expected_response",
904874
[
905-
(
906-
"function_name",
907-
"/message",
908-
"tests.integrations.django.myapp.views.message",
909-
"component",
910-
b"ok",
911-
),
912-
("url", "/message", "/message", "route", b"ok"),
913-
("url", "/404", "/404", "url", b"404"),
875+
("/message", "/message", "route", b"ok"),
876+
("/404", "/404", "url", b"404"),
914877
],
915878
)
916-
def test_transaction_style_tracing_disabled(
879+
def test_segment_name_tracing_disabled(
917880
sentry_init,
918881
client,
919882
capture_items,
920-
transaction_style,
921883
client_url,
922884
expected_transaction,
923885
expected_source,
924886
expected_response,
925887
):
926888
sentry_init(
927-
integrations=[DjangoIntegration(transaction_style=transaction_style)],
889+
integrations=[DjangoIntegration()],
928890
send_default_pii=True,
929891
)
930892
items = capture_items("event")

0 commit comments

Comments
 (0)