Skip to content

Conversation

@mabdinur
Copy link
Contributor

@mabdinur mabdinur commented Dec 14, 2021

Add support for django 4.0

Checklist

  • Added to the correct milestone.
  • Tests provided or description of manual testing performed is included in the code or PR.
  • Library documentation is updated.
  • Corp site documentation is updated (link to the PR).

@mabdinur mabdinur requested a review from a team as a code owner December 14, 2021 22:37
@mabdinur mabdinur added the changelog/no-changelog A changelog entry is not required for this PR. label Dec 14, 2021
Copy link
Contributor Author

@mabdinur mabdinur Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff between snapshot generated by django 4 and django 2.2 for test_safe_string_endocing

Django 4 instrumentation appends the name of the ListView class to the resource name of a django.view span.

 {
                                      "name": "django.view",
                                      "service": "django",
-                                     "resource": "tests.contrib.django.views.view",
+                                     "resource": "tests.contrib.django.views.SafeTemplateUserList",
                                      "trace_id": 0,
                                      "span_id": 26,
                                      "parent_id": 23,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add this to the PR description as well as a change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the other way around right? We lose SafeTemplateUserList for some reason in Django 4 and get tests.contrib.django.views.view instead?

Seems odd... maybe something changed in .as_view()? We should probably figure out why this changed since it could be breaking if a user has a facet on the resource of django view spans.

@brettlangdon brettlangdon removed the changelog/no-changelog A changelog entry is not required for this PR. label Dec 15, 2021
Copy link
Member

@brettlangdon brettlangdon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove references to dgango.urls.url

in PR description, should be django.urls.url

also, this will need a release note

Comment on lines 50 to 51
if django.VERSION >= (4, 0, 0):
CACHES["redis"]["BACKEND"] = "django.core.cache.backends.redis.RedisCache"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be cleaner to organize as... before CACHES is defined:

redis_backend = "django_redis.cache.RedisCache"
if django.VERSION >= (4, 0, 0):
    redis_backend = "django.core.cache.backends.redis.RedisCache"

CACHES = {
    ...
    "redis": {
        "BACKEND": redis_backend,
        "LOCATION": "..."
    },
    ...
}

a little cleaner than reaching into the nested dict later

if django.VERSION < (2, 0, 0):
from django.conf.urls import url
else:
from django.urls import re_path as url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably shouldn't do this, don't want to confuse anyone looking at all of the urlpatterns and expecting django.conf.urls.url instead of re_path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also a django 1.x app, why do we need this change?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer to just import re_path and use that instead rather than mapping it to url

}

if django.VERSION >= (4, 0, 0):
CACHES["redis"]["BACKEND"] = "django.core.cache.backends.redis.RedisCache"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

from .. import views


if django.VERSION < (2, 0, 0):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't be used with django 1 right, so is this needed?

Copy link
Contributor Author

@mabdinur mabdinur Dec 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope but this was a mistake that line should be django.VERSION < (4, 0, 0). I'd like to keep test coverage for django.conf.urls.url for django 2

if django.VERSION < (2, 0, 0):
from django.conf.urls import url
else:
from django.urls import re_path as url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here as above

if django.VERSION < (2, 0, 0):
from django.conf.urls import url
else:
from django.urls import re_path as url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, do we even test django_hosts with django 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope min version is 2.2. Good catch



if django.VERSION < (2, 0, 0):
from django.conf.urls import url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

if django.VERSION < (2, 0, 0):
from django.conf.urls import url
else:
from django.urls import re_path as url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, I'd prefer not to remap re_path to url

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mapped it to "handler". The reason why I made this change was to keep this pr small. In hindsight I should've prioritized readability

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add this to the PR description as well as a change



# django version < 2 does not support django.urls.re_path
# django version > 3 does not support django.conf.urls.url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean >=4.0?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we should be testing both when possible

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it's deprecated in django 3 but it's still supported

@mabdinur mabdinur force-pushed the munir/django-4.0 branch 4 times, most recently from e90d4b5 to f39707e Compare December 16, 2021 18:13
@mabdinur mabdinur force-pushed the munir/django-4.0 branch 2 times, most recently from efb7fc7 to d3d2d09 Compare December 16, 2021 19:08
@codecov-commenter
Copy link

codecov-commenter commented Dec 16, 2021

Codecov Report

Merging #3067 (4e2e41c) into master (d6d1705) will decrease coverage by 0.01%.
The diff coverage is 83.16%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3067      +/-   ##
==========================================
- Coverage   84.56%   84.54%   -0.02%     
==========================================
  Files         638      638              
  Lines       46069    46262     +193     
==========================================
+ Hits        38957    39114     +157     
- Misses       7112     7148      +36     
Impacted Files Coverage Δ
ddtrace/propagation/utils.py 0.00% <0.00%> (-100.00%) ⬇️
ddtrace/tracer.py 86.41% <0.00%> (ø)
...ests/contrib/django_hosts/django_app/extra_urls.py 0.00% <0.00%> (ø)
tests/profiling/collector/test_stack.py 0.00% <0.00%> (ø)
tests/profiling/collector/test_task.py 0.00% <0.00%> (ø)
ddtrace/sampler.py 94.66% <84.37%> (-2.04%) ⬇️
ddtrace/contrib/django/patch.py 83.66% <100.00%> (+0.05%) ⬆️
ddtrace/contrib/django/utils.py 89.26% <100.00%> (ø)
ddtrace/contrib/wsgi/wsgi.py 89.15% <100.00%> (ø)
ddtrace/internal/compat.py 95.37% <100.00%> (+0.97%) ⬆️
... and 19 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 921640e...4e2e41c. Read the comment docs.

Copy link
Member

@Kyle-Verhoog Kyle-Verhoog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Just a question about the subtle change to the view resource name and the docs. Otherwise lgtm

---
features:
- |
Add django 4.0 support. No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also have to update integrations.rst

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the other way around right? We lose SafeTemplateUserList for some reason in Django 4 and get tests.contrib.django.views.view instead?

Seems odd... maybe something changed in .as_view()? We should probably figure out why this changed since it could be breaking if a user has a facet on the resource of django view spans.

log.debug("Failed to instrument Django view %r", instance, exc_info=True)
view = func(*args, **kwargs)
return wrapt.FunctionWrapper(view, traced_func(django, "django.view", resource=func_name(view)))
return wrapt.FunctionWrapper(view, traced_func(django, "django.view", resource=func_name(instance)))
Copy link
Contributor Author

@mabdinur mabdinur Dec 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the func_name method view.__class__.__name__ returns "view" in django 4.0 instead of the name of the sub class (ex. tests.contrib.django.views.SomeViewClass). According to this comment, django 4.0 supports accessing the name of a View using theview_class attribute. Instead of this approach this change access the class name using an instance of a view and not view method. This approach is backwards compatible and can be used with the existing func_name utility.

@brettlangdon brettlangdon dismissed Kyle-Verhoog’s stale review December 21, 2021 15:55

Comments have been addressed

@brettlangdon brettlangdon merged commit 23827ed into master Dec 21, 2021
@brettlangdon brettlangdon deleted the munir/django-4.0 branch December 21, 2021 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants