Skip to content

Commit ad23d1c

Browse files
authored
fix: Fix crash on Django function-based middleware (getsentry#541)
* Test showing failure of function-based middleware in django. * fix: Fix crash of Django integration on Django 1.11 with function-based middleware * fix: Formatting * fix: Linters
1 parent aecb81f commit ad23d1c

File tree

3 files changed

+46
-25
lines changed

3 files changed

+46
-25
lines changed

sentry_sdk/integrations/django/middleware.py

+35-24
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
from django import VERSION as DJANGO_VERSION
88

99
from sentry_sdk import Hub
10-
from sentry_sdk.utils import ContextVar, transaction_from_function
10+
from sentry_sdk.utils import (
11+
ContextVar,
12+
transaction_from_function,
13+
capture_internal_exceptions,
14+
)
1115

1216
from sentry_sdk._types import MYPY
1317

@@ -64,29 +68,36 @@ def _wrap_middleware(middleware, middleware_name):
6468

6569
def _get_wrapped_method(old_method):
6670
# type: (F) -> F
67-
@wraps(old_method)
68-
def sentry_wrapped_method(*args, **kwargs):
69-
# type: (*Any, **Any) -> Any
70-
hub = Hub.current
71-
integration = hub.get_integration(DjangoIntegration)
72-
if integration is None or not integration.middleware_spans:
73-
return old_method(*args, **kwargs)
74-
75-
function_name = transaction_from_function(old_method)
76-
77-
description = middleware_name
78-
function_basename = getattr(old_method, "__name__", None)
79-
if function_basename:
80-
description = "{}.{}".format(description, function_basename)
81-
82-
with hub.start_span(
83-
op="django.middleware", description=description
84-
) as span:
85-
span.set_tag("django.function_name", function_name)
86-
span.set_tag("django.middleware_name", middleware_name)
87-
return old_method(*args, **kwargs)
88-
89-
return sentry_wrapped_method # type: ignore
71+
with capture_internal_exceptions():
72+
73+
def sentry_wrapped_method(*args, **kwargs):
74+
# type: (*Any, **Any) -> Any
75+
hub = Hub.current
76+
integration = hub.get_integration(DjangoIntegration)
77+
if integration is None or not integration.middleware_spans:
78+
return old_method(*args, **kwargs)
79+
80+
function_name = transaction_from_function(old_method)
81+
82+
description = middleware_name
83+
function_basename = getattr(old_method, "__name__", None)
84+
if function_basename:
85+
description = "{}.{}".format(description, function_basename)
86+
87+
with hub.start_span(
88+
op="django.middleware", description=description
89+
) as span:
90+
span.set_tag("django.function_name", function_name)
91+
span.set_tag("django.middleware_name", middleware_name)
92+
return old_method(*args, **kwargs)
93+
94+
try:
95+
# fails for __call__ of function on Python 2 (see py2.7-django-1.11)
96+
return wraps(old_method)(sentry_wrapped_method) # type: ignore
97+
except Exception:
98+
return sentry_wrapped_method # type: ignore
99+
100+
return old_method
90101

91102
class SentryWrappingMiddleware(object):
92103
def __init__(self, *args, **kwargs):

tests/integrations/django/myapp/settings.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,23 @@ def process_response(self, request, response):
6666
return response
6767

6868

69+
def TestFunctionMiddleware(get_response):
70+
def middleware(request):
71+
return get_response(request)
72+
73+
return middleware
74+
75+
6976
MIDDLEWARE_CLASSES = [
7077
"django.contrib.sessions.middleware.SessionMiddleware",
7178
"django.contrib.auth.middleware.AuthenticationMiddleware",
7279
"tests.integrations.django.myapp.settings.TestMiddleware",
7380
]
7481

7582
if MiddlewareMixin is not object:
76-
MIDDLEWARE = MIDDLEWARE_CLASSES
83+
MIDDLEWARE = MIDDLEWARE_CLASSES + [
84+
"tests.integrations.django.myapp.settings.TestFunctionMiddleware"
85+
]
7786

7887

7988
ROOT_URLCONF = "tests.integrations.django.myapp.urls"

tests/integrations/django/test_basic.py

+1
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ def test_middleware_spans(sentry_init, client, capture_events):
519519

520520
if DJANGO_VERSION >= (1, 10):
521521
reference_value = [
522+
"tests.integrations.django.myapp.settings.TestFunctionMiddleware.__call__",
522523
"tests.integrations.django.myapp.settings.TestMiddleware.__call__",
523524
"django.contrib.auth.middleware.AuthenticationMiddleware.__call__",
524525
"django.contrib.sessions.middleware.SessionMiddleware.__call__",

0 commit comments

Comments
 (0)