sentry-sdk 3.0.0a2__py2.py3-none-any.whl → 3.0.0a4__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.
Potentially problematic release.
This version of sentry-sdk might be problematic. Click here for more details.
- sentry_sdk/__init__.py +4 -0
- sentry_sdk/_compat.py +5 -12
- sentry_sdk/_init_implementation.py +7 -7
- sentry_sdk/_log_batcher.py +17 -29
- sentry_sdk/_lru_cache.py +7 -9
- sentry_sdk/_queue.py +2 -4
- sentry_sdk/_types.py +9 -16
- sentry_sdk/_werkzeug.py +5 -7
- sentry_sdk/ai/monitoring.py +45 -33
- sentry_sdk/ai/utils.py +8 -5
- sentry_sdk/api.py +91 -87
- sentry_sdk/attachments.py +10 -12
- sentry_sdk/client.py +119 -159
- sentry_sdk/consts.py +432 -223
- sentry_sdk/crons/api.py +16 -17
- sentry_sdk/crons/decorator.py +25 -27
- sentry_sdk/debug.py +4 -6
- sentry_sdk/envelope.py +46 -112
- sentry_sdk/feature_flags.py +9 -15
- sentry_sdk/integrations/__init__.py +24 -19
- sentry_sdk/integrations/_asgi_common.py +16 -18
- sentry_sdk/integrations/_wsgi_common.py +22 -33
- sentry_sdk/integrations/aiohttp.py +33 -31
- sentry_sdk/integrations/anthropic.py +43 -38
- sentry_sdk/integrations/argv.py +3 -4
- sentry_sdk/integrations/ariadne.py +16 -18
- sentry_sdk/integrations/arq.py +20 -29
- sentry_sdk/integrations/asgi.py +63 -37
- sentry_sdk/integrations/asyncio.py +15 -17
- sentry_sdk/integrations/asyncpg.py +1 -1
- sentry_sdk/integrations/atexit.py +6 -10
- sentry_sdk/integrations/aws_lambda.py +26 -36
- sentry_sdk/integrations/beam.py +10 -18
- sentry_sdk/integrations/boto3.py +20 -18
- sentry_sdk/integrations/bottle.py +25 -34
- sentry_sdk/integrations/celery/__init__.py +40 -59
- sentry_sdk/integrations/celery/beat.py +22 -26
- sentry_sdk/integrations/celery/utils.py +15 -17
- sentry_sdk/integrations/chalice.py +8 -10
- sentry_sdk/integrations/clickhouse_driver.py +22 -32
- sentry_sdk/integrations/cloud_resource_context.py +9 -16
- sentry_sdk/integrations/cohere.py +19 -25
- sentry_sdk/integrations/dedupe.py +5 -8
- sentry_sdk/integrations/django/__init__.py +69 -74
- sentry_sdk/integrations/django/asgi.py +25 -33
- sentry_sdk/integrations/django/caching.py +24 -20
- sentry_sdk/integrations/django/middleware.py +18 -21
- sentry_sdk/integrations/django/signals_handlers.py +12 -11
- sentry_sdk/integrations/django/templates.py +21 -18
- sentry_sdk/integrations/django/transactions.py +16 -11
- sentry_sdk/integrations/django/views.py +8 -12
- sentry_sdk/integrations/dramatiq.py +21 -21
- sentry_sdk/integrations/excepthook.py +10 -10
- sentry_sdk/integrations/executing.py +3 -4
- sentry_sdk/integrations/falcon.py +27 -42
- sentry_sdk/integrations/fastapi.py +13 -16
- sentry_sdk/integrations/flask.py +31 -38
- sentry_sdk/integrations/gcp.py +13 -16
- sentry_sdk/integrations/gnu_backtrace.py +7 -20
- sentry_sdk/integrations/gql.py +16 -17
- sentry_sdk/integrations/graphene.py +14 -13
- sentry_sdk/integrations/grpc/__init__.py +3 -2
- sentry_sdk/integrations/grpc/aio/client.py +2 -2
- sentry_sdk/integrations/grpc/aio/server.py +15 -14
- sentry_sdk/integrations/grpc/client.py +21 -11
- sentry_sdk/integrations/grpc/consts.py +2 -0
- sentry_sdk/integrations/grpc/server.py +12 -8
- sentry_sdk/integrations/httpx.py +11 -14
- sentry_sdk/integrations/huey.py +14 -21
- sentry_sdk/integrations/huggingface_hub.py +17 -17
- sentry_sdk/integrations/langchain.py +204 -114
- sentry_sdk/integrations/launchdarkly.py +13 -10
- sentry_sdk/integrations/litestar.py +40 -38
- sentry_sdk/integrations/logging.py +29 -36
- sentry_sdk/integrations/loguru.py +16 -20
- sentry_sdk/integrations/modules.py +3 -4
- sentry_sdk/integrations/openai.py +421 -204
- sentry_sdk/integrations/openai_agents/__init__.py +49 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
- sentry_sdk/integrations/openai_agents/utils.py +153 -0
- sentry_sdk/integrations/openfeature.py +12 -8
- sentry_sdk/integrations/pure_eval.py +6 -10
- sentry_sdk/integrations/pymongo.py +14 -18
- sentry_sdk/integrations/pyramid.py +31 -36
- sentry_sdk/integrations/quart.py +23 -28
- sentry_sdk/integrations/ray.py +73 -64
- sentry_sdk/integrations/redis/__init__.py +7 -4
- sentry_sdk/integrations/redis/_async_common.py +18 -12
- sentry_sdk/integrations/redis/_sync_common.py +16 -15
- sentry_sdk/integrations/redis/modules/caches.py +17 -8
- sentry_sdk/integrations/redis/modules/queries.py +9 -8
- sentry_sdk/integrations/redis/rb.py +3 -2
- sentry_sdk/integrations/redis/redis.py +4 -4
- sentry_sdk/integrations/redis/redis_cluster.py +10 -8
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
- sentry_sdk/integrations/redis/utils.py +21 -22
- sentry_sdk/integrations/rq.py +13 -16
- sentry_sdk/integrations/rust_tracing.py +10 -7
- sentry_sdk/integrations/sanic.py +34 -46
- sentry_sdk/integrations/serverless.py +22 -27
- sentry_sdk/integrations/socket.py +29 -17
- sentry_sdk/integrations/spark/__init__.py +1 -0
- sentry_sdk/integrations/spark/spark_driver.py +45 -83
- sentry_sdk/integrations/spark/spark_worker.py +7 -11
- sentry_sdk/integrations/sqlalchemy.py +22 -19
- sentry_sdk/integrations/starlette.py +89 -93
- sentry_sdk/integrations/starlite.py +31 -37
- sentry_sdk/integrations/statsig.py +5 -4
- sentry_sdk/integrations/stdlib.py +32 -28
- sentry_sdk/integrations/strawberry.py +63 -50
- sentry_sdk/integrations/sys_exit.py +7 -11
- sentry_sdk/integrations/threading.py +13 -15
- sentry_sdk/integrations/tornado.py +28 -32
- sentry_sdk/integrations/trytond.py +4 -3
- sentry_sdk/integrations/typer.py +8 -6
- sentry_sdk/integrations/unleash.py +5 -4
- sentry_sdk/integrations/wsgi.py +47 -46
- sentry_sdk/logger.py +13 -9
- sentry_sdk/monitor.py +16 -28
- sentry_sdk/opentelemetry/consts.py +11 -4
- sentry_sdk/opentelemetry/contextvars_context.py +17 -15
- sentry_sdk/opentelemetry/propagator.py +38 -21
- sentry_sdk/opentelemetry/sampler.py +51 -34
- sentry_sdk/opentelemetry/scope.py +46 -37
- sentry_sdk/opentelemetry/span_processor.py +43 -59
- sentry_sdk/opentelemetry/tracing.py +32 -12
- sentry_sdk/opentelemetry/utils.py +180 -196
- sentry_sdk/profiler/continuous_profiler.py +108 -97
- sentry_sdk/profiler/transaction_profiler.py +70 -97
- sentry_sdk/profiler/utils.py +11 -15
- sentry_sdk/scope.py +251 -264
- sentry_sdk/scrubber.py +22 -26
- sentry_sdk/serializer.py +48 -65
- sentry_sdk/session.py +44 -61
- sentry_sdk/sessions.py +35 -49
- sentry_sdk/spotlight.py +15 -21
- sentry_sdk/tracing.py +118 -184
- sentry_sdk/tracing_utils.py +103 -123
- sentry_sdk/transport.py +131 -157
- sentry_sdk/utils.py +278 -309
- sentry_sdk/worker.py +16 -28
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
- sentry_sdk-3.0.0a4.dist-info/RECORD +168 -0
- sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/top_level.txt +0 -0
sentry_sdk/client.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import os
|
|
2
3
|
import uuid
|
|
3
4
|
import random
|
|
@@ -5,7 +6,7 @@ import socket
|
|
|
5
6
|
from collections.abc import Mapping
|
|
6
7
|
from datetime import datetime, timezone
|
|
7
8
|
from importlib import import_module
|
|
8
|
-
from typing import TYPE_CHECKING,
|
|
9
|
+
from typing import TYPE_CHECKING, overload
|
|
9
10
|
|
|
10
11
|
import sentry_sdk
|
|
11
12
|
from sentry_sdk._compat import check_uwsgi_thread_support
|
|
@@ -45,16 +46,18 @@ from sentry_sdk.profiler.transaction_profiler import (
|
|
|
45
46
|
)
|
|
46
47
|
from sentry_sdk.scrubber import EventScrubber
|
|
47
48
|
from sentry_sdk.monitor import Monitor
|
|
48
|
-
from sentry_sdk.spotlight import setup_spotlight
|
|
49
49
|
|
|
50
50
|
if TYPE_CHECKING:
|
|
51
|
-
from typing import
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
from typing import (
|
|
52
|
+
Any,
|
|
53
|
+
Callable,
|
|
54
|
+
Optional,
|
|
55
|
+
Sequence,
|
|
56
|
+
Type,
|
|
57
|
+
Union,
|
|
58
|
+
TypeVar,
|
|
59
|
+
Dict,
|
|
60
|
+
)
|
|
58
61
|
|
|
59
62
|
from sentry_sdk._types import Event, Hint, SDKInfo, Log
|
|
60
63
|
from sentry_sdk.integrations import Integration
|
|
@@ -64,22 +67,22 @@ if TYPE_CHECKING:
|
|
|
64
67
|
from sentry_sdk.transport import Transport
|
|
65
68
|
from sentry_sdk._log_batcher import LogBatcher
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
IntegrationType = TypeVar("IntegrationType", bound=Integration) # noqa: E741
|
|
71
|
+
|
|
68
72
|
|
|
69
73
|
_client_init_debug = ContextVar("client_init_debug")
|
|
70
74
|
|
|
71
75
|
|
|
72
|
-
SDK_INFO = {
|
|
76
|
+
SDK_INFO: SDKInfo = {
|
|
73
77
|
"name": "sentry.python", # SDK name will be overridden after integrations have been loaded with sentry_sdk.integrations.setup_integrations()
|
|
74
78
|
"version": VERSION,
|
|
75
79
|
"packages": [{"name": "pypi:sentry-sdk", "version": VERSION}],
|
|
76
|
-
}
|
|
80
|
+
}
|
|
77
81
|
|
|
78
82
|
|
|
79
|
-
def _get_options(*args, **kwargs):
|
|
80
|
-
# type: (*Optional[str], **Any) -> Dict[str, Any]
|
|
83
|
+
def _get_options(*args: Optional[str], **kwargs: Any) -> Dict[str, Any]:
|
|
81
84
|
if args and (isinstance(args[0], (bytes, str)) or args[0] is None):
|
|
82
|
-
dsn = args[0]
|
|
85
|
+
dsn: Optional[str] = args[0]
|
|
83
86
|
args = args[1:]
|
|
84
87
|
else:
|
|
85
88
|
dsn = None
|
|
@@ -149,37 +152,31 @@ class BaseClient:
|
|
|
149
152
|
The basic definition of a client that is used for sending data to Sentry.
|
|
150
153
|
"""
|
|
151
154
|
|
|
152
|
-
spotlight
|
|
155
|
+
spotlight: Optional[SpotlightClient] = None
|
|
153
156
|
|
|
154
|
-
def __init__(self, options=None):
|
|
155
|
-
|
|
156
|
-
self.options = (
|
|
157
|
+
def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
|
|
158
|
+
self.options: Dict[str, Any] = (
|
|
157
159
|
options if options is not None else DEFAULT_OPTIONS
|
|
158
|
-
)
|
|
160
|
+
)
|
|
159
161
|
|
|
160
|
-
self.transport
|
|
161
|
-
self.monitor
|
|
162
|
-
self.log_batcher
|
|
162
|
+
self.transport: Optional[Transport] = None
|
|
163
|
+
self.monitor: Optional[Monitor] = None
|
|
164
|
+
self.log_batcher: Optional[LogBatcher] = None
|
|
163
165
|
|
|
164
|
-
def __getstate__(self, *args, **kwargs):
|
|
165
|
-
# type: (*Any, **Any) -> Any
|
|
166
|
+
def __getstate__(self, *args: Any, **kwargs: Any) -> Any:
|
|
166
167
|
return {"options": {}}
|
|
167
168
|
|
|
168
|
-
def __setstate__(self, *args, **kwargs):
|
|
169
|
-
# type: (*Any, **Any) -> None
|
|
169
|
+
def __setstate__(self, *args: Any, **kwargs: Any) -> None:
|
|
170
170
|
pass
|
|
171
171
|
|
|
172
172
|
@property
|
|
173
|
-
def dsn(self):
|
|
174
|
-
# type: () -> Optional[str]
|
|
173
|
+
def dsn(self) -> Optional[str]:
|
|
175
174
|
return None
|
|
176
175
|
|
|
177
|
-
def should_send_default_pii(self):
|
|
178
|
-
# type: () -> bool
|
|
176
|
+
def should_send_default_pii(self) -> bool:
|
|
179
177
|
return False
|
|
180
178
|
|
|
181
|
-
def is_active(self):
|
|
182
|
-
# type: () -> bool
|
|
179
|
+
def is_active(self) -> bool:
|
|
183
180
|
"""
|
|
184
181
|
.. versionadded:: 2.0.0
|
|
185
182
|
|
|
@@ -187,48 +184,40 @@ class BaseClient:
|
|
|
187
184
|
"""
|
|
188
185
|
return False
|
|
189
186
|
|
|
190
|
-
def capture_event(self, *args, **kwargs):
|
|
191
|
-
# type: (*Any, **Any) -> Optional[str]
|
|
187
|
+
def capture_event(self, *args: Any, **kwargs: Any) -> Optional[str]:
|
|
192
188
|
return None
|
|
193
189
|
|
|
194
|
-
def _capture_experimental_log(self, log):
|
|
195
|
-
# type: (Log) -> None
|
|
190
|
+
def _capture_experimental_log(self, log: "Log") -> None:
|
|
196
191
|
pass
|
|
197
192
|
|
|
198
|
-
def capture_session(self, *args, **kwargs):
|
|
199
|
-
# type: (*Any, **Any) -> None
|
|
193
|
+
def capture_session(self, *args: Any, **kwargs: Any) -> None:
|
|
200
194
|
return None
|
|
201
195
|
|
|
202
196
|
if TYPE_CHECKING:
|
|
203
197
|
|
|
204
198
|
@overload
|
|
205
|
-
def get_integration(self, name_or_class):
|
|
206
|
-
# type: (str) -> Optional[Integration]
|
|
207
|
-
...
|
|
199
|
+
def get_integration(self, name_or_class: str) -> Optional[Integration]: ...
|
|
208
200
|
|
|
209
201
|
@overload
|
|
210
|
-
def get_integration(
|
|
211
|
-
|
|
212
|
-
|
|
202
|
+
def get_integration(
|
|
203
|
+
self, name_or_class: type[IntegrationType]
|
|
204
|
+
) -> Optional[IntegrationType]: ...
|
|
213
205
|
|
|
214
|
-
def get_integration(
|
|
215
|
-
|
|
206
|
+
def get_integration(
|
|
207
|
+
self, name_or_class: Union[str, type[Integration]]
|
|
208
|
+
) -> Optional[Integration]:
|
|
216
209
|
return None
|
|
217
210
|
|
|
218
|
-
def close(self, *args, **kwargs):
|
|
219
|
-
# type: (*Any, **Any) -> None
|
|
211
|
+
def close(self, *args: Any, **kwargs: Any) -> None:
|
|
220
212
|
return None
|
|
221
213
|
|
|
222
|
-
def flush(self, *args, **kwargs):
|
|
223
|
-
# type: (*Any, **Any) -> None
|
|
214
|
+
def flush(self, *args: Any, **kwargs: Any) -> None:
|
|
224
215
|
return None
|
|
225
216
|
|
|
226
|
-
def __enter__(self):
|
|
227
|
-
# type: () -> BaseClient
|
|
217
|
+
def __enter__(self) -> BaseClient:
|
|
228
218
|
return self
|
|
229
219
|
|
|
230
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
231
|
-
# type: (Any, Any, Any) -> None
|
|
220
|
+
def __exit__(self, exc_type: Any, exc_value: Any, tb: Any) -> None:
|
|
232
221
|
return None
|
|
233
222
|
|
|
234
223
|
|
|
@@ -252,22 +241,20 @@ class _Client(BaseClient):
|
|
|
252
241
|
Alias of :py:class:`sentry_sdk.Client`. (Was created for better intelisense support)
|
|
253
242
|
"""
|
|
254
243
|
|
|
255
|
-
def __init__(self, *args, **kwargs):
|
|
256
|
-
|
|
257
|
-
super(_Client, self).__init__(options=get_options(*args, **kwargs))
|
|
244
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
245
|
+
super(_Client, self).__init__(options=_get_options(*args, **kwargs))
|
|
258
246
|
self._init_impl()
|
|
259
247
|
|
|
260
|
-
def __getstate__(self):
|
|
261
|
-
# type: () -> Any
|
|
248
|
+
def __getstate__(self) -> Any:
|
|
262
249
|
return {"options": self.options}
|
|
263
250
|
|
|
264
|
-
def __setstate__(self, state):
|
|
265
|
-
# type: (Any) -> None
|
|
251
|
+
def __setstate__(self, state: Any) -> None:
|
|
266
252
|
self.options = state["options"]
|
|
267
253
|
self._init_impl()
|
|
268
254
|
|
|
269
|
-
def _setup_instrumentation(
|
|
270
|
-
|
|
255
|
+
def _setup_instrumentation(
|
|
256
|
+
self, functions_to_trace: Sequence[Dict[str, str]]
|
|
257
|
+
) -> None:
|
|
271
258
|
"""
|
|
272
259
|
Instruments the functions given in the list `functions_to_trace` with the `@sentry_sdk.tracing.trace` decorator.
|
|
273
260
|
"""
|
|
@@ -317,12 +304,10 @@ class _Client(BaseClient):
|
|
|
317
304
|
e,
|
|
318
305
|
)
|
|
319
306
|
|
|
320
|
-
def _init_impl(self):
|
|
321
|
-
# type: () -> None
|
|
307
|
+
def _init_impl(self) -> None:
|
|
322
308
|
old_debug = _client_init_debug.get(False)
|
|
323
309
|
|
|
324
|
-
def _capture_envelope(envelope):
|
|
325
|
-
# type: (Envelope) -> None
|
|
310
|
+
def _capture_envelope(envelope: Envelope) -> None:
|
|
326
311
|
if self.transport is not None:
|
|
327
312
|
self.transport.capture_envelope(envelope)
|
|
328
313
|
|
|
@@ -337,9 +322,9 @@ class _Client(BaseClient):
|
|
|
337
322
|
|
|
338
323
|
self.session_flusher = SessionFlusher(capture_func=_capture_envelope)
|
|
339
324
|
|
|
340
|
-
experiments = self.options.get("_experiments", {})
|
|
341
325
|
self.log_batcher = None
|
|
342
|
-
|
|
326
|
+
|
|
327
|
+
if self.options.get("enable_logs") is True:
|
|
343
328
|
from sentry_sdk._log_batcher import LogBatcher
|
|
344
329
|
|
|
345
330
|
self.log_batcher = LogBatcher(capture_func=_capture_envelope)
|
|
@@ -372,6 +357,10 @@ class _Client(BaseClient):
|
|
|
372
357
|
)
|
|
373
358
|
|
|
374
359
|
if self.options.get("spotlight"):
|
|
360
|
+
# This is intentionally here to prevent setting up spotlight
|
|
361
|
+
# stuff we don't need unless spotlight is explicitly enabled
|
|
362
|
+
from sentry_sdk.spotlight import setup_spotlight
|
|
363
|
+
|
|
375
364
|
self.spotlight = setup_spotlight(self.options)
|
|
376
365
|
if not self.options["dsn"]:
|
|
377
366
|
sample_all = lambda *_args, **_kwargs: 1.0
|
|
@@ -423,8 +412,7 @@ class _Client(BaseClient):
|
|
|
423
412
|
# need to check if it's safe to use them.
|
|
424
413
|
check_uwsgi_thread_support()
|
|
425
414
|
|
|
426
|
-
def is_active(self):
|
|
427
|
-
# type: () -> bool
|
|
415
|
+
def is_active(self) -> bool:
|
|
428
416
|
"""
|
|
429
417
|
.. versionadded:: 2.0.0
|
|
430
418
|
|
|
@@ -432,8 +420,7 @@ class _Client(BaseClient):
|
|
|
432
420
|
"""
|
|
433
421
|
return True
|
|
434
422
|
|
|
435
|
-
def should_send_default_pii(self):
|
|
436
|
-
# type: () -> bool
|
|
423
|
+
def should_send_default_pii(self) -> bool:
|
|
437
424
|
"""
|
|
438
425
|
.. versionadded:: 2.0.0
|
|
439
426
|
|
|
@@ -442,28 +429,26 @@ class _Client(BaseClient):
|
|
|
442
429
|
return self.options.get("send_default_pii") or False
|
|
443
430
|
|
|
444
431
|
@property
|
|
445
|
-
def dsn(self):
|
|
446
|
-
# type: () -> Optional[str]
|
|
432
|
+
def dsn(self) -> Optional[str]:
|
|
447
433
|
"""Returns the configured DSN as string."""
|
|
448
434
|
return self.options["dsn"]
|
|
449
435
|
|
|
450
436
|
def _prepare_event(
|
|
451
437
|
self,
|
|
452
|
-
event
|
|
453
|
-
hint
|
|
454
|
-
scope
|
|
455
|
-
):
|
|
456
|
-
# type: (...) -> Optional[Event]
|
|
438
|
+
event: Event,
|
|
439
|
+
hint: Hint,
|
|
440
|
+
scope: Optional[Scope],
|
|
441
|
+
) -> Optional[Event]:
|
|
457
442
|
|
|
458
|
-
previous_total_spans
|
|
459
|
-
previous_total_breadcrumbs
|
|
443
|
+
previous_total_spans: Optional[int] = None
|
|
444
|
+
previous_total_breadcrumbs: Optional[int] = None
|
|
460
445
|
|
|
461
446
|
if event.get("timestamp") is None:
|
|
462
447
|
event["timestamp"] = datetime.now(timezone.utc)
|
|
463
448
|
|
|
464
449
|
if scope is not None:
|
|
465
450
|
is_transaction = event.get("type") == "transaction"
|
|
466
|
-
spans_before = len(
|
|
451
|
+
spans_before = len(event.get("spans", []))
|
|
467
452
|
event_ = scope.apply_to_event(event, hint, self.options)
|
|
468
453
|
|
|
469
454
|
# one of the event/error processors returned None
|
|
@@ -481,16 +466,14 @@ class _Client(BaseClient):
|
|
|
481
466
|
)
|
|
482
467
|
return None
|
|
483
468
|
|
|
484
|
-
event = event_
|
|
485
|
-
spans_delta = spans_before - len(
|
|
486
|
-
cast(List[Dict[str, object]], event.get("spans", []))
|
|
487
|
-
)
|
|
469
|
+
event = event_
|
|
470
|
+
spans_delta = spans_before - len(event.get("spans", []))
|
|
488
471
|
if is_transaction and spans_delta > 0 and self.transport is not None:
|
|
489
472
|
self.transport.record_lost_event(
|
|
490
473
|
"event_processor", data_category="span", quantity=spans_delta
|
|
491
474
|
)
|
|
492
475
|
|
|
493
|
-
dropped_spans = event.pop("_dropped_spans", 0) + spans_delta
|
|
476
|
+
dropped_spans: int = event.pop("_dropped_spans", 0) + spans_delta
|
|
494
477
|
if dropped_spans > 0:
|
|
495
478
|
previous_total_spans = spans_before + dropped_spans
|
|
496
479
|
if scope._n_breadcrumbs_truncated > 0:
|
|
@@ -562,14 +545,11 @@ class _Client(BaseClient):
|
|
|
562
545
|
# Postprocess the event here so that annotated types do
|
|
563
546
|
# generally not surface in before_send
|
|
564
547
|
if event is not None:
|
|
565
|
-
event =
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
max_value_length=self.options.get("max_value_length"),
|
|
571
|
-
custom_repr=self.options.get("custom_repr"),
|
|
572
|
-
),
|
|
548
|
+
event: Event = serialize( # type: ignore[no-redef]
|
|
549
|
+
event,
|
|
550
|
+
max_request_body_size=self.options.get("max_request_body_size"),
|
|
551
|
+
max_value_length=self.options.get("max_value_length"),
|
|
552
|
+
custom_repr=self.options.get("custom_repr"),
|
|
573
553
|
)
|
|
574
554
|
|
|
575
555
|
before_send = self.options["before_send"]
|
|
@@ -578,7 +558,7 @@ class _Client(BaseClient):
|
|
|
578
558
|
and event is not None
|
|
579
559
|
and event.get("type") != "transaction"
|
|
580
560
|
):
|
|
581
|
-
new_event
|
|
561
|
+
new_event: Optional["Event"] = None
|
|
582
562
|
with capture_internal_exceptions():
|
|
583
563
|
new_event = before_send(event, hint or {})
|
|
584
564
|
if new_event is None:
|
|
@@ -595,7 +575,7 @@ class _Client(BaseClient):
|
|
|
595
575
|
if event.get("exception"):
|
|
596
576
|
DedupeIntegration.reset_last_seen()
|
|
597
577
|
|
|
598
|
-
event = new_event
|
|
578
|
+
event = new_event
|
|
599
579
|
|
|
600
580
|
before_send_transaction = self.options["before_send_transaction"]
|
|
601
581
|
if (
|
|
@@ -604,7 +584,7 @@ class _Client(BaseClient):
|
|
|
604
584
|
and event.get("type") == "transaction"
|
|
605
585
|
):
|
|
606
586
|
new_event = None
|
|
607
|
-
spans_before = len(
|
|
587
|
+
spans_before = len(event.get("spans", []))
|
|
608
588
|
with capture_internal_exceptions():
|
|
609
589
|
new_event = before_send_transaction(event, hint or {})
|
|
610
590
|
if new_event is None:
|
|
@@ -619,20 +599,17 @@ class _Client(BaseClient):
|
|
|
619
599
|
quantity=spans_before + 1, # +1 for the transaction itself
|
|
620
600
|
)
|
|
621
601
|
else:
|
|
622
|
-
spans_delta = spans_before - len(
|
|
623
|
-
cast(List[Dict[str, object]], new_event.get("spans", []))
|
|
624
|
-
)
|
|
602
|
+
spans_delta = spans_before - len(new_event.get("spans", []))
|
|
625
603
|
if spans_delta > 0 and self.transport is not None:
|
|
626
604
|
self.transport.record_lost_event(
|
|
627
605
|
reason="before_send", data_category="span", quantity=spans_delta
|
|
628
606
|
)
|
|
629
607
|
|
|
630
|
-
event = new_event
|
|
608
|
+
event = new_event
|
|
631
609
|
|
|
632
610
|
return event
|
|
633
611
|
|
|
634
|
-
def _is_ignored_error(self, event, hint):
|
|
635
|
-
# type: (Event, Hint) -> bool
|
|
612
|
+
def _is_ignored_error(self, event: Event, hint: Hint) -> bool:
|
|
636
613
|
exc_info = hint.get("exc_info")
|
|
637
614
|
if exc_info is None:
|
|
638
615
|
return False
|
|
@@ -655,11 +632,10 @@ class _Client(BaseClient):
|
|
|
655
632
|
|
|
656
633
|
def _should_capture(
|
|
657
634
|
self,
|
|
658
|
-
event
|
|
659
|
-
hint
|
|
660
|
-
scope
|
|
661
|
-
):
|
|
662
|
-
# type: (...) -> bool
|
|
635
|
+
event: "Event",
|
|
636
|
+
hint: "Hint",
|
|
637
|
+
scope: Optional["Scope"] = None,
|
|
638
|
+
) -> bool:
|
|
663
639
|
# Transactions are sampled independent of error events.
|
|
664
640
|
is_transaction = event.get("type") == "transaction"
|
|
665
641
|
if is_transaction:
|
|
@@ -677,10 +653,9 @@ class _Client(BaseClient):
|
|
|
677
653
|
|
|
678
654
|
def _should_sample_error(
|
|
679
655
|
self,
|
|
680
|
-
event
|
|
681
|
-
hint
|
|
682
|
-
):
|
|
683
|
-
# type: (...) -> bool
|
|
656
|
+
event: Event,
|
|
657
|
+
hint: Hint,
|
|
658
|
+
) -> bool:
|
|
684
659
|
error_sampler = self.options.get("error_sampler", None)
|
|
685
660
|
|
|
686
661
|
if callable(error_sampler):
|
|
@@ -725,10 +700,9 @@ class _Client(BaseClient):
|
|
|
725
700
|
|
|
726
701
|
def _update_session_from_event(
|
|
727
702
|
self,
|
|
728
|
-
session
|
|
729
|
-
event
|
|
730
|
-
):
|
|
731
|
-
# type: (...) -> None
|
|
703
|
+
session: Session,
|
|
704
|
+
event: Event,
|
|
705
|
+
) -> None:
|
|
732
706
|
|
|
733
707
|
crashed = False
|
|
734
708
|
errored = False
|
|
@@ -764,11 +738,10 @@ class _Client(BaseClient):
|
|
|
764
738
|
|
|
765
739
|
def capture_event(
|
|
766
740
|
self,
|
|
767
|
-
event
|
|
768
|
-
hint
|
|
769
|
-
scope
|
|
770
|
-
):
|
|
771
|
-
# type: (...) -> Optional[str]
|
|
741
|
+
event: Event,
|
|
742
|
+
hint: Optional[Hint] = None,
|
|
743
|
+
scope: Optional[Scope] = None,
|
|
744
|
+
) -> Optional[str]:
|
|
772
745
|
"""Captures an event.
|
|
773
746
|
|
|
774
747
|
:param event: A ready-made event that can be directly sent to Sentry.
|
|
@@ -779,7 +752,7 @@ class _Client(BaseClient):
|
|
|
779
752
|
|
|
780
753
|
:returns: An event ID. May be `None` if there is no DSN set or of if the SDK decided to discard the event for other reasons. In such situations setting `debug=True` on `init()` may help.
|
|
781
754
|
"""
|
|
782
|
-
hint = dict(hint or ())
|
|
755
|
+
hint: Hint = dict(hint or ())
|
|
783
756
|
|
|
784
757
|
if not self._should_capture(event, hint, scope):
|
|
785
758
|
return None
|
|
@@ -814,10 +787,10 @@ class _Client(BaseClient):
|
|
|
814
787
|
trace_context = event_opt.get("contexts", {}).get("trace") or {}
|
|
815
788
|
dynamic_sampling_context = trace_context.pop("dynamic_sampling_context", {})
|
|
816
789
|
|
|
817
|
-
headers = {
|
|
790
|
+
headers: dict[str, object] = {
|
|
818
791
|
"event_id": event_opt["event_id"],
|
|
819
792
|
"sent_at": format_timestamp(datetime.now(timezone.utc)),
|
|
820
|
-
}
|
|
793
|
+
}
|
|
821
794
|
|
|
822
795
|
if dynamic_sampling_context:
|
|
823
796
|
headers["trace"] = dynamic_sampling_context
|
|
@@ -847,10 +820,8 @@ class _Client(BaseClient):
|
|
|
847
820
|
|
|
848
821
|
return return_value
|
|
849
822
|
|
|
850
|
-
def _capture_experimental_log(self, log):
|
|
851
|
-
|
|
852
|
-
logs_enabled = self.options["_experiments"].get("enable_logs", False)
|
|
853
|
-
if not logs_enabled:
|
|
823
|
+
def _capture_experimental_log(self, log: Optional[Log]) -> None:
|
|
824
|
+
if self.options.get("enable_logs") is not True or log is None:
|
|
854
825
|
return
|
|
855
826
|
|
|
856
827
|
current_scope = sentry_sdk.get_current_scope()
|
|
@@ -905,19 +876,17 @@ class _Client(BaseClient):
|
|
|
905
876
|
f'[Sentry Logs] [{log.get("severity_text")}] {log.get("body")}'
|
|
906
877
|
)
|
|
907
878
|
|
|
908
|
-
before_send_log = self.options
|
|
879
|
+
before_send_log = self.options.get("before_send_log")
|
|
909
880
|
if before_send_log is not None:
|
|
910
881
|
log = before_send_log(log, {})
|
|
882
|
+
|
|
911
883
|
if log is None:
|
|
912
884
|
return
|
|
913
885
|
|
|
914
886
|
if self.log_batcher:
|
|
915
887
|
self.log_batcher.add(log)
|
|
916
888
|
|
|
917
|
-
def capture_session(
|
|
918
|
-
self, session # type: Session
|
|
919
|
-
):
|
|
920
|
-
# type: (...) -> None
|
|
889
|
+
def capture_session(self, session: Session) -> None:
|
|
921
890
|
if not session.release:
|
|
922
891
|
logger.info("Discarded session update because of missing release")
|
|
923
892
|
else:
|
|
@@ -926,19 +895,16 @@ class _Client(BaseClient):
|
|
|
926
895
|
if TYPE_CHECKING:
|
|
927
896
|
|
|
928
897
|
@overload
|
|
929
|
-
def get_integration(self, name_or_class):
|
|
930
|
-
# type: (str) -> Optional[Integration]
|
|
931
|
-
...
|
|
898
|
+
def get_integration(self, name_or_class: str) -> Optional[Integration]: ...
|
|
932
899
|
|
|
933
900
|
@overload
|
|
934
|
-
def get_integration(
|
|
935
|
-
|
|
936
|
-
|
|
901
|
+
def get_integration(
|
|
902
|
+
self, name_or_class: type[IntegrationType]
|
|
903
|
+
) -> Optional[IntegrationType]: ...
|
|
937
904
|
|
|
938
905
|
def get_integration(
|
|
939
|
-
self, name_or_class
|
|
940
|
-
):
|
|
941
|
-
# type: (...) -> Optional[Integration]
|
|
906
|
+
self, name_or_class: Union[str, Type[Integration]]
|
|
907
|
+
) -> Optional[Integration]:
|
|
942
908
|
"""Returns the integration for this client by name or class.
|
|
943
909
|
If the client does not have that integration then `None` is returned.
|
|
944
910
|
"""
|
|
@@ -953,10 +919,9 @@ class _Client(BaseClient):
|
|
|
953
919
|
|
|
954
920
|
def close(
|
|
955
921
|
self,
|
|
956
|
-
timeout
|
|
957
|
-
callback
|
|
958
|
-
):
|
|
959
|
-
# type: (...) -> None
|
|
922
|
+
timeout: Optional[float] = None,
|
|
923
|
+
callback: Optional[Callable[[int, float], None]] = None,
|
|
924
|
+
) -> None:
|
|
960
925
|
"""
|
|
961
926
|
Close the client and shut down the transport. Arguments have the same
|
|
962
927
|
semantics as :py:meth:`Client.flush`.
|
|
@@ -977,10 +942,9 @@ class _Client(BaseClient):
|
|
|
977
942
|
|
|
978
943
|
def flush(
|
|
979
944
|
self,
|
|
980
|
-
timeout
|
|
981
|
-
callback
|
|
982
|
-
):
|
|
983
|
-
# type: (...) -> None
|
|
945
|
+
timeout: Optional[float] = None,
|
|
946
|
+
callback: Optional[Callable[[int, float], None]] = None,
|
|
947
|
+
) -> None:
|
|
984
948
|
"""
|
|
985
949
|
Wait for the current events to be sent.
|
|
986
950
|
|
|
@@ -998,17 +962,13 @@ class _Client(BaseClient):
|
|
|
998
962
|
|
|
999
963
|
self.transport.flush(timeout=timeout, callback=callback)
|
|
1000
964
|
|
|
1001
|
-
def __enter__(self):
|
|
1002
|
-
# type: () -> _Client
|
|
965
|
+
def __enter__(self) -> _Client:
|
|
1003
966
|
return self
|
|
1004
967
|
|
|
1005
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
1006
|
-
# type: (Any, Any, Any) -> None
|
|
968
|
+
def __exit__(self, exc_type: Any, exc_value: Any, tb: Any) -> None:
|
|
1007
969
|
self.close()
|
|
1008
970
|
|
|
1009
971
|
|
|
1010
|
-
from typing import TYPE_CHECKING
|
|
1011
|
-
|
|
1012
972
|
if TYPE_CHECKING:
|
|
1013
973
|
# Make mypy, PyCharm and other static analyzers think `get_options` is a
|
|
1014
974
|
# type to have nicer autocompletion for params.
|