sentry-sdk 0.18.0__py2.py3-none-any.whl → 2.46.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sentry_sdk/__init__.py +48 -6
- sentry_sdk/_compat.py +64 -56
- sentry_sdk/_init_implementation.py +84 -0
- sentry_sdk/_log_batcher.py +172 -0
- sentry_sdk/_lru_cache.py +47 -0
- sentry_sdk/_metrics_batcher.py +167 -0
- sentry_sdk/_queue.py +81 -19
- sentry_sdk/_types.py +311 -11
- sentry_sdk/_werkzeug.py +98 -0
- sentry_sdk/ai/__init__.py +7 -0
- sentry_sdk/ai/monitoring.py +137 -0
- sentry_sdk/ai/utils.py +144 -0
- sentry_sdk/api.py +409 -67
- sentry_sdk/attachments.py +75 -0
- sentry_sdk/client.py +849 -103
- sentry_sdk/consts.py +1389 -34
- sentry_sdk/crons/__init__.py +10 -0
- sentry_sdk/crons/api.py +62 -0
- sentry_sdk/crons/consts.py +4 -0
- sentry_sdk/crons/decorator.py +135 -0
- sentry_sdk/debug.py +12 -15
- sentry_sdk/envelope.py +112 -61
- sentry_sdk/feature_flags.py +71 -0
- sentry_sdk/hub.py +442 -386
- sentry_sdk/integrations/__init__.py +228 -58
- sentry_sdk/integrations/_asgi_common.py +108 -0
- sentry_sdk/integrations/_wsgi_common.py +131 -40
- sentry_sdk/integrations/aiohttp.py +221 -72
- sentry_sdk/integrations/anthropic.py +439 -0
- sentry_sdk/integrations/argv.py +4 -6
- sentry_sdk/integrations/ariadne.py +161 -0
- sentry_sdk/integrations/arq.py +247 -0
- sentry_sdk/integrations/asgi.py +237 -135
- sentry_sdk/integrations/asyncio.py +144 -0
- sentry_sdk/integrations/asyncpg.py +208 -0
- sentry_sdk/integrations/atexit.py +13 -18
- sentry_sdk/integrations/aws_lambda.py +233 -80
- sentry_sdk/integrations/beam.py +27 -35
- sentry_sdk/integrations/boto3.py +137 -0
- sentry_sdk/integrations/bottle.py +91 -69
- sentry_sdk/integrations/celery/__init__.py +529 -0
- sentry_sdk/integrations/celery/beat.py +293 -0
- sentry_sdk/integrations/celery/utils.py +43 -0
- sentry_sdk/integrations/chalice.py +35 -28
- sentry_sdk/integrations/clickhouse_driver.py +177 -0
- sentry_sdk/integrations/cloud_resource_context.py +280 -0
- sentry_sdk/integrations/cohere.py +274 -0
- sentry_sdk/integrations/dedupe.py +32 -8
- sentry_sdk/integrations/django/__init__.py +343 -89
- sentry_sdk/integrations/django/asgi.py +201 -22
- sentry_sdk/integrations/django/caching.py +204 -0
- sentry_sdk/integrations/django/middleware.py +80 -32
- sentry_sdk/integrations/django/signals_handlers.py +91 -0
- sentry_sdk/integrations/django/templates.py +69 -2
- sentry_sdk/integrations/django/transactions.py +39 -14
- sentry_sdk/integrations/django/views.py +69 -16
- sentry_sdk/integrations/dramatiq.py +226 -0
- sentry_sdk/integrations/excepthook.py +19 -13
- sentry_sdk/integrations/executing.py +5 -6
- sentry_sdk/integrations/falcon.py +128 -65
- sentry_sdk/integrations/fastapi.py +141 -0
- sentry_sdk/integrations/flask.py +114 -75
- sentry_sdk/integrations/gcp.py +67 -36
- sentry_sdk/integrations/gnu_backtrace.py +14 -22
- sentry_sdk/integrations/google_genai/__init__.py +301 -0
- sentry_sdk/integrations/google_genai/consts.py +16 -0
- sentry_sdk/integrations/google_genai/streaming.py +155 -0
- sentry_sdk/integrations/google_genai/utils.py +576 -0
- sentry_sdk/integrations/gql.py +162 -0
- sentry_sdk/integrations/graphene.py +151 -0
- sentry_sdk/integrations/grpc/__init__.py +168 -0
- sentry_sdk/integrations/grpc/aio/__init__.py +7 -0
- sentry_sdk/integrations/grpc/aio/client.py +95 -0
- sentry_sdk/integrations/grpc/aio/server.py +100 -0
- sentry_sdk/integrations/grpc/client.py +91 -0
- sentry_sdk/integrations/grpc/consts.py +1 -0
- sentry_sdk/integrations/grpc/server.py +66 -0
- sentry_sdk/integrations/httpx.py +178 -0
- sentry_sdk/integrations/huey.py +174 -0
- sentry_sdk/integrations/huggingface_hub.py +378 -0
- sentry_sdk/integrations/langchain.py +1132 -0
- sentry_sdk/integrations/langgraph.py +337 -0
- sentry_sdk/integrations/launchdarkly.py +61 -0
- sentry_sdk/integrations/litellm.py +287 -0
- sentry_sdk/integrations/litestar.py +315 -0
- sentry_sdk/integrations/logging.py +261 -85
- sentry_sdk/integrations/loguru.py +213 -0
- sentry_sdk/integrations/mcp.py +566 -0
- sentry_sdk/integrations/modules.py +6 -33
- sentry_sdk/integrations/openai.py +725 -0
- sentry_sdk/integrations/openai_agents/__init__.py +61 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +140 -0
- sentry_sdk/integrations/openai_agents/patches/error_tracing.py +77 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +50 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +45 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +77 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +21 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +42 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +48 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +19 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +86 -0
- sentry_sdk/integrations/openai_agents/utils.py +199 -0
- sentry_sdk/integrations/openfeature.py +35 -0
- sentry_sdk/integrations/opentelemetry/__init__.py +7 -0
- sentry_sdk/integrations/opentelemetry/consts.py +5 -0
- sentry_sdk/integrations/opentelemetry/integration.py +58 -0
- sentry_sdk/integrations/opentelemetry/propagator.py +117 -0
- sentry_sdk/integrations/opentelemetry/span_processor.py +391 -0
- sentry_sdk/integrations/otlp.py +82 -0
- sentry_sdk/integrations/pure_eval.py +20 -11
- sentry_sdk/integrations/pydantic_ai/__init__.py +47 -0
- sentry_sdk/integrations/pydantic_ai/consts.py +1 -0
- sentry_sdk/integrations/pydantic_ai/patches/__init__.py +4 -0
- sentry_sdk/integrations/pydantic_ai/patches/agent_run.py +215 -0
- sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py +110 -0
- sentry_sdk/integrations/pydantic_ai/patches/model_request.py +40 -0
- sentry_sdk/integrations/pydantic_ai/patches/tools.py +98 -0
- sentry_sdk/integrations/pydantic_ai/spans/__init__.py +3 -0
- sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +246 -0
- sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py +49 -0
- sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +112 -0
- sentry_sdk/integrations/pydantic_ai/utils.py +223 -0
- sentry_sdk/integrations/pymongo.py +214 -0
- sentry_sdk/integrations/pyramid.py +71 -60
- sentry_sdk/integrations/quart.py +237 -0
- sentry_sdk/integrations/ray.py +165 -0
- sentry_sdk/integrations/redis/__init__.py +48 -0
- sentry_sdk/integrations/redis/_async_common.py +116 -0
- sentry_sdk/integrations/redis/_sync_common.py +119 -0
- sentry_sdk/integrations/redis/consts.py +19 -0
- sentry_sdk/integrations/redis/modules/__init__.py +0 -0
- sentry_sdk/integrations/redis/modules/caches.py +118 -0
- sentry_sdk/integrations/redis/modules/queries.py +65 -0
- sentry_sdk/integrations/redis/rb.py +32 -0
- sentry_sdk/integrations/redis/redis.py +69 -0
- sentry_sdk/integrations/redis/redis_cluster.py +107 -0
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +50 -0
- sentry_sdk/integrations/redis/utils.py +148 -0
- sentry_sdk/integrations/rq.py +62 -52
- sentry_sdk/integrations/rust_tracing.py +284 -0
- sentry_sdk/integrations/sanic.py +248 -114
- sentry_sdk/integrations/serverless.py +13 -22
- sentry_sdk/integrations/socket.py +96 -0
- sentry_sdk/integrations/spark/spark_driver.py +115 -62
- sentry_sdk/integrations/spark/spark_worker.py +42 -50
- sentry_sdk/integrations/sqlalchemy.py +82 -37
- sentry_sdk/integrations/starlette.py +737 -0
- sentry_sdk/integrations/starlite.py +292 -0
- sentry_sdk/integrations/statsig.py +37 -0
- sentry_sdk/integrations/stdlib.py +100 -58
- sentry_sdk/integrations/strawberry.py +394 -0
- sentry_sdk/integrations/sys_exit.py +70 -0
- sentry_sdk/integrations/threading.py +142 -38
- sentry_sdk/integrations/tornado.py +68 -53
- sentry_sdk/integrations/trytond.py +15 -20
- sentry_sdk/integrations/typer.py +60 -0
- sentry_sdk/integrations/unleash.py +33 -0
- sentry_sdk/integrations/unraisablehook.py +53 -0
- sentry_sdk/integrations/wsgi.py +126 -125
- sentry_sdk/logger.py +96 -0
- sentry_sdk/metrics.py +81 -0
- sentry_sdk/monitor.py +120 -0
- sentry_sdk/profiler/__init__.py +49 -0
- sentry_sdk/profiler/continuous_profiler.py +730 -0
- sentry_sdk/profiler/transaction_profiler.py +839 -0
- sentry_sdk/profiler/utils.py +195 -0
- sentry_sdk/scope.py +1542 -112
- sentry_sdk/scrubber.py +177 -0
- sentry_sdk/serializer.py +152 -210
- sentry_sdk/session.py +177 -0
- sentry_sdk/sessions.py +202 -179
- sentry_sdk/spotlight.py +242 -0
- sentry_sdk/tracing.py +1202 -294
- sentry_sdk/tracing_utils.py +1236 -0
- sentry_sdk/transport.py +693 -189
- sentry_sdk/types.py +52 -0
- sentry_sdk/utils.py +1395 -228
- sentry_sdk/worker.py +30 -17
- sentry_sdk-2.46.0.dist-info/METADATA +268 -0
- sentry_sdk-2.46.0.dist-info/RECORD +189 -0
- {sentry_sdk-0.18.0.dist-info → sentry_sdk-2.46.0.dist-info}/WHEEL +1 -1
- sentry_sdk-2.46.0.dist-info/entry_points.txt +2 -0
- sentry_sdk-2.46.0.dist-info/licenses/LICENSE +21 -0
- sentry_sdk/_functools.py +0 -66
- sentry_sdk/integrations/celery.py +0 -275
- sentry_sdk/integrations/redis.py +0 -103
- sentry_sdk-0.18.0.dist-info/LICENSE +0 -9
- sentry_sdk-0.18.0.dist-info/METADATA +0 -66
- sentry_sdk-0.18.0.dist-info/RECORD +0 -65
- {sentry_sdk-0.18.0.dist-info → sentry_sdk-2.46.0.dist-info}/top_level.txt +0 -0
sentry_sdk/spotlight.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import urllib.parse
|
|
5
|
+
import urllib.request
|
|
6
|
+
import urllib.error
|
|
7
|
+
import urllib3
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from itertools import chain, product
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Any
|
|
16
|
+
from typing import Callable
|
|
17
|
+
from typing import Dict
|
|
18
|
+
from typing import Optional
|
|
19
|
+
from typing import Self
|
|
20
|
+
|
|
21
|
+
from sentry_sdk.utils import (
|
|
22
|
+
logger as sentry_logger,
|
|
23
|
+
env_to_bool,
|
|
24
|
+
capture_internal_exceptions,
|
|
25
|
+
)
|
|
26
|
+
from sentry_sdk.envelope import Envelope
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger("spotlight")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
DEFAULT_SPOTLIGHT_URL = "http://localhost:8969/stream"
|
|
33
|
+
DJANGO_SPOTLIGHT_MIDDLEWARE_PATH = "sentry_sdk.spotlight.SpotlightMiddleware"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class SpotlightClient:
|
|
37
|
+
def __init__(self, url):
|
|
38
|
+
# type: (str) -> None
|
|
39
|
+
self.url = url
|
|
40
|
+
self.http = urllib3.PoolManager()
|
|
41
|
+
self.fails = 0
|
|
42
|
+
|
|
43
|
+
def capture_envelope(self, envelope):
|
|
44
|
+
# type: (Envelope) -> None
|
|
45
|
+
body = io.BytesIO()
|
|
46
|
+
envelope.serialize_into(body)
|
|
47
|
+
try:
|
|
48
|
+
req = self.http.request(
|
|
49
|
+
url=self.url,
|
|
50
|
+
body=body.getvalue(),
|
|
51
|
+
method="POST",
|
|
52
|
+
headers={
|
|
53
|
+
"Content-Type": "application/x-sentry-envelope",
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
req.close()
|
|
57
|
+
self.fails = 0
|
|
58
|
+
except Exception as e:
|
|
59
|
+
if self.fails < 2:
|
|
60
|
+
sentry_logger.warning(str(e))
|
|
61
|
+
self.fails += 1
|
|
62
|
+
elif self.fails == 2:
|
|
63
|
+
self.fails += 1
|
|
64
|
+
sentry_logger.warning(
|
|
65
|
+
"Looks like Spotlight is not running, will keep trying to send events but will not log errors."
|
|
66
|
+
)
|
|
67
|
+
# omitting self.fails += 1 in the `else:` case intentionally
|
|
68
|
+
# to avoid overflowing the variable if Spotlight never becomes reachable
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
from django.utils.deprecation import MiddlewareMixin
|
|
73
|
+
from django.http import HttpResponseServerError, HttpResponse, HttpRequest
|
|
74
|
+
from django.conf import settings
|
|
75
|
+
|
|
76
|
+
SPOTLIGHT_JS_ENTRY_PATH = "/assets/main.js"
|
|
77
|
+
SPOTLIGHT_JS_SNIPPET_PATTERN = (
|
|
78
|
+
"<script>window.__spotlight = {{ initOptions: {{ sidecarUrl: '{spotlight_url}', fullPage: false }} }};</script>\n"
|
|
79
|
+
'<script type="module" crossorigin src="{spotlight_js_url}"></script>\n'
|
|
80
|
+
)
|
|
81
|
+
SPOTLIGHT_ERROR_PAGE_SNIPPET = (
|
|
82
|
+
'<html><base href="{spotlight_url}">\n'
|
|
83
|
+
'<script>window.__spotlight = {{ initOptions: {{ fullPage: true, startFrom: "/errors/{event_id}" }}}};</script>\n'
|
|
84
|
+
)
|
|
85
|
+
CHARSET_PREFIX = "charset="
|
|
86
|
+
BODY_TAG_NAME = "body"
|
|
87
|
+
BODY_CLOSE_TAG_POSSIBILITIES = tuple(
|
|
88
|
+
"</{}>".format("".join(chars))
|
|
89
|
+
for chars in product(*zip(BODY_TAG_NAME.upper(), BODY_TAG_NAME.lower()))
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
class SpotlightMiddleware(MiddlewareMixin): # type: ignore[misc]
|
|
93
|
+
_spotlight_script = None # type: Optional[str]
|
|
94
|
+
_spotlight_url = None # type: Optional[str]
|
|
95
|
+
|
|
96
|
+
def __init__(self, get_response):
|
|
97
|
+
# type: (Self, Callable[..., HttpResponse]) -> None
|
|
98
|
+
super().__init__(get_response)
|
|
99
|
+
|
|
100
|
+
import sentry_sdk.api
|
|
101
|
+
|
|
102
|
+
self.sentry_sdk = sentry_sdk.api
|
|
103
|
+
|
|
104
|
+
spotlight_client = self.sentry_sdk.get_client().spotlight
|
|
105
|
+
if spotlight_client is None:
|
|
106
|
+
sentry_logger.warning(
|
|
107
|
+
"Cannot find Spotlight client from SpotlightMiddleware, disabling the middleware."
|
|
108
|
+
)
|
|
109
|
+
return None
|
|
110
|
+
# Spotlight URL has a trailing `/stream` part at the end so split it off
|
|
111
|
+
self._spotlight_url = urllib.parse.urljoin(spotlight_client.url, "../")
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def spotlight_script(self):
|
|
115
|
+
# type: (Self) -> Optional[str]
|
|
116
|
+
if self._spotlight_url is not None and self._spotlight_script is None:
|
|
117
|
+
try:
|
|
118
|
+
spotlight_js_url = urllib.parse.urljoin(
|
|
119
|
+
self._spotlight_url, SPOTLIGHT_JS_ENTRY_PATH
|
|
120
|
+
)
|
|
121
|
+
req = urllib.request.Request(
|
|
122
|
+
spotlight_js_url,
|
|
123
|
+
method="HEAD",
|
|
124
|
+
)
|
|
125
|
+
urllib.request.urlopen(req)
|
|
126
|
+
self._spotlight_script = SPOTLIGHT_JS_SNIPPET_PATTERN.format(
|
|
127
|
+
spotlight_url=self._spotlight_url,
|
|
128
|
+
spotlight_js_url=spotlight_js_url,
|
|
129
|
+
)
|
|
130
|
+
except urllib.error.URLError as err:
|
|
131
|
+
sentry_logger.debug(
|
|
132
|
+
"Cannot get Spotlight JS to inject at %s. SpotlightMiddleware will not be very useful.",
|
|
133
|
+
spotlight_js_url,
|
|
134
|
+
exc_info=err,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return self._spotlight_script
|
|
138
|
+
|
|
139
|
+
def process_response(self, _request, response):
|
|
140
|
+
# type: (Self, HttpRequest, HttpResponse) -> Optional[HttpResponse]
|
|
141
|
+
content_type_header = tuple(
|
|
142
|
+
p.strip()
|
|
143
|
+
for p in response.headers.get("Content-Type", "").lower().split(";")
|
|
144
|
+
)
|
|
145
|
+
content_type = content_type_header[0]
|
|
146
|
+
if len(content_type_header) > 1 and content_type_header[1].startswith(
|
|
147
|
+
CHARSET_PREFIX
|
|
148
|
+
):
|
|
149
|
+
encoding = content_type_header[1][len(CHARSET_PREFIX) :]
|
|
150
|
+
else:
|
|
151
|
+
encoding = "utf-8"
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
self.spotlight_script is not None
|
|
155
|
+
and not response.streaming
|
|
156
|
+
and content_type == "text/html"
|
|
157
|
+
):
|
|
158
|
+
content_length = len(response.content)
|
|
159
|
+
injection = self.spotlight_script.encode(encoding)
|
|
160
|
+
injection_site = next(
|
|
161
|
+
(
|
|
162
|
+
idx
|
|
163
|
+
for idx in (
|
|
164
|
+
response.content.rfind(body_variant.encode(encoding))
|
|
165
|
+
for body_variant in BODY_CLOSE_TAG_POSSIBILITIES
|
|
166
|
+
)
|
|
167
|
+
if idx > -1
|
|
168
|
+
),
|
|
169
|
+
content_length,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# This approach works even when we don't have a `</body>` tag
|
|
173
|
+
response.content = (
|
|
174
|
+
response.content[:injection_site]
|
|
175
|
+
+ injection
|
|
176
|
+
+ response.content[injection_site:]
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if response.has_header("Content-Length"):
|
|
180
|
+
response.headers["Content-Length"] = content_length + len(injection)
|
|
181
|
+
|
|
182
|
+
return response
|
|
183
|
+
|
|
184
|
+
def process_exception(self, _request, exception):
|
|
185
|
+
# type: (Self, HttpRequest, Exception) -> Optional[HttpResponseServerError]
|
|
186
|
+
if not settings.DEBUG or not self._spotlight_url:
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
spotlight = (
|
|
191
|
+
urllib.request.urlopen(self._spotlight_url).read().decode("utf-8")
|
|
192
|
+
)
|
|
193
|
+
except urllib.error.URLError:
|
|
194
|
+
return None
|
|
195
|
+
else:
|
|
196
|
+
event_id = self.sentry_sdk.capture_exception(exception)
|
|
197
|
+
return HttpResponseServerError(
|
|
198
|
+
spotlight.replace(
|
|
199
|
+
"<html>",
|
|
200
|
+
SPOTLIGHT_ERROR_PAGE_SNIPPET.format(
|
|
201
|
+
spotlight_url=self._spotlight_url, event_id=event_id
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
except ImportError:
|
|
207
|
+
settings = None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def setup_spotlight(options):
|
|
211
|
+
# type: (Dict[str, Any]) -> Optional[SpotlightClient]
|
|
212
|
+
_handler = logging.StreamHandler(sys.stderr)
|
|
213
|
+
_handler.setFormatter(logging.Formatter(" [spotlight] %(levelname)s: %(message)s"))
|
|
214
|
+
logger.addHandler(_handler)
|
|
215
|
+
logger.setLevel(logging.INFO)
|
|
216
|
+
|
|
217
|
+
url = options.get("spotlight")
|
|
218
|
+
|
|
219
|
+
if url is True:
|
|
220
|
+
url = DEFAULT_SPOTLIGHT_URL
|
|
221
|
+
|
|
222
|
+
if not isinstance(url, str):
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
with capture_internal_exceptions():
|
|
226
|
+
if (
|
|
227
|
+
settings is not None
|
|
228
|
+
and settings.DEBUG
|
|
229
|
+
and env_to_bool(os.environ.get("SENTRY_SPOTLIGHT_ON_ERROR", "1"))
|
|
230
|
+
and env_to_bool(os.environ.get("SENTRY_SPOTLIGHT_MIDDLEWARE", "1"))
|
|
231
|
+
):
|
|
232
|
+
middleware = settings.MIDDLEWARE
|
|
233
|
+
if DJANGO_SPOTLIGHT_MIDDLEWARE_PATH not in middleware:
|
|
234
|
+
settings.MIDDLEWARE = type(middleware)(
|
|
235
|
+
chain(middleware, (DJANGO_SPOTLIGHT_MIDDLEWARE_PATH,))
|
|
236
|
+
)
|
|
237
|
+
logger.info("Enabled Spotlight integration for Django")
|
|
238
|
+
|
|
239
|
+
client = SpotlightClient(url)
|
|
240
|
+
logger.info("Enabled Spotlight using sidecar at %s", url)
|
|
241
|
+
|
|
242
|
+
return client
|