sentry-sdk 3.0.0a1__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 +11 -18
- sentry_sdk/_werkzeug.py +5 -7
- sentry_sdk/ai/monitoring.py +44 -31
- sentry_sdk/ai/utils.py +3 -4
- sentry_sdk/api.py +75 -87
- sentry_sdk/attachments.py +10 -12
- sentry_sdk/client.py +137 -155
- sentry_sdk/consts.py +430 -174
- 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 +15 -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 +21 -29
- 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 +41 -61
- sentry_sdk/integrations/celery/beat.py +23 -27
- 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 +27 -33
- sentry_sdk/integrations/dedupe.py +5 -8
- sentry_sdk/integrations/django/__init__.py +57 -72
- sentry_sdk/integrations/django/asgi.py +26 -34
- 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 +19 -1
- 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 +18 -18
- 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 +52 -65
- sentry_sdk/integrations/loguru.py +127 -57
- sentry_sdk/integrations/modules.py +3 -4
- sentry_sdk/integrations/openai.py +100 -88
- 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 +25 -12
- sentry_sdk/integrations/redis/_sync_common.py +19 -13
- 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 +21 -13
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
- sentry_sdk/integrations/redis/utils.py +23 -24
- 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 +41 -10
- sentry_sdk/monitor.py +16 -28
- sentry_sdk/opentelemetry/consts.py +11 -4
- sentry_sdk/opentelemetry/contextvars_context.py +26 -16
- 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 +48 -58
- sentry_sdk/opentelemetry/tracing.py +58 -14
- sentry_sdk/opentelemetry/utils.py +186 -194
- 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 -273
- 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 +121 -187
- sentry_sdk/tracing_utils.py +104 -122
- sentry_sdk/transport.py +131 -157
- sentry_sdk/utils.py +232 -309
- sentry_sdk/worker.py +16 -28
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +3 -3
- sentry_sdk-3.0.0a3.dist-info/RECORD +168 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/WHEEL +1 -1
- sentry_sdk-3.0.0a1.dist-info/RECORD +0 -154
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/top_level.txt +0 -0
sentry_sdk/integrations/beam.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sys
|
|
2
3
|
import types
|
|
3
4
|
from functools import wraps
|
|
@@ -35,8 +36,7 @@ class BeamIntegration(Integration):
|
|
|
35
36
|
identifier = "beam"
|
|
36
37
|
|
|
37
38
|
@staticmethod
|
|
38
|
-
def setup_once():
|
|
39
|
-
# type: () -> None
|
|
39
|
+
def setup_once() -> None:
|
|
40
40
|
from apache_beam.transforms.core import DoFn, ParDo # type: ignore
|
|
41
41
|
|
|
42
42
|
ignore_logger("root")
|
|
@@ -52,8 +52,7 @@ class BeamIntegration(Integration):
|
|
|
52
52
|
|
|
53
53
|
old_init = ParDo.__init__
|
|
54
54
|
|
|
55
|
-
def sentry_init_pardo(self, fn, *args, **kwargs):
|
|
56
|
-
# type: (ParDo, Any, *Any, **Any) -> Any
|
|
55
|
+
def sentry_init_pardo(self: ParDo, fn: Any, *args: Any, **kwargs: Any) -> Any:
|
|
57
56
|
# Do not monkey patch init twice
|
|
58
57
|
if not getattr(self, "_sentry_is_patched", False):
|
|
59
58
|
for func_name in function_patches:
|
|
@@ -79,14 +78,12 @@ class BeamIntegration(Integration):
|
|
|
79
78
|
ParDo.__init__ = sentry_init_pardo
|
|
80
79
|
|
|
81
80
|
|
|
82
|
-
def _wrap_inspect_call(cls, func_name):
|
|
83
|
-
# type: (Any, Any) -> Any
|
|
81
|
+
def _wrap_inspect_call(cls: Any, func_name: Any) -> Any:
|
|
84
82
|
|
|
85
83
|
if not hasattr(cls, func_name):
|
|
86
84
|
return None
|
|
87
85
|
|
|
88
|
-
def _inspect(self):
|
|
89
|
-
# type: (Any) -> Any
|
|
86
|
+
def _inspect(self: Any) -> Any:
|
|
90
87
|
"""
|
|
91
88
|
Inspect function overrides the way Beam gets argspec.
|
|
92
89
|
"""
|
|
@@ -113,15 +110,13 @@ def _wrap_inspect_call(cls, func_name):
|
|
|
113
110
|
return _inspect
|
|
114
111
|
|
|
115
112
|
|
|
116
|
-
def _wrap_task_call(func):
|
|
117
|
-
# type: (F) -> F
|
|
113
|
+
def _wrap_task_call(func: F) -> F:
|
|
118
114
|
"""
|
|
119
115
|
Wrap task call with a try catch to get exceptions.
|
|
120
116
|
"""
|
|
121
117
|
|
|
122
118
|
@wraps(func)
|
|
123
|
-
def _inner(*args, **kwargs):
|
|
124
|
-
# type: (*Any, **Any) -> Any
|
|
119
|
+
def _inner(*args: Any, **kwargs: Any) -> Any:
|
|
125
120
|
try:
|
|
126
121
|
gen = func(*args, **kwargs)
|
|
127
122
|
except Exception:
|
|
@@ -136,8 +131,7 @@ def _wrap_task_call(func):
|
|
|
136
131
|
|
|
137
132
|
|
|
138
133
|
@ensure_integration_enabled(BeamIntegration)
|
|
139
|
-
def _capture_exception(exc_info):
|
|
140
|
-
# type: (ExcInfo) -> None
|
|
134
|
+
def _capture_exception(exc_info: ExcInfo) -> None:
|
|
141
135
|
"""
|
|
142
136
|
Send Beam exception to Sentry.
|
|
143
137
|
"""
|
|
@@ -151,8 +145,7 @@ def _capture_exception(exc_info):
|
|
|
151
145
|
sentry_sdk.capture_event(event, hint=hint)
|
|
152
146
|
|
|
153
147
|
|
|
154
|
-
def raise_exception():
|
|
155
|
-
# type: () -> None
|
|
148
|
+
def raise_exception() -> None:
|
|
156
149
|
"""
|
|
157
150
|
Raise an exception.
|
|
158
151
|
"""
|
|
@@ -162,8 +155,7 @@ def raise_exception():
|
|
|
162
155
|
reraise(*exc_info)
|
|
163
156
|
|
|
164
157
|
|
|
165
|
-
def _wrap_generator_call(gen):
|
|
166
|
-
# type: (Iterator[T]) -> Iterator[T]
|
|
158
|
+
def _wrap_generator_call(gen: Iterator[T]) -> Iterator[T]:
|
|
167
159
|
"""
|
|
168
160
|
Wrap the generator to handle any failures.
|
|
169
161
|
"""
|
sentry_sdk/integrations/boto3.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from functools import partial
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -34,15 +35,15 @@ class Boto3Integration(Integration):
|
|
|
34
35
|
origin = f"auto.http.{identifier}"
|
|
35
36
|
|
|
36
37
|
@staticmethod
|
|
37
|
-
def setup_once():
|
|
38
|
-
# type: () -> None
|
|
38
|
+
def setup_once() -> None:
|
|
39
39
|
version = parse_version(BOTOCORE_VERSION)
|
|
40
40
|
_check_minimum_version(Boto3Integration, version, "botocore")
|
|
41
41
|
|
|
42
42
|
orig_init = BaseClient.__init__
|
|
43
43
|
|
|
44
|
-
def sentry_patched_init(
|
|
45
|
-
|
|
44
|
+
def sentry_patched_init(
|
|
45
|
+
self: Type[BaseClient], *args: Any, **kwargs: Any
|
|
46
|
+
) -> None:
|
|
46
47
|
orig_init(self, *args, **kwargs)
|
|
47
48
|
meta = self.meta
|
|
48
49
|
service_id = meta.service_model.service_id.hyphenize()
|
|
@@ -57,8 +58,9 @@ class Boto3Integration(Integration):
|
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
@ensure_integration_enabled(Boto3Integration)
|
|
60
|
-
def _sentry_request_created(
|
|
61
|
-
|
|
61
|
+
def _sentry_request_created(
|
|
62
|
+
service_id: str, request: AWSRequest, operation_name: str, **kwargs: Any
|
|
63
|
+
) -> None:
|
|
62
64
|
description = "aws.%s.%s" % (service_id, operation_name)
|
|
63
65
|
span = sentry_sdk.start_span(
|
|
64
66
|
op=OP.HTTP_CLIENT,
|
|
@@ -92,9 +94,10 @@ def _sentry_request_created(service_id, request, operation_name, **kwargs):
|
|
|
92
94
|
request.context["_sentrysdk_span_data"] = data
|
|
93
95
|
|
|
94
96
|
|
|
95
|
-
def _sentry_after_call(
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
def _sentry_after_call(
|
|
98
|
+
context: Dict[str, Any], parsed: Dict[str, Any], **kwargs: Any
|
|
99
|
+
) -> None:
|
|
100
|
+
span: Optional[Span] = context.pop("_sentrysdk_span", None)
|
|
98
101
|
|
|
99
102
|
# Span could be absent if the integration is disabled.
|
|
100
103
|
if span is None:
|
|
@@ -122,8 +125,7 @@ def _sentry_after_call(context, parsed, **kwargs):
|
|
|
122
125
|
|
|
123
126
|
orig_read = body.read
|
|
124
127
|
|
|
125
|
-
def sentry_streaming_body_read(*args, **kwargs):
|
|
126
|
-
# type: (*Any, **Any) -> bytes
|
|
128
|
+
def sentry_streaming_body_read(*args: Any, **kwargs: Any) -> bytes:
|
|
127
129
|
try:
|
|
128
130
|
ret = orig_read(*args, **kwargs)
|
|
129
131
|
if not ret:
|
|
@@ -137,8 +139,7 @@ def _sentry_after_call(context, parsed, **kwargs):
|
|
|
137
139
|
|
|
138
140
|
orig_close = body.close
|
|
139
141
|
|
|
140
|
-
def sentry_streaming_body_close(*args, **kwargs):
|
|
141
|
-
# type: (*Any, **Any) -> None
|
|
142
|
+
def sentry_streaming_body_close(*args: Any, **kwargs: Any) -> None:
|
|
142
143
|
streaming_span.finish()
|
|
143
144
|
orig_close(*args, **kwargs)
|
|
144
145
|
|
|
@@ -147,9 +148,10 @@ def _sentry_after_call(context, parsed, **kwargs):
|
|
|
147
148
|
span.__exit__(None, None, None)
|
|
148
149
|
|
|
149
150
|
|
|
150
|
-
def _sentry_after_call_error(
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
def _sentry_after_call_error(
|
|
152
|
+
context: Dict[str, Any], exception: Type[BaseException], **kwargs: Any
|
|
153
|
+
) -> None:
|
|
154
|
+
span: Optional[Span] = context.pop("_sentrysdk_span", None)
|
|
153
155
|
|
|
154
156
|
# Span could be absent if the integration is disabled.
|
|
155
157
|
if span is None:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import functools
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -55,11 +56,10 @@ class BottleIntegration(Integration):
|
|
|
55
56
|
|
|
56
57
|
def __init__(
|
|
57
58
|
self,
|
|
58
|
-
transaction_style="endpoint",
|
|
59
|
+
transaction_style: str = "endpoint",
|
|
59
60
|
*,
|
|
60
|
-
failed_request_status_codes
|
|
61
|
-
):
|
|
62
|
-
# type: (...) -> None
|
|
61
|
+
failed_request_status_codes: Set[int] = _DEFAULT_FAILED_REQUEST_STATUS_CODES,
|
|
62
|
+
) -> None:
|
|
63
63
|
|
|
64
64
|
if transaction_style not in TRANSACTION_STYLE_VALUES:
|
|
65
65
|
raise ValueError(
|
|
@@ -70,16 +70,16 @@ class BottleIntegration(Integration):
|
|
|
70
70
|
self.failed_request_status_codes = failed_request_status_codes
|
|
71
71
|
|
|
72
72
|
@staticmethod
|
|
73
|
-
def setup_once():
|
|
74
|
-
# type: () -> None
|
|
73
|
+
def setup_once() -> None:
|
|
75
74
|
version = parse_version(BOTTLE_VERSION)
|
|
76
75
|
_check_minimum_version(BottleIntegration, version)
|
|
77
76
|
|
|
78
77
|
old_app = Bottle.__call__
|
|
79
78
|
|
|
80
79
|
@ensure_integration_enabled(BottleIntegration, old_app)
|
|
81
|
-
def sentry_patched_wsgi_app(
|
|
82
|
-
|
|
80
|
+
def sentry_patched_wsgi_app(
|
|
81
|
+
self: Any, environ: Dict[str, str], start_response: Callable[..., Any]
|
|
82
|
+
) -> _ScopedResponse:
|
|
83
83
|
middleware = SentryWsgiMiddleware(
|
|
84
84
|
lambda *a, **kw: old_app(self, *a, **kw),
|
|
85
85
|
span_origin=BottleIntegration.origin,
|
|
@@ -92,8 +92,7 @@ class BottleIntegration(Integration):
|
|
|
92
92
|
old_handle = Bottle._handle
|
|
93
93
|
|
|
94
94
|
@functools.wraps(old_handle)
|
|
95
|
-
def _patched_handle(self, environ):
|
|
96
|
-
# type: (Bottle, Dict[str, Any]) -> Any
|
|
95
|
+
def _patched_handle(self: Bottle, environ: Dict[str, Any]) -> Any:
|
|
97
96
|
integration = sentry_sdk.get_client().get_integration(BottleIntegration)
|
|
98
97
|
if integration is None:
|
|
99
98
|
return old_handle(self, environ)
|
|
@@ -112,16 +111,14 @@ class BottleIntegration(Integration):
|
|
|
112
111
|
old_make_callback = Route._make_callback
|
|
113
112
|
|
|
114
113
|
@functools.wraps(old_make_callback)
|
|
115
|
-
def patched_make_callback(self, *args, **kwargs):
|
|
116
|
-
# type: (Route, *object, **object) -> Any
|
|
114
|
+
def patched_make_callback(self: Route, *args: object, **kwargs: object) -> Any:
|
|
117
115
|
prepared_callback = old_make_callback(self, *args, **kwargs)
|
|
118
116
|
|
|
119
117
|
integration = sentry_sdk.get_client().get_integration(BottleIntegration)
|
|
120
118
|
if integration is None:
|
|
121
119
|
return prepared_callback
|
|
122
120
|
|
|
123
|
-
def wrapped_callback(*args, **kwargs):
|
|
124
|
-
# type: (*object, **object) -> Any
|
|
121
|
+
def wrapped_callback(*args: object, **kwargs: object) -> Any:
|
|
125
122
|
try:
|
|
126
123
|
res = prepared_callback(*args, **kwargs)
|
|
127
124
|
except Exception as exception:
|
|
@@ -142,38 +139,33 @@ class BottleIntegration(Integration):
|
|
|
142
139
|
|
|
143
140
|
|
|
144
141
|
class BottleRequestExtractor(RequestExtractor):
|
|
145
|
-
def env(self):
|
|
146
|
-
# type: () -> Dict[str, str]
|
|
142
|
+
def env(self) -> Dict[str, str]:
|
|
147
143
|
return self.request.environ
|
|
148
144
|
|
|
149
|
-
def cookies(self):
|
|
150
|
-
# type: () -> Dict[str, str]
|
|
145
|
+
def cookies(self) -> Dict[str, str]:
|
|
151
146
|
return self.request.cookies
|
|
152
147
|
|
|
153
|
-
def raw_data(self):
|
|
154
|
-
# type: () -> bytes
|
|
148
|
+
def raw_data(self) -> bytes:
|
|
155
149
|
return self.request.body.read()
|
|
156
150
|
|
|
157
|
-
def form(self):
|
|
158
|
-
# type: () -> FormsDict
|
|
151
|
+
def form(self) -> FormsDict:
|
|
159
152
|
if self.is_json():
|
|
160
153
|
return None
|
|
161
154
|
return self.request.forms.decode()
|
|
162
155
|
|
|
163
|
-
def files(self):
|
|
164
|
-
# type: () -> Optional[Dict[str, str]]
|
|
156
|
+
def files(self) -> Optional[Dict[str, str]]:
|
|
165
157
|
if self.is_json():
|
|
166
158
|
return None
|
|
167
159
|
|
|
168
160
|
return self.request.files
|
|
169
161
|
|
|
170
|
-
def size_of_file(self, file):
|
|
171
|
-
# type: (FileUpload) -> int
|
|
162
|
+
def size_of_file(self, file: FileUpload) -> int:
|
|
172
163
|
return file.content_length
|
|
173
164
|
|
|
174
165
|
|
|
175
|
-
def _set_transaction_name_and_source(
|
|
176
|
-
|
|
166
|
+
def _set_transaction_name_and_source(
|
|
167
|
+
event: Event, transaction_style: str, request: Any
|
|
168
|
+
) -> None:
|
|
177
169
|
name = ""
|
|
178
170
|
|
|
179
171
|
if transaction_style == "url":
|
|
@@ -196,11 +188,11 @@ def _set_transaction_name_and_source(event, transaction_style, request):
|
|
|
196
188
|
event["transaction_info"] = {"source": SOURCE_FOR_STYLE[transaction_style]}
|
|
197
189
|
|
|
198
190
|
|
|
199
|
-
def _make_request_event_processor(
|
|
200
|
-
|
|
191
|
+
def _make_request_event_processor(
|
|
192
|
+
app: Bottle, request: LocalRequest, integration: BottleIntegration
|
|
193
|
+
) -> EventProcessor:
|
|
201
194
|
|
|
202
|
-
def event_processor(event, hint):
|
|
203
|
-
# type: (Event, dict[str, Any]) -> Event
|
|
195
|
+
def event_processor(event: Event, hint: dict[str, Any]) -> Event:
|
|
204
196
|
_set_transaction_name_and_source(event, integration.transaction_style, request)
|
|
205
197
|
|
|
206
198
|
with capture_internal_exceptions():
|
|
@@ -211,8 +203,7 @@ def _make_request_event_processor(app, request, integration):
|
|
|
211
203
|
return event_processor
|
|
212
204
|
|
|
213
205
|
|
|
214
|
-
def _capture_exception(exception, handled):
|
|
215
|
-
# type: (BaseException, bool) -> None
|
|
206
|
+
def _capture_exception(exception: BaseException, handled: bool) -> None:
|
|
216
207
|
event, hint = event_from_exception(
|
|
217
208
|
exception,
|
|
218
209
|
client_options=sentry_sdk.get_client().options,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sys
|
|
2
3
|
from collections.abc import Mapping
|
|
3
4
|
from functools import wraps
|
|
@@ -8,7 +9,7 @@ from sentry_sdk.consts import OP, SPANSTATUS, SPANDATA, BAGGAGE_HEADER_NAME
|
|
|
8
9
|
from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable
|
|
9
10
|
from sentry_sdk.integrations.celery.beat import (
|
|
10
11
|
_patch_beat_apply_entry,
|
|
11
|
-
|
|
12
|
+
_patch_redbeat_apply_async,
|
|
12
13
|
_setup_celery_beat_signals,
|
|
13
14
|
)
|
|
14
15
|
from sentry_sdk.integrations.celery.utils import _now_seconds_since_epoch
|
|
@@ -62,22 +63,20 @@ class CeleryIntegration(Integration):
|
|
|
62
63
|
|
|
63
64
|
def __init__(
|
|
64
65
|
self,
|
|
65
|
-
propagate_traces=True,
|
|
66
|
-
monitor_beat_tasks=False,
|
|
67
|
-
exclude_beat_tasks=None,
|
|
68
|
-
):
|
|
69
|
-
# type: (bool, bool, Optional[List[str]]) -> None
|
|
66
|
+
propagate_traces: bool = True,
|
|
67
|
+
monitor_beat_tasks: bool = False,
|
|
68
|
+
exclude_beat_tasks: Optional[List[str]] = None,
|
|
69
|
+
) -> None:
|
|
70
70
|
self.propagate_traces = propagate_traces
|
|
71
71
|
self.monitor_beat_tasks = monitor_beat_tasks
|
|
72
72
|
self.exclude_beat_tasks = exclude_beat_tasks
|
|
73
73
|
|
|
74
74
|
_patch_beat_apply_entry()
|
|
75
|
-
|
|
75
|
+
_patch_redbeat_apply_async()
|
|
76
76
|
_setup_celery_beat_signals(monitor_beat_tasks)
|
|
77
77
|
|
|
78
78
|
@staticmethod
|
|
79
|
-
def setup_once():
|
|
80
|
-
# type: () -> None
|
|
79
|
+
def setup_once() -> None:
|
|
81
80
|
_check_minimum_version(CeleryIntegration, CELERY_VERSION)
|
|
82
81
|
|
|
83
82
|
_patch_build_tracer()
|
|
@@ -97,16 +96,14 @@ class CeleryIntegration(Integration):
|
|
|
97
96
|
ignore_logger("celery.redirected")
|
|
98
97
|
|
|
99
98
|
|
|
100
|
-
def _set_status(status):
|
|
101
|
-
# type: (str) -> None
|
|
99
|
+
def _set_status(status: str) -> None:
|
|
102
100
|
with capture_internal_exceptions():
|
|
103
|
-
|
|
104
|
-
if
|
|
105
|
-
|
|
101
|
+
span = sentry_sdk.get_current_span()
|
|
102
|
+
if span is not None:
|
|
103
|
+
span.set_status(status)
|
|
106
104
|
|
|
107
105
|
|
|
108
|
-
def _capture_exception(task, exc_info):
|
|
109
|
-
# type: (Any, ExcInfo) -> None
|
|
106
|
+
def _capture_exception(task: Any, exc_info: ExcInfo) -> None:
|
|
110
107
|
client = sentry_sdk.get_client()
|
|
111
108
|
if client.get_integration(CeleryIntegration) is None:
|
|
112
109
|
return
|
|
@@ -129,10 +126,10 @@ def _capture_exception(task, exc_info):
|
|
|
129
126
|
sentry_sdk.capture_event(event, hint=hint)
|
|
130
127
|
|
|
131
128
|
|
|
132
|
-
def _make_event_processor(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
129
|
+
def _make_event_processor(
|
|
130
|
+
task: Any, uuid: Any, args: Any, kwargs: Any, request: Optional[Any] = None
|
|
131
|
+
) -> EventProcessor:
|
|
132
|
+
def event_processor(event: Event, hint: Hint) -> Optional[Event]:
|
|
136
133
|
|
|
137
134
|
with capture_internal_exceptions():
|
|
138
135
|
tags = event.setdefault("tags", {})
|
|
@@ -158,8 +155,9 @@ def _make_event_processor(task, uuid, args, kwargs, request=None):
|
|
|
158
155
|
return event_processor
|
|
159
156
|
|
|
160
157
|
|
|
161
|
-
def _update_celery_task_headers(
|
|
162
|
-
|
|
158
|
+
def _update_celery_task_headers(
|
|
159
|
+
original_headers: dict[str, Any], span: Optional[Span], monitor_beat_tasks: bool
|
|
160
|
+
) -> dict[str, Any]:
|
|
163
161
|
"""
|
|
164
162
|
Updates the headers of the Celery task with the tracing information
|
|
165
163
|
and eventually Sentry Crons monitoring information for beat tasks.
|
|
@@ -233,20 +231,16 @@ def _update_celery_task_headers(original_headers, span, monitor_beat_tasks):
|
|
|
233
231
|
|
|
234
232
|
|
|
235
233
|
class NoOpMgr:
|
|
236
|
-
def __enter__(self):
|
|
237
|
-
# type: () -> None
|
|
234
|
+
def __enter__(self) -> None:
|
|
238
235
|
return None
|
|
239
236
|
|
|
240
|
-
def __exit__(self, exc_type, exc_value, traceback):
|
|
241
|
-
# type: (Any, Any, Any) -> None
|
|
237
|
+
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
242
238
|
return None
|
|
243
239
|
|
|
244
240
|
|
|
245
|
-
def _wrap_task_run(f):
|
|
246
|
-
# type: (F) -> F
|
|
241
|
+
def _wrap_task_run(f: F) -> F:
|
|
247
242
|
@wraps(f)
|
|
248
|
-
def apply_async(*args, **kwargs):
|
|
249
|
-
# type: (*Any, **Any) -> Any
|
|
243
|
+
def apply_async(*args: Any, **kwargs: Any) -> Any:
|
|
250
244
|
# Note: kwargs can contain headers=None, so no setdefault!
|
|
251
245
|
# Unsure which backend though.
|
|
252
246
|
integration = sentry_sdk.get_client().get_integration(CeleryIntegration)
|
|
@@ -262,7 +256,7 @@ def _wrap_task_run(f):
|
|
|
262
256
|
return f(*args, **kwargs)
|
|
263
257
|
|
|
264
258
|
if isinstance(args[0], Task):
|
|
265
|
-
task_name = args[0].name
|
|
259
|
+
task_name: str = args[0].name
|
|
266
260
|
elif len(args) > 1 and isinstance(args[1], str):
|
|
267
261
|
task_name = args[1]
|
|
268
262
|
else:
|
|
@@ -270,7 +264,7 @@ def _wrap_task_run(f):
|
|
|
270
264
|
|
|
271
265
|
task_started_from_beat = sentry_sdk.get_isolation_scope()._name == "celery-beat"
|
|
272
266
|
|
|
273
|
-
span_mgr = (
|
|
267
|
+
span_mgr: Union[Span, NoOpMgr] = (
|
|
274
268
|
sentry_sdk.start_span(
|
|
275
269
|
op=OP.QUEUE_SUBMIT_CELERY,
|
|
276
270
|
name=task_name,
|
|
@@ -279,7 +273,7 @@ def _wrap_task_run(f):
|
|
|
279
273
|
)
|
|
280
274
|
if not task_started_from_beat
|
|
281
275
|
else NoOpMgr()
|
|
282
|
-
)
|
|
276
|
+
)
|
|
283
277
|
|
|
284
278
|
with span_mgr as span:
|
|
285
279
|
kwargs["headers"] = _update_celery_task_headers(
|
|
@@ -290,8 +284,7 @@ def _wrap_task_run(f):
|
|
|
290
284
|
return apply_async # type: ignore
|
|
291
285
|
|
|
292
286
|
|
|
293
|
-
def _wrap_tracer(task, f):
|
|
294
|
-
# type: (Any, F) -> F
|
|
287
|
+
def _wrap_tracer(task: Any, f: F) -> F:
|
|
295
288
|
|
|
296
289
|
# Need to wrap tracer for pushing the scope before prerun is sent, and
|
|
297
290
|
# popping it after postrun is sent.
|
|
@@ -301,8 +294,7 @@ def _wrap_tracer(task, f):
|
|
|
301
294
|
# crashes.
|
|
302
295
|
@wraps(f)
|
|
303
296
|
@ensure_integration_enabled(CeleryIntegration, f)
|
|
304
|
-
def _inner(*args, **kwargs):
|
|
305
|
-
# type: (*Any, **Any) -> Any
|
|
297
|
+
def _inner(*args: Any, **kwargs: Any) -> Any:
|
|
306
298
|
with isolation_scope() as scope:
|
|
307
299
|
scope._name = "celery"
|
|
308
300
|
scope.clear_breadcrumbs()
|
|
@@ -333,8 +325,7 @@ def _wrap_tracer(task, f):
|
|
|
333
325
|
return _inner # type: ignore
|
|
334
326
|
|
|
335
327
|
|
|
336
|
-
def _set_messaging_destination_name(task, span):
|
|
337
|
-
# type: (Any, Span) -> None
|
|
328
|
+
def _set_messaging_destination_name(task: Any, span: Span) -> None:
|
|
338
329
|
"""Set "messaging.destination.name" tag for span"""
|
|
339
330
|
with capture_internal_exceptions():
|
|
340
331
|
delivery_info = task.request.delivery_info
|
|
@@ -346,8 +337,7 @@ def _set_messaging_destination_name(task, span):
|
|
|
346
337
|
span.set_attribute(SPANDATA.MESSAGING_DESTINATION_NAME, routing_key)
|
|
347
338
|
|
|
348
339
|
|
|
349
|
-
def _wrap_task_call(task, f):
|
|
350
|
-
# type: (Any, F) -> F
|
|
340
|
+
def _wrap_task_call(task: Any, f: F) -> F:
|
|
351
341
|
|
|
352
342
|
# Need to wrap task call because the exception is caught before we get to
|
|
353
343
|
# see it. Also celery's reported stacktrace is untrustworthy.
|
|
@@ -358,8 +348,7 @@ def _wrap_task_call(task, f):
|
|
|
358
348
|
# to add @functools.wraps(f) here.
|
|
359
349
|
# https://github.com/getsentry/sentry-python/issues/421
|
|
360
350
|
@ensure_integration_enabled(CeleryIntegration, f)
|
|
361
|
-
def _inner(*args, **kwargs):
|
|
362
|
-
# type: (*Any, **Any) -> Any
|
|
351
|
+
def _inner(*args: Any, **kwargs: Any) -> Any:
|
|
363
352
|
try:
|
|
364
353
|
with sentry_sdk.start_span(
|
|
365
354
|
op=OP.QUEUE_PROCESS,
|
|
@@ -409,14 +398,12 @@ def _wrap_task_call(task, f):
|
|
|
409
398
|
return _inner # type: ignore
|
|
410
399
|
|
|
411
400
|
|
|
412
|
-
def _patch_build_tracer():
|
|
413
|
-
# type: () -> None
|
|
401
|
+
def _patch_build_tracer() -> None:
|
|
414
402
|
import celery.app.trace as trace # type: ignore
|
|
415
403
|
|
|
416
404
|
original_build_tracer = trace.build_tracer
|
|
417
405
|
|
|
418
|
-
def sentry_build_tracer(name, task, *args, **kwargs):
|
|
419
|
-
# type: (Any, Any, *Any, **Any) -> Any
|
|
406
|
+
def sentry_build_tracer(name: Any, task: Any, *args: Any, **kwargs: Any) -> Any:
|
|
420
407
|
if not getattr(task, "_sentry_is_patched", False):
|
|
421
408
|
# determine whether Celery will use __call__ or run and patch
|
|
422
409
|
# accordingly
|
|
@@ -435,20 +422,17 @@ def _patch_build_tracer():
|
|
|
435
422
|
trace.build_tracer = sentry_build_tracer
|
|
436
423
|
|
|
437
424
|
|
|
438
|
-
def _patch_task_apply_async():
|
|
439
|
-
# type: () -> None
|
|
425
|
+
def _patch_task_apply_async() -> None:
|
|
440
426
|
Task.apply_async = _wrap_task_run(Task.apply_async)
|
|
441
427
|
|
|
442
428
|
|
|
443
|
-
def _patch_celery_send_task():
|
|
444
|
-
# type: () -> None
|
|
429
|
+
def _patch_celery_send_task() -> None:
|
|
445
430
|
from celery import Celery
|
|
446
431
|
|
|
447
432
|
Celery.send_task = _wrap_task_run(Celery.send_task)
|
|
448
433
|
|
|
449
434
|
|
|
450
|
-
def _patch_worker_exit():
|
|
451
|
-
# type: () -> None
|
|
435
|
+
def _patch_worker_exit() -> None:
|
|
452
436
|
|
|
453
437
|
# Need to flush queue before worker shutdown because a crashing worker will
|
|
454
438
|
# call os._exit
|
|
@@ -456,8 +440,7 @@ def _patch_worker_exit():
|
|
|
456
440
|
|
|
457
441
|
original_workloop = Worker.workloop
|
|
458
442
|
|
|
459
|
-
def sentry_workloop(*args, **kwargs):
|
|
460
|
-
# type: (*Any, **Any) -> Any
|
|
443
|
+
def sentry_workloop(*args: Any, **kwargs: Any) -> Any:
|
|
461
444
|
try:
|
|
462
445
|
return original_workloop(*args, **kwargs)
|
|
463
446
|
finally:
|
|
@@ -471,13 +454,11 @@ def _patch_worker_exit():
|
|
|
471
454
|
Worker.workloop = sentry_workloop
|
|
472
455
|
|
|
473
456
|
|
|
474
|
-
def _patch_producer_publish():
|
|
475
|
-
# type: () -> None
|
|
457
|
+
def _patch_producer_publish() -> None:
|
|
476
458
|
original_publish = Producer.publish
|
|
477
459
|
|
|
478
460
|
@ensure_integration_enabled(CeleryIntegration, original_publish)
|
|
479
|
-
def sentry_publish(self, *args, **kwargs):
|
|
480
|
-
# type: (Producer, *Any, **Any) -> Any
|
|
461
|
+
def sentry_publish(self: Producer, *args: Any, **kwargs: Any) -> Any:
|
|
481
462
|
kwargs_headers = kwargs.get("headers", {})
|
|
482
463
|
if not isinstance(kwargs_headers, Mapping):
|
|
483
464
|
# Ensure kwargs_headers is a Mapping, so we can safely call get().
|
|
@@ -521,8 +502,7 @@ def _patch_producer_publish():
|
|
|
521
502
|
Producer.publish = sentry_publish
|
|
522
503
|
|
|
523
504
|
|
|
524
|
-
def _prepopulate_attributes(task, args, kwargs):
|
|
525
|
-
# type: (Any, *Any, **Any) -> dict[str, str]
|
|
505
|
+
def _prepopulate_attributes(task: Any, args: Any, kwargs: Any) -> dict[str, str]:
|
|
526
506
|
attributes = {
|
|
527
507
|
"celery.job.task": task.name,
|
|
528
508
|
}
|