Skip to content

Commit 891afee

Browse files
authored
fix(spotlight): More defensive Django spotlight middleware injection (#3665)
Turns out `settings.MIDDLEWARE` does not have to be a `list`. This causes issues as not all iterables support appending items to them. This PR leverages `itertools.chain` along with `type(settings.MIDDLEWARE)` to extend the middleware list while keeping its original type. It also adds a try-except block around the injection code to make sure it doesn't block anything further down in the unexpected case that it fails.
1 parent f493057 commit 891afee

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

sentry_sdk/spotlight.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import urllib.error
66
import urllib3
77

8+
from itertools import chain
9+
810
from typing import TYPE_CHECKING
911

1012
if TYPE_CHECKING:
@@ -13,11 +15,12 @@
1315
from typing import Dict
1416
from typing import Optional
1517

16-
from sentry_sdk.utils import logger, env_to_bool
18+
from sentry_sdk.utils import logger, env_to_bool, capture_internal_exceptions
1719
from sentry_sdk.envelope import Envelope
1820

1921

2022
DEFAULT_SPOTLIGHT_URL = "http://localhost:8969/stream"
23+
DJANGO_SPOTLIGHT_MIDDLEWARE_PATH = "sentry_sdk.spotlight.SpotlightMiddleware"
2124

2225

2326
class SpotlightClient:
@@ -112,9 +115,16 @@ def setup_spotlight(options):
112115
else:
113116
return None
114117

115-
if settings is not None and env_to_bool(
116-
os.environ.get("SENTRY_SPOTLIGHT_ON_ERROR", "1")
118+
if (
119+
settings is not None
120+
and settings.DEBUG
121+
and env_to_bool(os.environ.get("SENTRY_SPOTLIGHT_ON_ERROR", "1"))
117122
):
118-
settings.MIDDLEWARE.append("sentry_sdk.spotlight.SpotlightMiddleware")
123+
with capture_internal_exceptions():
124+
middleware = settings.MIDDLEWARE
125+
if DJANGO_SPOTLIGHT_MIDDLEWARE_PATH not in middleware:
126+
settings.MIDDLEWARE = type(middleware)(
127+
chain(middleware, (DJANGO_SPOTLIGHT_MIDDLEWARE_PATH,))
128+
)
119129

120130
return SpotlightClient(url)

tests/integrations/django/test_basic.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,7 @@ def test_ensures_spotlight_middleware_when_spotlight_is_enabled(sentry_init, set
12471247
Test that ensures if Spotlight is enabled, relevant SpotlightMiddleware
12481248
is added to middleware list in settings.
12491249
"""
1250+
settings.DEBUG = True
12501251
original_middleware = frozenset(settings.MIDDLEWARE)
12511252

12521253
sentry_init(integrations=[DjangoIntegration()], spotlight=True)
@@ -1263,6 +1264,7 @@ def test_ensures_no_spotlight_middleware_when_env_killswitch_is_false(
12631264
Test that ensures if Spotlight is enabled, but is set to a falsy value
12641265
the relevant SpotlightMiddleware is NOT added to middleware list in settings.
12651266
"""
1267+
settings.DEBUG = True
12661268
monkeypatch.setenv("SENTRY_SPOTLIGHT_ON_ERROR", "no")
12671269

12681270
original_middleware = frozenset(settings.MIDDLEWARE)
@@ -1281,6 +1283,8 @@ def test_ensures_no_spotlight_middleware_when_no_spotlight(
12811283
Test that ensures if Spotlight is not enabled
12821284
the relevant SpotlightMiddleware is NOT added to middleware list in settings.
12831285
"""
1286+
settings.DEBUG = True
1287+
12841288
# We should NOT have the middleware even if the env var is truthy if Spotlight is off
12851289
monkeypatch.setenv("SENTRY_SPOTLIGHT_ON_ERROR", "1")
12861290

0 commit comments

Comments
 (0)