Skip to content

Commit 90f8be5

Browse files
authored
fix(django): include the view class name in resource names (backport #5891 to 1.12) (#5907)
1 parent 1fd1840 commit 90f8be5

File tree

5 files changed

+504
-1
lines changed

5 files changed

+504
-1
lines changed

ddtrace/contrib/django/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,13 @@ def _set_resolver_tags(pin, span, request):
189189
# The request quite likely failed (e.g. 404) so we do the resolution anyway.
190190
resolver = get_resolver(getattr(request, "urlconf", None))
191191
resolver_match = resolver.resolve(request.path_info)
192-
handler = func_name(resolver_match[0])
192+
193+
if hasattr(resolver_match[0], "view_class"):
194+
# In django==4.0, view.__name__ defaults to <module>.views.view
195+
# Accessing view.view_class is equired for django>4.0 to get the name of underlying view
196+
handler = func_name(resolver_match[0].view_class)
197+
else:
198+
handler = func_name(resolver_match[0])
193199

194200
route = None
195201
# In Django >= 2.2.0 we can access the original route or regex pattern
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
django: Resolves an issue where the resource name of django.request span did not contain the full name of a view
5+
when ``DD_DJANGO_USE_HANDLER_RESOURCE_FORMAT=True``. This issue impacts ``django>=4.0``.

tests/contrib/django/test_django.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,30 @@ def test_request_view(client, test_spans):
492492
)
493493

494494

495+
def test_class_views_resource_names(client, test_spans):
496+
"""
497+
When making a request to a Django app and DD_DJANGO_USE_HANDLER_RESOURCE_FORMAT=True
498+
The resource name of the django.request span should contain the name of the view
499+
"""
500+
with override_config("django", dict(use_handler_resource_format=True)):
501+
# Send a request to a endpoint with a class based view
502+
resp = client.get("/simple/")
503+
assert resp.status_code == 200
504+
assert resp.content == b""
505+
506+
view_spans = list(test_spans.filter_spans(name="django.view"))
507+
assert len(view_spans) == 1
508+
# Assert span properties
509+
view_span = view_spans[0]
510+
view_span.assert_matches(
511+
name="django.view", service="django", resource="tests.contrib.django.views.BasicView", error=0
512+
)
513+
# Get request span
514+
request_span = list(test_spans.filter_spans(name="django.request"))[0]
515+
# Ensure resource name contains the view
516+
assert view_span.resource in request_span.resource
517+
518+
495519
def test_lambda_based_view(client, test_spans):
496520
# ensures that the internals are properly traced when using a function view
497521
assert client.get("/lambda-view/").status_code == 200

tests/contrib/django/test_django_snapshots.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,12 @@ def test_templates_disabled():
236236
resp = client.get("/template-view/")
237237
assert resp.status_code == 200
238238
assert resp.content == b"some content\n"
239+
240+
241+
@snapshot(ignores=["meta.http.useragent"])
242+
@pytest.mark.skipif(django.VERSION < (3, 0, 0), reason="ASGI not supported in django<3")
243+
def test_django_resource_handler():
244+
# regression test for: DataDog/dd-trace-py/issues/5711
245+
with daphne_client("application", additional_env={"DD_DJANGO_USE_HANDLER_RESOURCE_FORMAT": "true"}) as client:
246+
# Request a class based view
247+
assert client.get("simple/").status_code == 200

0 commit comments

Comments
 (0)