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.

Files changed (157) hide show
  1. sentry_sdk/__init__.py +2 -0
  2. sentry_sdk/_compat.py +5 -12
  3. sentry_sdk/_init_implementation.py +7 -7
  4. sentry_sdk/_log_batcher.py +17 -29
  5. sentry_sdk/_lru_cache.py +7 -9
  6. sentry_sdk/_queue.py +2 -4
  7. sentry_sdk/_types.py +9 -16
  8. sentry_sdk/_werkzeug.py +5 -7
  9. sentry_sdk/ai/monitoring.py +40 -28
  10. sentry_sdk/ai/utils.py +3 -4
  11. sentry_sdk/api.py +75 -87
  12. sentry_sdk/attachments.py +10 -12
  13. sentry_sdk/client.py +110 -153
  14. sentry_sdk/consts.py +398 -220
  15. sentry_sdk/crons/api.py +16 -17
  16. sentry_sdk/crons/decorator.py +25 -27
  17. sentry_sdk/debug.py +4 -6
  18. sentry_sdk/envelope.py +46 -112
  19. sentry_sdk/feature_flags.py +9 -15
  20. sentry_sdk/integrations/__init__.py +24 -19
  21. sentry_sdk/integrations/_asgi_common.py +16 -18
  22. sentry_sdk/integrations/_wsgi_common.py +22 -33
  23. sentry_sdk/integrations/aiohttp.py +32 -30
  24. sentry_sdk/integrations/anthropic.py +42 -37
  25. sentry_sdk/integrations/argv.py +3 -4
  26. sentry_sdk/integrations/ariadne.py +16 -18
  27. sentry_sdk/integrations/arq.py +19 -28
  28. sentry_sdk/integrations/asgi.py +63 -37
  29. sentry_sdk/integrations/asyncio.py +14 -16
  30. sentry_sdk/integrations/atexit.py +6 -10
  31. sentry_sdk/integrations/aws_lambda.py +26 -36
  32. sentry_sdk/integrations/beam.py +10 -18
  33. sentry_sdk/integrations/boto3.py +18 -16
  34. sentry_sdk/integrations/bottle.py +25 -34
  35. sentry_sdk/integrations/celery/__init__.py +36 -56
  36. sentry_sdk/integrations/celery/beat.py +22 -26
  37. sentry_sdk/integrations/celery/utils.py +15 -17
  38. sentry_sdk/integrations/chalice.py +8 -10
  39. sentry_sdk/integrations/clickhouse_driver.py +21 -31
  40. sentry_sdk/integrations/cloud_resource_context.py +9 -16
  41. sentry_sdk/integrations/cohere.py +17 -23
  42. sentry_sdk/integrations/dedupe.py +5 -8
  43. sentry_sdk/integrations/django/__init__.py +57 -72
  44. sentry_sdk/integrations/django/asgi.py +24 -32
  45. sentry_sdk/integrations/django/caching.py +23 -19
  46. sentry_sdk/integrations/django/middleware.py +17 -20
  47. sentry_sdk/integrations/django/signals_handlers.py +11 -10
  48. sentry_sdk/integrations/django/templates.py +19 -16
  49. sentry_sdk/integrations/django/transactions.py +16 -11
  50. sentry_sdk/integrations/django/views.py +6 -10
  51. sentry_sdk/integrations/dramatiq.py +21 -21
  52. sentry_sdk/integrations/excepthook.py +10 -10
  53. sentry_sdk/integrations/executing.py +3 -4
  54. sentry_sdk/integrations/falcon.py +27 -42
  55. sentry_sdk/integrations/fastapi.py +13 -16
  56. sentry_sdk/integrations/flask.py +31 -38
  57. sentry_sdk/integrations/gcp.py +13 -16
  58. sentry_sdk/integrations/gnu_backtrace.py +4 -6
  59. sentry_sdk/integrations/gql.py +16 -17
  60. sentry_sdk/integrations/graphene.py +13 -12
  61. sentry_sdk/integrations/grpc/__init__.py +3 -2
  62. sentry_sdk/integrations/grpc/aio/server.py +15 -14
  63. sentry_sdk/integrations/grpc/client.py +19 -9
  64. sentry_sdk/integrations/grpc/consts.py +2 -0
  65. sentry_sdk/integrations/grpc/server.py +12 -8
  66. sentry_sdk/integrations/httpx.py +9 -12
  67. sentry_sdk/integrations/huey.py +13 -20
  68. sentry_sdk/integrations/huggingface_hub.py +16 -16
  69. sentry_sdk/integrations/langchain.py +203 -113
  70. sentry_sdk/integrations/launchdarkly.py +13 -10
  71. sentry_sdk/integrations/litestar.py +37 -35
  72. sentry_sdk/integrations/logging.py +28 -35
  73. sentry_sdk/integrations/loguru.py +15 -19
  74. sentry_sdk/integrations/modules.py +3 -4
  75. sentry_sdk/integrations/openai.py +96 -84
  76. sentry_sdk/integrations/openai_agents/__init__.py +49 -0
  77. sentry_sdk/integrations/openai_agents/consts.py +1 -0
  78. sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
  79. sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
  80. sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
  81. sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
  82. sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
  83. sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
  84. sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
  85. sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
  86. sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
  87. sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
  88. sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
  89. sentry_sdk/integrations/openai_agents/utils.py +201 -0
  90. sentry_sdk/integrations/openfeature.py +11 -6
  91. sentry_sdk/integrations/pure_eval.py +6 -10
  92. sentry_sdk/integrations/pymongo.py +13 -17
  93. sentry_sdk/integrations/pyramid.py +31 -36
  94. sentry_sdk/integrations/quart.py +23 -28
  95. sentry_sdk/integrations/ray.py +73 -64
  96. sentry_sdk/integrations/redis/__init__.py +7 -4
  97. sentry_sdk/integrations/redis/_async_common.py +15 -9
  98. sentry_sdk/integrations/redis/_sync_common.py +13 -12
  99. sentry_sdk/integrations/redis/modules/caches.py +17 -8
  100. sentry_sdk/integrations/redis/modules/queries.py +9 -8
  101. sentry_sdk/integrations/redis/rb.py +3 -2
  102. sentry_sdk/integrations/redis/redis.py +4 -4
  103. sentry_sdk/integrations/redis/redis_cluster.py +10 -8
  104. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  105. sentry_sdk/integrations/redis/utils.py +21 -22
  106. sentry_sdk/integrations/rq.py +13 -16
  107. sentry_sdk/integrations/rust_tracing.py +9 -6
  108. sentry_sdk/integrations/sanic.py +34 -46
  109. sentry_sdk/integrations/serverless.py +22 -27
  110. sentry_sdk/integrations/socket.py +27 -15
  111. sentry_sdk/integrations/spark/__init__.py +1 -0
  112. sentry_sdk/integrations/spark/spark_driver.py +45 -83
  113. sentry_sdk/integrations/spark/spark_worker.py +7 -11
  114. sentry_sdk/integrations/sqlalchemy.py +22 -19
  115. sentry_sdk/integrations/starlette.py +86 -90
  116. sentry_sdk/integrations/starlite.py +28 -34
  117. sentry_sdk/integrations/statsig.py +5 -4
  118. sentry_sdk/integrations/stdlib.py +28 -24
  119. sentry_sdk/integrations/strawberry.py +62 -49
  120. sentry_sdk/integrations/sys_exit.py +7 -11
  121. sentry_sdk/integrations/threading.py +12 -14
  122. sentry_sdk/integrations/tornado.py +28 -32
  123. sentry_sdk/integrations/trytond.py +4 -3
  124. sentry_sdk/integrations/typer.py +8 -6
  125. sentry_sdk/integrations/unleash.py +5 -4
  126. sentry_sdk/integrations/wsgi.py +47 -46
  127. sentry_sdk/logger.py +13 -9
  128. sentry_sdk/monitor.py +16 -28
  129. sentry_sdk/opentelemetry/consts.py +11 -4
  130. sentry_sdk/opentelemetry/contextvars_context.py +17 -15
  131. sentry_sdk/opentelemetry/propagator.py +38 -21
  132. sentry_sdk/opentelemetry/sampler.py +51 -34
  133. sentry_sdk/opentelemetry/scope.py +36 -37
  134. sentry_sdk/opentelemetry/span_processor.py +43 -59
  135. sentry_sdk/opentelemetry/tracing.py +32 -12
  136. sentry_sdk/opentelemetry/utils.py +180 -196
  137. sentry_sdk/profiler/continuous_profiler.py +108 -97
  138. sentry_sdk/profiler/transaction_profiler.py +70 -97
  139. sentry_sdk/profiler/utils.py +11 -15
  140. sentry_sdk/scope.py +251 -264
  141. sentry_sdk/scrubber.py +22 -26
  142. sentry_sdk/serializer.py +40 -54
  143. sentry_sdk/session.py +44 -61
  144. sentry_sdk/sessions.py +35 -49
  145. sentry_sdk/spotlight.py +15 -21
  146. sentry_sdk/tracing.py +116 -182
  147. sentry_sdk/tracing_utils.py +100 -120
  148. sentry_sdk/transport.py +131 -157
  149. sentry_sdk/utils.py +232 -309
  150. sentry_sdk/worker.py +16 -28
  151. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +1 -1
  152. sentry_sdk-3.0.0a3.dist-info/RECORD +168 -0
  153. sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
  154. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/WHEEL +0 -0
  155. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
  156. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
  157. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a3.dist-info}/top_level.txt +0 -0
@@ -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
  """
@@ -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(self, *args, **kwargs):
45
- # type: (Type[BaseClient], *Any, **Any) -> None
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(service_id, request, operation_name, **kwargs):
61
- # type: (str, AWSRequest, str, **Any) -> None
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(context, parsed, **kwargs):
96
- # type: (Dict[str, Any], Dict[str, Any], **Any) -> None
97
- span = context.pop("_sentrysdk_span", None) # type: Optional[Span]
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(context, exception, **kwargs):
151
- # type: (Dict[str, Any], Type[BaseException], **Any) -> None
152
- span = context.pop("_sentrysdk_span", None) # type: Optional[Span]
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", # type: str
59
+ transaction_style: str = "endpoint",
59
60
  *,
60
- failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int]
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(self, environ, start_response):
82
- # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse
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(event, transaction_style, request):
176
- # type: (Event, str, Any) -> None
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(app, request, integration):
200
- # type: (Bottle, LocalRequest, BottleIntegration) -> EventProcessor
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
@@ -62,11 +63,10 @@ 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
@@ -76,8 +76,7 @@ class CeleryIntegration(Integration):
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
101
  span = sentry_sdk.get_current_span()
104
102
  if span is not None:
105
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(task, uuid, args, kwargs, request=None):
133
- # type: (Any, Any, Any, Any, Optional[Any]) -> EventProcessor
134
- def event_processor(event, hint):
135
- # type: (Event, Hint) -> Optional[Event]
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(original_headers, span, monitor_beat_tasks):
162
- # type: (dict[str, Any], Optional[Span], bool) -> dict[str, Any]
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 # type: str
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
- ) # type: Union[Span, NoOpMgr]
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
  }
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sentry_sdk
2
3
  from sentry_sdk.crons import capture_checkin, MonitorStatus
3
4
  from sentry_sdk.integrations import DidNotEnable
@@ -42,8 +43,7 @@ except ImportError:
42
43
  RedBeatScheduler = None
43
44
 
44
45
 
45
- def _get_headers(task):
46
- # type: (Task) -> dict[str, Any]
46
+ def _get_headers(task: Task) -> dict[str, Any]:
47
47
  headers = task.request.get("headers") or {}
48
48
 
49
49
  # flatten nested headers
@@ -56,12 +56,13 @@ def _get_headers(task):
56
56
  return headers
57
57
 
58
58
 
59
- def _get_monitor_config(celery_schedule, app, monitor_name):
60
- # type: (Any, Celery, str) -> MonitorConfig
61
- monitor_config = {} # type: MonitorConfig
62
- schedule_type = None # type: Optional[MonitorConfigScheduleType]
63
- schedule_value = None # type: Optional[Union[str, int]]
64
- schedule_unit = None # type: Optional[MonitorConfigScheduleUnit]
59
+ def _get_monitor_config(
60
+ celery_schedule: Any, app: Celery, monitor_name: str
61
+ ) -> MonitorConfig:
62
+ monitor_config: MonitorConfig = {}
63
+ schedule_type: Optional[MonitorConfigScheduleType] = None
64
+ schedule_value: Optional[Union[str, int]] = None
65
+ schedule_unit: Optional[MonitorConfigScheduleUnit] = None
65
66
 
66
67
  if isinstance(celery_schedule, crontab):
67
68
  schedule_type = "crontab"
@@ -113,8 +114,11 @@ def _get_monitor_config(celery_schedule, app, monitor_name):
113
114
  return monitor_config
114
115
 
115
116
 
116
- def _apply_crons_data_to_schedule_entry(scheduler, schedule_entry, integration):
117
- # type: (Any, Any, sentry_sdk.integrations.celery.CeleryIntegration) -> None
117
+ def _apply_crons_data_to_schedule_entry(
118
+ scheduler: Any,
119
+ schedule_entry: Any,
120
+ integration: sentry_sdk.integrations.celery.CeleryIntegration,
121
+ ) -> None:
118
122
  """
119
123
  Add Sentry Crons information to the schedule_entry headers.
120
124
  """
@@ -158,8 +162,7 @@ def _apply_crons_data_to_schedule_entry(scheduler, schedule_entry, integration):
158
162
  schedule_entry.options["headers"] = headers
159
163
 
160
164
 
161
- def _wrap_beat_scheduler(original_function):
162
- # type: (Callable[..., Any]) -> Callable[..., Any]
165
+ def _wrap_beat_scheduler(original_function: Callable[..., Any]) -> Callable[..., Any]:
163
166
  """
164
167
  Makes sure that:
165
168
  - a new Sentry trace is started for each task started by Celery Beat and
@@ -178,8 +181,7 @@ def _wrap_beat_scheduler(original_function):
178
181
 
179
182
  from sentry_sdk.integrations.celery import CeleryIntegration
180
183
 
181
- def sentry_patched_scheduler(*args, **kwargs):
182
- # type: (*Any, **Any) -> None
184
+ def sentry_patched_scheduler(*args: Any, **kwargs: Any) -> None:
183
185
  integration = sentry_sdk.get_client().get_integration(CeleryIntegration)
184
186
  if integration is None:
185
187
  return original_function(*args, **kwargs)
@@ -197,29 +199,25 @@ def _wrap_beat_scheduler(original_function):
197
199
  return sentry_patched_scheduler
198
200
 
199
201
 
200
- def _patch_beat_apply_entry():
201
- # type: () -> None
202
+ def _patch_beat_apply_entry() -> None:
202
203
  Scheduler.apply_entry = _wrap_beat_scheduler(Scheduler.apply_entry)
203
204
 
204
205
 
205
- def _patch_redbeat_apply_async():
206
- # type: () -> None
206
+ def _patch_redbeat_apply_async() -> None:
207
207
  if RedBeatScheduler is None:
208
208
  return
209
209
 
210
210
  RedBeatScheduler.apply_async = _wrap_beat_scheduler(RedBeatScheduler.apply_async)
211
211
 
212
212
 
213
- def _setup_celery_beat_signals(monitor_beat_tasks):
214
- # type: (bool) -> None
213
+ def _setup_celery_beat_signals(monitor_beat_tasks: bool) -> None:
215
214
  if monitor_beat_tasks:
216
215
  task_success.connect(crons_task_success)
217
216
  task_failure.connect(crons_task_failure)
218
217
  task_retry.connect(crons_task_retry)
219
218
 
220
219
 
221
- def crons_task_success(sender, **kwargs):
222
- # type: (Task, dict[Any, Any]) -> None
220
+ def crons_task_success(sender: Task, **kwargs: dict[Any, Any]) -> None:
223
221
  logger.debug("celery_task_success %s", sender)
224
222
  headers = _get_headers(sender)
225
223
 
@@ -243,8 +241,7 @@ def crons_task_success(sender, **kwargs):
243
241
  )
244
242
 
245
243
 
246
- def crons_task_failure(sender, **kwargs):
247
- # type: (Task, dict[Any, Any]) -> None
244
+ def crons_task_failure(sender: Task, **kwargs: dict[Any, Any]) -> None:
248
245
  logger.debug("celery_task_failure %s", sender)
249
246
  headers = _get_headers(sender)
250
247
 
@@ -268,8 +265,7 @@ def crons_task_failure(sender, **kwargs):
268
265
  )
269
266
 
270
267
 
271
- def crons_task_retry(sender, **kwargs):
272
- # type: (Task, dict[Any, Any]) -> None
268
+ def crons_task_retry(sender: Task, **kwargs: dict[Any, Any]) -> None:
273
269
  logger.debug("celery_task_retry %s", sender)
274
270
  headers = _get_headers(sender)
275
271