Skip to content

Commit 77b583a

Browse files
authored
Fix for partial signals in old Django and old Python versions. (#1641)
* Making sure signal names can be retrieved from partials and normal functions in all Python and Django versions. * Added test to safeguard the change.
1 parent 5348834 commit 77b583a

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

sentry_sdk/integrations/django/signals_handlers.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,32 @@
1313
from typing import List
1414

1515

16+
def _get_receiver_name(receiver):
17+
# type: (Callable[..., Any]) -> str
18+
name = ""
19+
20+
if hasattr(receiver, "__qualname__"):
21+
name += receiver.__qualname__
22+
elif hasattr(receiver, "__name__"): # Python 2.7 has no __qualname__
23+
name += receiver.__name__
24+
25+
if (
26+
name == ""
27+
): # certain functions (like partials) dont have a name so return the string representation
28+
return str(receiver)
29+
30+
if hasattr(receiver, "__module__"): # prepend with module, if there is one
31+
name = receiver.__module__ + "." + name
32+
33+
return name
34+
35+
1636
def patch_signals():
1737
# type: () -> None
1838
"""Patch django signal receivers to create a span"""
1939

2040
old_live_receivers = Signal._live_receivers
2141

22-
def _get_receiver_name(receiver):
23-
# type: (Callable[..., Any]) -> str
24-
name = receiver.__module__ + "."
25-
if hasattr(receiver, "__name__"):
26-
return name + receiver.__name__
27-
return name + str(receiver)
28-
2942
def _sentry_live_receivers(self, sender):
3043
# type: (Signal, Any) -> List[Callable[..., Any]]
3144
hub = Hub.current
@@ -35,11 +48,12 @@ def sentry_receiver_wrapper(receiver):
3548
# type: (Callable[..., Any]) -> Callable[..., Any]
3649
def wrapper(*args, **kwargs):
3750
# type: (Any, Any) -> Any
51+
signal_name = _get_receiver_name(receiver)
3852
with hub.start_span(
3953
op="django.signals",
40-
description=_get_receiver_name(receiver),
54+
description=signal_name,
4155
) as span:
42-
span.set_data("signal", _get_receiver_name(receiver))
56+
span.set_data("signal", signal_name)
4357
return receiver(*args, **kwargs)
4458

4559
return wrapper

tests/integrations/django/test_basic.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
from __future__ import absolute_import
22

3+
import json
34
import pytest
45
import pytest_django
5-
import json
6+
from functools import partial
67

78
from werkzeug.test import Client
89
from django import VERSION as DJANGO_VERSION
910
from django.contrib.auth.models import User
1011
from django.core.management import execute_from_command_line
1112
from django.db.utils import OperationalError, ProgrammingError, DataError
1213

13-
from sentry_sdk.integrations.executing import ExecutingIntegration
14-
1514
try:
1615
from django.urls import reverse
1716
except ImportError:
1817
from django.core.urlresolvers import reverse
1918

19+
from sentry_sdk._compat import PY2
2020
from sentry_sdk import capture_message, capture_exception, configure_scope
2121
from sentry_sdk.integrations.django import DjangoIntegration
22-
from functools import partial
22+
from sentry_sdk.integrations.django.signals_handlers import _get_receiver_name
23+
from sentry_sdk.integrations.executing import ExecutingIntegration
2324

2425
from tests.integrations.django.myapp.wsgi import application
2526

@@ -816,3 +817,22 @@ def test_custom_urlconf_middleware(
816817
assert "custom_urlconf_middleware" in render_span_tree(transaction_event)
817818

818819
settings.MIDDLEWARE.pop(0)
820+
821+
822+
def test_get_receiver_name():
823+
def dummy(a, b):
824+
return a + b
825+
826+
name = _get_receiver_name(dummy)
827+
828+
if PY2:
829+
assert name == "tests.integrations.django.test_basic.dummy"
830+
else:
831+
assert (
832+
name
833+
== "tests.integrations.django.test_basic.test_get_receiver_name.<locals>.dummy"
834+
)
835+
836+
a_partial = partial(dummy)
837+
name = _get_receiver_name(a_partial)
838+
assert name == str(a_partial)

0 commit comments

Comments
 (0)