Skip to content

Commit ea70268

Browse files
authored
fix(django): include the view class name in resource names (backport #5891 to 1.13) (#5906)
Resolves: #5711 ## Checklist - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines) are followed. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] OPTIONAL: PR description includes explicit acknowledgement of the performance implications of the change as reported in the benchmarks PR comment. ## Reviewer Checklist - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment.
1 parent 482c120 commit ea70268

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
@@ -188,7 +188,13 @@ def _set_resolver_tags(pin, span, request):
188188
# The request quite likely failed (e.g. 404) so we do the resolution anyway.
189189
resolver = get_resolver(getattr(request, "urlconf", None))
190190
resolver_match = resolver.resolve(request.path_info)
191-
handler = func_name(resolver_match[0])
191+
192+
if hasattr(resolver_match[0], "view_class"):
193+
# In django==4.0, view.__name__ defaults to <module>.views.view
194+
# Accessing view.view_class is equired for django>4.0 to get the name of underlying view
195+
handler = func_name(resolver_match[0].view_class)
196+
else:
197+
handler = func_name(resolver_match[0])
192198

193199
route = None
194200
# 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
@@ -291,3 +291,12 @@ def test_templates_disabled():
291291
resp = client.get("/template-view/")
292292
assert resp.status_code == 200
293293
assert resp.content == b"some content\n"
294+
295+
296+
@snapshot(ignores=["meta.http.useragent"])
297+
@pytest.mark.skipif(django.VERSION < (3, 0, 0), reason="ASGI not supported in django<3")
298+
def test_django_resource_handler():
299+
# regression test for: DataDog/dd-trace-py/issues/5711
300+
with daphne_client("application", additional_env={"DD_DJANGO_USE_HANDLER_RESOURCE_FORMAT": "true"}) as client:
301+
# Request a class based view
302+
assert client.get("simple/").status_code == 200

0 commit comments

Comments
 (0)