Skip to content

Commit

Permalink
Add span for Django SimpleTemplateResponse rendering (#1818)
Browse files Browse the repository at this point in the history
  • Loading branch information
chdsbd authored Jan 4, 2023
1 parent 1578832 commit dfb04f5
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions sentry_sdk/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class OP:
SUBPROCESS_COMMUNICATE = "subprocess.communicate"
TEMPLATE_RENDER = "template.render"
VIEW_RENDER = "view.render"
VIEW_RESPONSE_RENDER = "view.response.render"
WEBSOCKET_SERVER = "websocket.server"


Expand Down
11 changes: 11 additions & 0 deletions sentry_sdk/integrations/django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,19 @@ def patch_views():
# type: () -> None

from django.core.handlers.base import BaseHandler
from django.template.response import SimpleTemplateResponse
from sentry_sdk.integrations.django import DjangoIntegration

old_make_view_atomic = BaseHandler.make_view_atomic
old_render = SimpleTemplateResponse.render

def sentry_patched_render(self):
# type: (SimpleTemplateResponse) -> Any
hub = Hub.current
with hub.start_span(
op=OP.VIEW_RESPONSE_RENDER, description="serialize response"
):
return old_render(self)

@_functools.wraps(old_make_view_atomic)
def sentry_patched_make_view_atomic(self, *args, **kwargs):
Expand Down Expand Up @@ -54,6 +64,7 @@ def sentry_patched_make_view_atomic(self, *args, **kwargs):

return sentry_wrapped_callback

SimpleTemplateResponse.render = sentry_patched_render
BaseHandler.make_view_atomic = sentry_patched_make_view_atomic


Expand Down
3 changes: 3 additions & 0 deletions tests/integrations/django/myapp/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ def path(path, *args, **kwargs):
)
)
urlpatterns.append(path("rest-hello", views.rest_hello, name="rest_hello"))
urlpatterns.append(
path("rest-json-response", views.rest_json_response, name="rest_json_response")
)
urlpatterns.append(
path(
"rest-permission-denied-exc",
Expand Down
5 changes: 5 additions & 0 deletions tests/integrations/django/myapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

try:
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(["POST"])
def rest_framework_exc(request):
Expand All @@ -29,6 +30,10 @@ def rest_hello(request):
def rest_permission_denied_exc(request):
raise PermissionDenied("bye")

@api_view(["GET"])
def rest_json_response(request):
return Response(dict(ok=True))

except ImportError:
pass

Expand Down
19 changes: 19 additions & 0 deletions tests/integrations/django/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,25 @@ def test_sql_dict_query_params(sentry_init, capture_events):
assert crumb["data"]["db.params"] == {"my_foo": 10}


@pytest.mark.forked
@pytest_mark_django_db_decorator()
def test_response_trace(sentry_init, client, capture_events, render_span_tree):
pytest.importorskip("rest_framework")
sentry_init(
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
)

events = capture_events()
content, status, headers = client.get(reverse("rest_json_response"))
assert status == "200 OK"

assert (
'- op="view.response.render": description="serialize response"'
in render_span_tree(events[0])
)


@pytest.mark.parametrize(
"query",
[
Expand Down

0 comments on commit dfb04f5

Please sign in to comment.