sentry-sdk 3.0.0a2__py2.py3-none-any.whl → 3.0.0a3__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 +2 -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 +40 -28
- sentry_sdk/ai/utils.py +3 -4
- sentry_sdk/api.py +75 -87
- sentry_sdk/attachments.py +10 -12
- sentry_sdk/client.py +110 -153
- sentry_sdk/consts.py +398 -220
- 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 +32 -30
- sentry_sdk/integrations/anthropic.py +42 -37
- sentry_sdk/integrations/argv.py +3 -4
- sentry_sdk/integrations/ariadne.py +16 -18
- sentry_sdk/integrations/arq.py +19 -28
- sentry_sdk/integrations/asgi.py +63 -37
- sentry_sdk/integrations/asyncio.py +14 -16
- 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 +18 -16
- sentry_sdk/integrations/bottle.py +25 -34
- sentry_sdk/integrations/celery/__init__.py +36 -56
- 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 +21 -31
- sentry_sdk/integrations/cloud_resource_context.py +9 -16
- sentry_sdk/integrations/cohere.py +17 -23
- sentry_sdk/integrations/dedupe.py +5 -8
- sentry_sdk/integrations/django/__init__.py +57 -72
- sentry_sdk/integrations/django/asgi.py +24 -32
- sentry_sdk/integrations/django/caching.py +23 -19
- sentry_sdk/integrations/django/middleware.py +17 -20
- sentry_sdk/integrations/django/signals_handlers.py +11 -10
- sentry_sdk/integrations/django/templates.py +19 -16
- sentry_sdk/integrations/django/transactions.py +16 -11
- sentry_sdk/integrations/django/views.py +6 -10
- 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 +4 -6
- sentry_sdk/integrations/gql.py +16 -17
- sentry_sdk/integrations/graphene.py +13 -12
- sentry_sdk/integrations/grpc/__init__.py +3 -2
- sentry_sdk/integrations/grpc/aio/server.py +15 -14
- sentry_sdk/integrations/grpc/client.py +19 -9
- sentry_sdk/integrations/grpc/consts.py +2 -0
- sentry_sdk/integrations/grpc/server.py +12 -8
- sentry_sdk/integrations/httpx.py +9 -12
- sentry_sdk/integrations/huey.py +13 -20
- sentry_sdk/integrations/huggingface_hub.py +16 -16
- sentry_sdk/integrations/langchain.py +203 -113
- sentry_sdk/integrations/launchdarkly.py +13 -10
- sentry_sdk/integrations/litestar.py +37 -35
- sentry_sdk/integrations/logging.py +28 -35
- sentry_sdk/integrations/loguru.py +15 -19
- sentry_sdk/integrations/modules.py +3 -4
- sentry_sdk/integrations/openai.py +96 -84
- 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 +201 -0
- sentry_sdk/integrations/openfeature.py +11 -6
- sentry_sdk/integrations/pure_eval.py +6 -10
- sentry_sdk/integrations/pymongo.py +13 -17
- 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 +15 -9
- sentry_sdk/integrations/redis/_sync_common.py +13 -12
- 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 +9 -6
- sentry_sdk/integrations/sanic.py +34 -46
- sentry_sdk/integrations/serverless.py +22 -27
- sentry_sdk/integrations/socket.py +27 -15
- 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 +86 -90
- sentry_sdk/integrations/starlite.py +28 -34
- sentry_sdk/integrations/statsig.py +5 -4
- sentry_sdk/integrations/stdlib.py +28 -24
- sentry_sdk/integrations/strawberry.py +62 -49
- sentry_sdk/integrations/sys_exit.py +7 -11
- sentry_sdk/integrations/threading.py +12 -14
- 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 +36 -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 +40 -54
- sentry_sdk/session.py +44 -61
- sentry_sdk/sessions.py +35 -49
- sentry_sdk/spotlight.py +15 -21
- sentry_sdk/tracing.py +116 -182
- sentry_sdk/tracing_utils.py +100 -120
- sentry_sdk/transport.py +131 -157
- sentry_sdk/utils.py +232 -309
- sentry_sdk/worker.py +16 -28
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +1 -1
- sentry_sdk-3.0.0a3.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.0a3.dist-info}/WHEEL +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.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
|
|
@@ -48,13 +49,16 @@ from sentry_sdk.monitor import Monitor
|
|
|
48
49
|
from sentry_sdk.spotlight import setup_spotlight
|
|
49
50
|
|
|
50
51
|
if TYPE_CHECKING:
|
|
51
|
-
from typing import
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
from typing import (
|
|
53
|
+
Any,
|
|
54
|
+
Callable,
|
|
55
|
+
Optional,
|
|
56
|
+
Sequence,
|
|
57
|
+
Type,
|
|
58
|
+
Union,
|
|
59
|
+
TypeVar,
|
|
60
|
+
Dict,
|
|
61
|
+
)
|
|
58
62
|
|
|
59
63
|
from sentry_sdk._types import Event, Hint, SDKInfo, Log
|
|
60
64
|
from sentry_sdk.integrations import Integration
|
|
@@ -64,22 +68,22 @@ if TYPE_CHECKING:
|
|
|
64
68
|
from sentry_sdk.transport import Transport
|
|
65
69
|
from sentry_sdk._log_batcher import LogBatcher
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
IntegrationType = TypeVar("IntegrationType", bound=Integration) # noqa: E741
|
|
72
|
+
|
|
68
73
|
|
|
69
74
|
_client_init_debug = ContextVar("client_init_debug")
|
|
70
75
|
|
|
71
76
|
|
|
72
|
-
SDK_INFO = {
|
|
77
|
+
SDK_INFO: SDKInfo = {
|
|
73
78
|
"name": "sentry.python", # SDK name will be overridden after integrations have been loaded with sentry_sdk.integrations.setup_integrations()
|
|
74
79
|
"version": VERSION,
|
|
75
80
|
"packages": [{"name": "pypi:sentry-sdk", "version": VERSION}],
|
|
76
|
-
}
|
|
81
|
+
}
|
|
77
82
|
|
|
78
83
|
|
|
79
|
-
def _get_options(*args, **kwargs):
|
|
80
|
-
# type: (*Optional[str], **Any) -> Dict[str, Any]
|
|
84
|
+
def _get_options(*args: Optional[str], **kwargs: Any) -> Dict[str, Any]:
|
|
81
85
|
if args and (isinstance(args[0], (bytes, str)) or args[0] is None):
|
|
82
|
-
dsn = args[0]
|
|
86
|
+
dsn: Optional[str] = args[0]
|
|
83
87
|
args = args[1:]
|
|
84
88
|
else:
|
|
85
89
|
dsn = None
|
|
@@ -149,37 +153,31 @@ class BaseClient:
|
|
|
149
153
|
The basic definition of a client that is used for sending data to Sentry.
|
|
150
154
|
"""
|
|
151
155
|
|
|
152
|
-
spotlight
|
|
156
|
+
spotlight: Optional[SpotlightClient] = None
|
|
153
157
|
|
|
154
|
-
def __init__(self, options=None):
|
|
155
|
-
|
|
156
|
-
self.options = (
|
|
158
|
+
def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
|
|
159
|
+
self.options: Dict[str, Any] = (
|
|
157
160
|
options if options is not None else DEFAULT_OPTIONS
|
|
158
|
-
)
|
|
161
|
+
)
|
|
159
162
|
|
|
160
|
-
self.transport
|
|
161
|
-
self.monitor
|
|
162
|
-
self.log_batcher
|
|
163
|
+
self.transport: Optional[Transport] = None
|
|
164
|
+
self.monitor: Optional[Monitor] = None
|
|
165
|
+
self.log_batcher: Optional[LogBatcher] = None
|
|
163
166
|
|
|
164
|
-
def __getstate__(self, *args, **kwargs):
|
|
165
|
-
# type: (*Any, **Any) -> Any
|
|
167
|
+
def __getstate__(self, *args: Any, **kwargs: Any) -> Any:
|
|
166
168
|
return {"options": {}}
|
|
167
169
|
|
|
168
|
-
def __setstate__(self, *args, **kwargs):
|
|
169
|
-
# type: (*Any, **Any) -> None
|
|
170
|
+
def __setstate__(self, *args: Any, **kwargs: Any) -> None:
|
|
170
171
|
pass
|
|
171
172
|
|
|
172
173
|
@property
|
|
173
|
-
def dsn(self):
|
|
174
|
-
# type: () -> Optional[str]
|
|
174
|
+
def dsn(self) -> Optional[str]:
|
|
175
175
|
return None
|
|
176
176
|
|
|
177
|
-
def should_send_default_pii(self):
|
|
178
|
-
# type: () -> bool
|
|
177
|
+
def should_send_default_pii(self) -> bool:
|
|
179
178
|
return False
|
|
180
179
|
|
|
181
|
-
def is_active(self):
|
|
182
|
-
# type: () -> bool
|
|
180
|
+
def is_active(self) -> bool:
|
|
183
181
|
"""
|
|
184
182
|
.. versionadded:: 2.0.0
|
|
185
183
|
|
|
@@ -187,48 +185,40 @@ class BaseClient:
|
|
|
187
185
|
"""
|
|
188
186
|
return False
|
|
189
187
|
|
|
190
|
-
def capture_event(self, *args, **kwargs):
|
|
191
|
-
# type: (*Any, **Any) -> Optional[str]
|
|
188
|
+
def capture_event(self, *args: Any, **kwargs: Any) -> Optional[str]:
|
|
192
189
|
return None
|
|
193
190
|
|
|
194
|
-
def _capture_experimental_log(self, log):
|
|
195
|
-
# type: (Log) -> None
|
|
191
|
+
def _capture_experimental_log(self, log: "Log") -> None:
|
|
196
192
|
pass
|
|
197
193
|
|
|
198
|
-
def capture_session(self, *args, **kwargs):
|
|
199
|
-
# type: (*Any, **Any) -> None
|
|
194
|
+
def capture_session(self, *args: Any, **kwargs: Any) -> None:
|
|
200
195
|
return None
|
|
201
196
|
|
|
202
197
|
if TYPE_CHECKING:
|
|
203
198
|
|
|
204
199
|
@overload
|
|
205
|
-
def get_integration(self, name_or_class):
|
|
206
|
-
# type: (str) -> Optional[Integration]
|
|
207
|
-
...
|
|
200
|
+
def get_integration(self, name_or_class: str) -> Optional[Integration]: ...
|
|
208
201
|
|
|
209
202
|
@overload
|
|
210
|
-
def get_integration(
|
|
211
|
-
|
|
212
|
-
|
|
203
|
+
def get_integration(
|
|
204
|
+
self, name_or_class: type[IntegrationType]
|
|
205
|
+
) -> Optional[IntegrationType]: ...
|
|
213
206
|
|
|
214
|
-
def get_integration(
|
|
215
|
-
|
|
207
|
+
def get_integration(
|
|
208
|
+
self, name_or_class: Union[str, type[Integration]]
|
|
209
|
+
) -> Optional[Integration]:
|
|
216
210
|
return None
|
|
217
211
|
|
|
218
|
-
def close(self, *args, **kwargs):
|
|
219
|
-
# type: (*Any, **Any) -> None
|
|
212
|
+
def close(self, *args: Any, **kwargs: Any) -> None:
|
|
220
213
|
return None
|
|
221
214
|
|
|
222
|
-
def flush(self, *args, **kwargs):
|
|
223
|
-
# type: (*Any, **Any) -> None
|
|
215
|
+
def flush(self, *args: Any, **kwargs: Any) -> None:
|
|
224
216
|
return None
|
|
225
217
|
|
|
226
|
-
def __enter__(self):
|
|
227
|
-
# type: () -> BaseClient
|
|
218
|
+
def __enter__(self) -> BaseClient:
|
|
228
219
|
return self
|
|
229
220
|
|
|
230
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
231
|
-
# type: (Any, Any, Any) -> None
|
|
221
|
+
def __exit__(self, exc_type: Any, exc_value: Any, tb: Any) -> None:
|
|
232
222
|
return None
|
|
233
223
|
|
|
234
224
|
|
|
@@ -252,22 +242,20 @@ class _Client(BaseClient):
|
|
|
252
242
|
Alias of :py:class:`sentry_sdk.Client`. (Was created for better intelisense support)
|
|
253
243
|
"""
|
|
254
244
|
|
|
255
|
-
def __init__(self, *args, **kwargs):
|
|
256
|
-
|
|
257
|
-
super(_Client, self).__init__(options=get_options(*args, **kwargs))
|
|
245
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
246
|
+
super(_Client, self).__init__(options=_get_options(*args, **kwargs))
|
|
258
247
|
self._init_impl()
|
|
259
248
|
|
|
260
|
-
def __getstate__(self):
|
|
261
|
-
# type: () -> Any
|
|
249
|
+
def __getstate__(self) -> Any:
|
|
262
250
|
return {"options": self.options}
|
|
263
251
|
|
|
264
|
-
def __setstate__(self, state):
|
|
265
|
-
# type: (Any) -> None
|
|
252
|
+
def __setstate__(self, state: Any) -> None:
|
|
266
253
|
self.options = state["options"]
|
|
267
254
|
self._init_impl()
|
|
268
255
|
|
|
269
|
-
def _setup_instrumentation(
|
|
270
|
-
|
|
256
|
+
def _setup_instrumentation(
|
|
257
|
+
self, functions_to_trace: Sequence[Dict[str, str]]
|
|
258
|
+
) -> None:
|
|
271
259
|
"""
|
|
272
260
|
Instruments the functions given in the list `functions_to_trace` with the `@sentry_sdk.tracing.trace` decorator.
|
|
273
261
|
"""
|
|
@@ -317,12 +305,10 @@ class _Client(BaseClient):
|
|
|
317
305
|
e,
|
|
318
306
|
)
|
|
319
307
|
|
|
320
|
-
def _init_impl(self):
|
|
321
|
-
# type: () -> None
|
|
308
|
+
def _init_impl(self) -> None:
|
|
322
309
|
old_debug = _client_init_debug.get(False)
|
|
323
310
|
|
|
324
|
-
def _capture_envelope(envelope):
|
|
325
|
-
# type: (Envelope) -> None
|
|
311
|
+
def _capture_envelope(envelope: Envelope) -> None:
|
|
326
312
|
if self.transport is not None:
|
|
327
313
|
self.transport.capture_envelope(envelope)
|
|
328
314
|
|
|
@@ -423,8 +409,7 @@ class _Client(BaseClient):
|
|
|
423
409
|
# need to check if it's safe to use them.
|
|
424
410
|
check_uwsgi_thread_support()
|
|
425
411
|
|
|
426
|
-
def is_active(self):
|
|
427
|
-
# type: () -> bool
|
|
412
|
+
def is_active(self) -> bool:
|
|
428
413
|
"""
|
|
429
414
|
.. versionadded:: 2.0.0
|
|
430
415
|
|
|
@@ -432,8 +417,7 @@ class _Client(BaseClient):
|
|
|
432
417
|
"""
|
|
433
418
|
return True
|
|
434
419
|
|
|
435
|
-
def should_send_default_pii(self):
|
|
436
|
-
# type: () -> bool
|
|
420
|
+
def should_send_default_pii(self) -> bool:
|
|
437
421
|
"""
|
|
438
422
|
.. versionadded:: 2.0.0
|
|
439
423
|
|
|
@@ -442,28 +426,26 @@ class _Client(BaseClient):
|
|
|
442
426
|
return self.options.get("send_default_pii") or False
|
|
443
427
|
|
|
444
428
|
@property
|
|
445
|
-
def dsn(self):
|
|
446
|
-
# type: () -> Optional[str]
|
|
429
|
+
def dsn(self) -> Optional[str]:
|
|
447
430
|
"""Returns the configured DSN as string."""
|
|
448
431
|
return self.options["dsn"]
|
|
449
432
|
|
|
450
433
|
def _prepare_event(
|
|
451
434
|
self,
|
|
452
|
-
event
|
|
453
|
-
hint
|
|
454
|
-
scope
|
|
455
|
-
):
|
|
456
|
-
# type: (...) -> Optional[Event]
|
|
435
|
+
event: Event,
|
|
436
|
+
hint: Hint,
|
|
437
|
+
scope: Optional[Scope],
|
|
438
|
+
) -> Optional[Event]:
|
|
457
439
|
|
|
458
|
-
previous_total_spans
|
|
459
|
-
previous_total_breadcrumbs
|
|
440
|
+
previous_total_spans: Optional[int] = None
|
|
441
|
+
previous_total_breadcrumbs: Optional[int] = None
|
|
460
442
|
|
|
461
443
|
if event.get("timestamp") is None:
|
|
462
444
|
event["timestamp"] = datetime.now(timezone.utc)
|
|
463
445
|
|
|
464
446
|
if scope is not None:
|
|
465
447
|
is_transaction = event.get("type") == "transaction"
|
|
466
|
-
spans_before = len(
|
|
448
|
+
spans_before = len(event.get("spans", []))
|
|
467
449
|
event_ = scope.apply_to_event(event, hint, self.options)
|
|
468
450
|
|
|
469
451
|
# one of the event/error processors returned None
|
|
@@ -481,16 +463,14 @@ class _Client(BaseClient):
|
|
|
481
463
|
)
|
|
482
464
|
return None
|
|
483
465
|
|
|
484
|
-
event = event_
|
|
485
|
-
spans_delta = spans_before - len(
|
|
486
|
-
cast(List[Dict[str, object]], event.get("spans", []))
|
|
487
|
-
)
|
|
466
|
+
event = event_
|
|
467
|
+
spans_delta = spans_before - len(event.get("spans", []))
|
|
488
468
|
if is_transaction and spans_delta > 0 and self.transport is not None:
|
|
489
469
|
self.transport.record_lost_event(
|
|
490
470
|
"event_processor", data_category="span", quantity=spans_delta
|
|
491
471
|
)
|
|
492
472
|
|
|
493
|
-
dropped_spans = event.pop("_dropped_spans", 0) + spans_delta
|
|
473
|
+
dropped_spans: int = event.pop("_dropped_spans", 0) + spans_delta
|
|
494
474
|
if dropped_spans > 0:
|
|
495
475
|
previous_total_spans = spans_before + dropped_spans
|
|
496
476
|
if scope._n_breadcrumbs_truncated > 0:
|
|
@@ -562,14 +542,11 @@ class _Client(BaseClient):
|
|
|
562
542
|
# Postprocess the event here so that annotated types do
|
|
563
543
|
# generally not surface in before_send
|
|
564
544
|
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
|
-
),
|
|
545
|
+
event: Event = serialize( # type: ignore[no-redef]
|
|
546
|
+
event,
|
|
547
|
+
max_request_body_size=self.options.get("max_request_body_size"),
|
|
548
|
+
max_value_length=self.options.get("max_value_length"),
|
|
549
|
+
custom_repr=self.options.get("custom_repr"),
|
|
573
550
|
)
|
|
574
551
|
|
|
575
552
|
before_send = self.options["before_send"]
|
|
@@ -578,7 +555,7 @@ class _Client(BaseClient):
|
|
|
578
555
|
and event is not None
|
|
579
556
|
and event.get("type") != "transaction"
|
|
580
557
|
):
|
|
581
|
-
new_event
|
|
558
|
+
new_event: Optional["Event"] = None
|
|
582
559
|
with capture_internal_exceptions():
|
|
583
560
|
new_event = before_send(event, hint or {})
|
|
584
561
|
if new_event is None:
|
|
@@ -595,7 +572,7 @@ class _Client(BaseClient):
|
|
|
595
572
|
if event.get("exception"):
|
|
596
573
|
DedupeIntegration.reset_last_seen()
|
|
597
574
|
|
|
598
|
-
event = new_event
|
|
575
|
+
event = new_event
|
|
599
576
|
|
|
600
577
|
before_send_transaction = self.options["before_send_transaction"]
|
|
601
578
|
if (
|
|
@@ -604,7 +581,7 @@ class _Client(BaseClient):
|
|
|
604
581
|
and event.get("type") == "transaction"
|
|
605
582
|
):
|
|
606
583
|
new_event = None
|
|
607
|
-
spans_before = len(
|
|
584
|
+
spans_before = len(event.get("spans", []))
|
|
608
585
|
with capture_internal_exceptions():
|
|
609
586
|
new_event = before_send_transaction(event, hint or {})
|
|
610
587
|
if new_event is None:
|
|
@@ -619,20 +596,17 @@ class _Client(BaseClient):
|
|
|
619
596
|
quantity=spans_before + 1, # +1 for the transaction itself
|
|
620
597
|
)
|
|
621
598
|
else:
|
|
622
|
-
spans_delta = spans_before - len(
|
|
623
|
-
cast(List[Dict[str, object]], new_event.get("spans", []))
|
|
624
|
-
)
|
|
599
|
+
spans_delta = spans_before - len(new_event.get("spans", []))
|
|
625
600
|
if spans_delta > 0 and self.transport is not None:
|
|
626
601
|
self.transport.record_lost_event(
|
|
627
602
|
reason="before_send", data_category="span", quantity=spans_delta
|
|
628
603
|
)
|
|
629
604
|
|
|
630
|
-
event = new_event
|
|
605
|
+
event = new_event
|
|
631
606
|
|
|
632
607
|
return event
|
|
633
608
|
|
|
634
|
-
def _is_ignored_error(self, event, hint):
|
|
635
|
-
# type: (Event, Hint) -> bool
|
|
609
|
+
def _is_ignored_error(self, event: Event, hint: Hint) -> bool:
|
|
636
610
|
exc_info = hint.get("exc_info")
|
|
637
611
|
if exc_info is None:
|
|
638
612
|
return False
|
|
@@ -655,11 +629,10 @@ class _Client(BaseClient):
|
|
|
655
629
|
|
|
656
630
|
def _should_capture(
|
|
657
631
|
self,
|
|
658
|
-
event
|
|
659
|
-
hint
|
|
660
|
-
scope
|
|
661
|
-
):
|
|
662
|
-
# type: (...) -> bool
|
|
632
|
+
event: "Event",
|
|
633
|
+
hint: "Hint",
|
|
634
|
+
scope: Optional["Scope"] = None,
|
|
635
|
+
) -> bool:
|
|
663
636
|
# Transactions are sampled independent of error events.
|
|
664
637
|
is_transaction = event.get("type") == "transaction"
|
|
665
638
|
if is_transaction:
|
|
@@ -677,10 +650,9 @@ class _Client(BaseClient):
|
|
|
677
650
|
|
|
678
651
|
def _should_sample_error(
|
|
679
652
|
self,
|
|
680
|
-
event
|
|
681
|
-
hint
|
|
682
|
-
):
|
|
683
|
-
# type: (...) -> bool
|
|
653
|
+
event: Event,
|
|
654
|
+
hint: Hint,
|
|
655
|
+
) -> bool:
|
|
684
656
|
error_sampler = self.options.get("error_sampler", None)
|
|
685
657
|
|
|
686
658
|
if callable(error_sampler):
|
|
@@ -725,10 +697,9 @@ class _Client(BaseClient):
|
|
|
725
697
|
|
|
726
698
|
def _update_session_from_event(
|
|
727
699
|
self,
|
|
728
|
-
session
|
|
729
|
-
event
|
|
730
|
-
):
|
|
731
|
-
# type: (...) -> None
|
|
700
|
+
session: Session,
|
|
701
|
+
event: Event,
|
|
702
|
+
) -> None:
|
|
732
703
|
|
|
733
704
|
crashed = False
|
|
734
705
|
errored = False
|
|
@@ -764,11 +735,10 @@ class _Client(BaseClient):
|
|
|
764
735
|
|
|
765
736
|
def capture_event(
|
|
766
737
|
self,
|
|
767
|
-
event
|
|
768
|
-
hint
|
|
769
|
-
scope
|
|
770
|
-
):
|
|
771
|
-
# type: (...) -> Optional[str]
|
|
738
|
+
event: Event,
|
|
739
|
+
hint: Optional[Hint] = None,
|
|
740
|
+
scope: Optional[Scope] = None,
|
|
741
|
+
) -> Optional[str]:
|
|
772
742
|
"""Captures an event.
|
|
773
743
|
|
|
774
744
|
:param event: A ready-made event that can be directly sent to Sentry.
|
|
@@ -779,7 +749,7 @@ class _Client(BaseClient):
|
|
|
779
749
|
|
|
780
750
|
: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
751
|
"""
|
|
782
|
-
hint = dict(hint or ())
|
|
752
|
+
hint: Hint = dict(hint or ())
|
|
783
753
|
|
|
784
754
|
if not self._should_capture(event, hint, scope):
|
|
785
755
|
return None
|
|
@@ -814,10 +784,10 @@ class _Client(BaseClient):
|
|
|
814
784
|
trace_context = event_opt.get("contexts", {}).get("trace") or {}
|
|
815
785
|
dynamic_sampling_context = trace_context.pop("dynamic_sampling_context", {})
|
|
816
786
|
|
|
817
|
-
headers = {
|
|
787
|
+
headers: dict[str, object] = {
|
|
818
788
|
"event_id": event_opt["event_id"],
|
|
819
789
|
"sent_at": format_timestamp(datetime.now(timezone.utc)),
|
|
820
|
-
}
|
|
790
|
+
}
|
|
821
791
|
|
|
822
792
|
if dynamic_sampling_context:
|
|
823
793
|
headers["trace"] = dynamic_sampling_context
|
|
@@ -847,8 +817,7 @@ class _Client(BaseClient):
|
|
|
847
817
|
|
|
848
818
|
return return_value
|
|
849
819
|
|
|
850
|
-
def _capture_experimental_log(self, log):
|
|
851
|
-
# type: (Log) -> None
|
|
820
|
+
def _capture_experimental_log(self, log: Log) -> None:
|
|
852
821
|
logs_enabled = self.options["_experiments"].get("enable_logs", False)
|
|
853
822
|
if not logs_enabled:
|
|
854
823
|
return
|
|
@@ -914,10 +883,7 @@ class _Client(BaseClient):
|
|
|
914
883
|
if self.log_batcher:
|
|
915
884
|
self.log_batcher.add(log)
|
|
916
885
|
|
|
917
|
-
def capture_session(
|
|
918
|
-
self, session # type: Session
|
|
919
|
-
):
|
|
920
|
-
# type: (...) -> None
|
|
886
|
+
def capture_session(self, session: Session) -> None:
|
|
921
887
|
if not session.release:
|
|
922
888
|
logger.info("Discarded session update because of missing release")
|
|
923
889
|
else:
|
|
@@ -926,19 +892,16 @@ class _Client(BaseClient):
|
|
|
926
892
|
if TYPE_CHECKING:
|
|
927
893
|
|
|
928
894
|
@overload
|
|
929
|
-
def get_integration(self, name_or_class):
|
|
930
|
-
# type: (str) -> Optional[Integration]
|
|
931
|
-
...
|
|
895
|
+
def get_integration(self, name_or_class: str) -> Optional[Integration]: ...
|
|
932
896
|
|
|
933
897
|
@overload
|
|
934
|
-
def get_integration(
|
|
935
|
-
|
|
936
|
-
|
|
898
|
+
def get_integration(
|
|
899
|
+
self, name_or_class: type[IntegrationType]
|
|
900
|
+
) -> Optional[IntegrationType]: ...
|
|
937
901
|
|
|
938
902
|
def get_integration(
|
|
939
|
-
self, name_or_class
|
|
940
|
-
):
|
|
941
|
-
# type: (...) -> Optional[Integration]
|
|
903
|
+
self, name_or_class: Union[str, Type[Integration]]
|
|
904
|
+
) -> Optional[Integration]:
|
|
942
905
|
"""Returns the integration for this client by name or class.
|
|
943
906
|
If the client does not have that integration then `None` is returned.
|
|
944
907
|
"""
|
|
@@ -953,10 +916,9 @@ class _Client(BaseClient):
|
|
|
953
916
|
|
|
954
917
|
def close(
|
|
955
918
|
self,
|
|
956
|
-
timeout
|
|
957
|
-
callback
|
|
958
|
-
):
|
|
959
|
-
# type: (...) -> None
|
|
919
|
+
timeout: Optional[float] = None,
|
|
920
|
+
callback: Optional[Callable[[int, float], None]] = None,
|
|
921
|
+
) -> None:
|
|
960
922
|
"""
|
|
961
923
|
Close the client and shut down the transport. Arguments have the same
|
|
962
924
|
semantics as :py:meth:`Client.flush`.
|
|
@@ -977,10 +939,9 @@ class _Client(BaseClient):
|
|
|
977
939
|
|
|
978
940
|
def flush(
|
|
979
941
|
self,
|
|
980
|
-
timeout
|
|
981
|
-
callback
|
|
982
|
-
):
|
|
983
|
-
# type: (...) -> None
|
|
942
|
+
timeout: Optional[float] = None,
|
|
943
|
+
callback: Optional[Callable[[int, float], None]] = None,
|
|
944
|
+
) -> None:
|
|
984
945
|
"""
|
|
985
946
|
Wait for the current events to be sent.
|
|
986
947
|
|
|
@@ -998,17 +959,13 @@ class _Client(BaseClient):
|
|
|
998
959
|
|
|
999
960
|
self.transport.flush(timeout=timeout, callback=callback)
|
|
1000
961
|
|
|
1001
|
-
def __enter__(self):
|
|
1002
|
-
# type: () -> _Client
|
|
962
|
+
def __enter__(self) -> _Client:
|
|
1003
963
|
return self
|
|
1004
964
|
|
|
1005
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
1006
|
-
# type: (Any, Any, Any) -> None
|
|
965
|
+
def __exit__(self, exc_type: Any, exc_value: Any, tb: Any) -> None:
|
|
1007
966
|
self.close()
|
|
1008
967
|
|
|
1009
968
|
|
|
1010
|
-
from typing import TYPE_CHECKING
|
|
1011
|
-
|
|
1012
969
|
if TYPE_CHECKING:
|
|
1013
970
|
# Make mypy, PyCharm and other static analyzers think `get_options` is a
|
|
1014
971
|
# type to have nicer autocompletion for params.
|