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.

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 +11 -18
  8. sentry_sdk/_werkzeug.py +5 -7
  9. sentry_sdk/ai/monitoring.py +44 -31
  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 +137 -155
  14. sentry_sdk/consts.py +430 -174
  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 +15 -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 +21 -29
  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 +41 -61
  36. sentry_sdk/integrations/celery/beat.py +23 -27
  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 +27 -33
  42. sentry_sdk/integrations/dedupe.py +5 -8
  43. sentry_sdk/integrations/django/__init__.py +57 -72
  44. sentry_sdk/integrations/django/asgi.py +26 -34
  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 +19 -1
  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 +18 -18
  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 +52 -65
  73. sentry_sdk/integrations/loguru.py +127 -57
  74. sentry_sdk/integrations/modules.py +3 -4
  75. sentry_sdk/integrations/openai.py +100 -88
  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 +25 -12
  98. sentry_sdk/integrations/redis/_sync_common.py +19 -13
  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 +21 -13
  104. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  105. sentry_sdk/integrations/redis/utils.py +23 -24
  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 +41 -10
  128. sentry_sdk/monitor.py +16 -28
  129. sentry_sdk/opentelemetry/consts.py +11 -4
  130. sentry_sdk/opentelemetry/contextvars_context.py +26 -16
  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 +48 -58
  135. sentry_sdk/opentelemetry/tracing.py +58 -14
  136. sentry_sdk/opentelemetry/utils.py +186 -194
  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 -273
  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 +121 -187
  147. sentry_sdk/tracing_utils.py +104 -122
  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.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +3 -3
  152. sentry_sdk-3.0.0a3.dist-info/RECORD +168 -0
  153. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/WHEEL +1 -1
  154. sentry_sdk-3.0.0a1.dist-info/RECORD +0 -154
  155. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
  156. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
  157. {sentry_sdk-3.0.0a1.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
 
3
4
  import sentry_sdk
@@ -45,8 +46,7 @@ class ArqIntegration(Integration):
45
46
  origin = f"auto.queue.{identifier}"
46
47
 
47
48
  @staticmethod
48
- def setup_once():
49
- # type: () -> None
49
+ def setup_once() -> None:
50
50
 
51
51
  try:
52
52
  if isinstance(ARQ_VERSION, str):
@@ -66,13 +66,13 @@ class ArqIntegration(Integration):
66
66
  ignore_logger("arq.worker")
67
67
 
68
68
 
69
- def patch_enqueue_job():
70
- # type: () -> None
69
+ def patch_enqueue_job() -> None:
71
70
  old_enqueue_job = ArqRedis.enqueue_job
72
71
  original_kwdefaults = old_enqueue_job.__kwdefaults__
73
72
 
74
- async def _sentry_enqueue_job(self, function, *args, **kwargs):
75
- # type: (ArqRedis, str, *Any, **Any) -> Optional[Job]
73
+ async def _sentry_enqueue_job(
74
+ self: ArqRedis, function: str, *args: Any, **kwargs: Any
75
+ ) -> Optional[Job]:
76
76
  integration = sentry_sdk.get_client().get_integration(ArqIntegration)
77
77
  if integration is None:
78
78
  return await old_enqueue_job(self, function, *args, **kwargs)
@@ -89,12 +89,10 @@ def patch_enqueue_job():
89
89
  ArqRedis.enqueue_job = _sentry_enqueue_job
90
90
 
91
91
 
92
- def patch_run_job():
93
- # type: () -> None
92
+ def patch_run_job() -> None:
94
93
  old_run_job = Worker.run_job
95
94
 
96
- async def _sentry_run_job(self, job_id, score):
97
- # type: (Worker, str, int) -> None
95
+ async def _sentry_run_job(self: Worker, job_id: str, score: int) -> None:
98
96
  integration = sentry_sdk.get_client().get_integration(ArqIntegration)
99
97
  if integration is None:
100
98
  return await old_run_job(self, job_id, score)
@@ -123,8 +121,7 @@ def patch_run_job():
123
121
  Worker.run_job = _sentry_run_job
124
122
 
125
123
 
126
- def _capture_exception(exc_info):
127
- # type: (ExcInfo) -> None
124
+ def _capture_exception(exc_info: ExcInfo) -> None:
128
125
  scope = sentry_sdk.get_current_scope()
129
126
 
130
127
  if scope.root_span is not None:
@@ -142,10 +139,10 @@ def _capture_exception(exc_info):
142
139
  sentry_sdk.capture_event(event, hint=hint)
143
140
 
144
141
 
145
- def _make_event_processor(ctx, *args, **kwargs):
146
- # type: (Dict[Any, Any], *Any, **Any) -> EventProcessor
147
- def event_processor(event, hint):
148
- # type: (Event, Hint) -> Optional[Event]
142
+ def _make_event_processor(
143
+ ctx: Dict[Any, Any], *args: Any, **kwargs: Any
144
+ ) -> EventProcessor:
145
+ def event_processor(event: Event, hint: Hint) -> Optional[Event]:
149
146
 
150
147
  with capture_internal_exceptions():
151
148
  scope = sentry_sdk.get_current_scope()
@@ -173,11 +170,9 @@ def _make_event_processor(ctx, *args, **kwargs):
173
170
  return event_processor
174
171
 
175
172
 
176
- def _wrap_coroutine(name, coroutine):
177
- # type: (str, WorkerCoroutine) -> WorkerCoroutine
173
+ def _wrap_coroutine(name: str, coroutine: WorkerCoroutine) -> WorkerCoroutine:
178
174
 
179
- async def _sentry_coroutine(ctx, *args, **kwargs):
180
- # type: (Dict[Any, Any], *Any, **Any) -> Any
175
+ async def _sentry_coroutine(ctx: Dict[Any, Any], *args: Any, **kwargs: Any) -> Any:
181
176
  integration = sentry_sdk.get_client().get_integration(ArqIntegration)
182
177
  if integration is None:
183
178
  return await coroutine(ctx, *args, **kwargs)
@@ -198,13 +193,11 @@ def _wrap_coroutine(name, coroutine):
198
193
  return _sentry_coroutine
199
194
 
200
195
 
201
- def patch_create_worker():
202
- # type: () -> None
196
+ def patch_create_worker() -> None:
203
197
  old_create_worker = arq.worker.create_worker
204
198
 
205
199
  @ensure_integration_enabled(ArqIntegration, old_create_worker)
206
- def _sentry_create_worker(*args, **kwargs):
207
- # type: (*Any, **Any) -> Worker
200
+ def _sentry_create_worker(*args: Any, **kwargs: Any) -> Worker:
208
201
  settings_cls = args[0]
209
202
 
210
203
  if isinstance(settings_cls, dict):
@@ -225,7 +218,8 @@ def patch_create_worker():
225
218
  ]
226
219
  if hasattr(settings_cls, "cron_jobs"):
227
220
  settings_cls.cron_jobs = [
228
- _get_arq_cron_job(cron_job) for cron_job in settings_cls.cron_jobs
221
+ _get_arq_cron_job(cron_job)
222
+ for cron_job in (settings_cls.cron_jobs or [])
229
223
  ]
230
224
 
231
225
  if "functions" in kwargs:
@@ -242,16 +236,14 @@ def patch_create_worker():
242
236
  arq.worker.create_worker = _sentry_create_worker
243
237
 
244
238
 
245
- def _get_arq_function(func):
246
- # type: (Union[str, Function, WorkerCoroutine]) -> Function
239
+ def _get_arq_function(func: Union[str, Function, WorkerCoroutine]) -> Function:
247
240
  arq_func = arq.worker.func(func)
248
241
  arq_func.coroutine = _wrap_coroutine(arq_func.name, arq_func.coroutine)
249
242
 
250
243
  return arq_func
251
244
 
252
245
 
253
- def _get_arq_cron_job(cron_job):
254
- # type: (CronJob) -> CronJob
246
+ def _get_arq_cron_job(cron_job: CronJob) -> CronJob:
255
247
  cron_job.coroutine = _wrap_coroutine(cron_job.name, cron_job.coroutine)
256
248
 
257
249
  return cron_job
@@ -4,6 +4,7 @@ An ASGI middleware.
4
4
  Based on Tom Christie's `sentry-asgi <https://github.com/encode/sentry-asgi>`.
5
5
  """
6
6
 
7
+ from __future__ import annotations
7
8
  import asyncio
8
9
  import inspect
9
10
  from copy import deepcopy
@@ -61,8 +62,7 @@ ASGI_SCOPE_PROPERTY_TO_ATTRIBUTE = {
61
62
  }
62
63
 
63
64
 
64
- def _capture_exception(exc, mechanism_type="asgi"):
65
- # type: (Any, str) -> None
65
+ def _capture_exception(exc: Any, mechanism_type: str = "asgi") -> None:
66
66
 
67
67
  event, hint = event_from_exception(
68
68
  exc,
@@ -72,8 +72,7 @@ def _capture_exception(exc, mechanism_type="asgi"):
72
72
  sentry_sdk.capture_event(event, hint=hint)
73
73
 
74
74
 
75
- def _looks_like_asgi3(app):
76
- # type: (Any) -> bool
75
+ def _looks_like_asgi3(app: Any) -> bool:
77
76
  """
78
77
  Try to figure out if an application object supports ASGI3.
79
78
 
@@ -100,14 +99,13 @@ class SentryAsgiMiddleware:
100
99
 
101
100
  def __init__(
102
101
  self,
103
- app, # type: Any
104
- unsafe_context_data=False, # type: bool
105
- transaction_style="endpoint", # type: str
106
- mechanism_type="asgi", # type: str
107
- span_origin=None, # type: Optional[str]
108
- http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: Tuple[str, ...]
109
- ):
110
- # type: (...) -> None
102
+ app: Any,
103
+ unsafe_context_data: bool = False,
104
+ transaction_style: str = "endpoint",
105
+ mechanism_type: str = "asgi",
106
+ span_origin: Optional[str] = None,
107
+ http_methods_to_capture: Tuple[str, ...] = DEFAULT_HTTP_METHODS_TO_CAPTURE,
108
+ ) -> None:
111
109
  """
112
110
  Instrument an ASGI application with Sentry. Provides HTTP/websocket
113
111
  data to sent events and basic handling for exceptions bubbling up
@@ -145,24 +143,41 @@ class SentryAsgiMiddleware:
145
143
  self.http_methods_to_capture = http_methods_to_capture
146
144
 
147
145
  if _looks_like_asgi3(app):
148
- self.__call__ = self._run_asgi3 # type: Callable[..., Any]
146
+ self.__call__: Callable[..., Any] = self._run_asgi3
149
147
  else:
150
148
  self.__call__ = self._run_asgi2
151
149
 
152
- def _run_asgi2(self, scope):
153
- # type: (Any) -> Any
154
- async def inner(receive, send):
155
- # type: (Any, Any) -> Any
150
+ def _capture_lifespan_exception(self, exc: Exception) -> None:
151
+ """Capture exceptions raise in application lifespan handlers.
152
+
153
+ The separate function is needed to support overriding in derived integrations that use different catching mechanisms.
154
+ """
155
+ return _capture_exception(exc=exc, mechanism_type=self.mechanism_type)
156
+
157
+ def _capture_request_exception(self, exc: Exception) -> None:
158
+ """Capture exceptions raised in incoming request handlers.
159
+
160
+ The separate function is needed to support overriding in derived integrations that use different catching mechanisms.
161
+ """
162
+ return _capture_exception(exc=exc, mechanism_type=self.mechanism_type)
163
+
164
+ def _run_asgi2(self, scope: Any) -> Any:
165
+ async def inner(receive: Any, send: Any) -> Any:
156
166
  return await self._run_app(scope, receive, send, asgi_version=2)
157
167
 
158
168
  return inner
159
169
 
160
- async def _run_asgi3(self, scope, receive, send):
161
- # type: (Any, Any, Any) -> Any
170
+ async def _run_asgi3(self, scope: Any, receive: Any, send: Any) -> Any:
162
171
  return await self._run_app(scope, receive, send, asgi_version=3)
163
172
 
164
- async def _run_original_app(self, scope, receive, send, asgi_version):
165
- # type: (Any, Any, Any, Any, int) -> Any
173
+ async def _run_original_app(
174
+ self,
175
+ scope: Any,
176
+ receive: Any,
177
+ send: Any,
178
+ asgi_version: Any,
179
+ is_lifespan: int = False,
180
+ ) -> Any:
166
181
  try:
167
182
  if asgi_version == 2:
168
183
  return await self.app(scope)(receive, send)
@@ -170,15 +185,21 @@ class SentryAsgiMiddleware:
170
185
  return await self.app(scope, receive, send)
171
186
 
172
187
  except Exception as exc:
173
- _capture_exception(exc, mechanism_type=self.mechanism_type)
188
+ if is_lifespan:
189
+ self._capture_lifespan_exception(exc)
190
+ else:
191
+ self._capture_request_exception(exc)
174
192
  raise exc from None
175
193
 
176
- async def _run_app(self, scope, receive, send, asgi_version):
177
- # type: (Any, Any, Any, Any, int) -> Any
194
+ async def _run_app(
195
+ self, scope: Any, receive: Any, send: Any, asgi_version: int
196
+ ) -> Any:
178
197
  is_recursive_asgi_middleware = _asgi_middleware_applied.get(False)
179
198
  is_lifespan = scope["type"] == "lifespan"
180
199
  if is_recursive_asgi_middleware or is_lifespan:
181
- return await self._run_original_app(scope, receive, send, asgi_version)
200
+ return await self._run_original_app(
201
+ scope, receive, send, asgi_version, is_lifespan
202
+ )
182
203
 
183
204
  _asgi_middleware_applied.set(True)
184
205
  try:
@@ -228,8 +249,9 @@ class SentryAsgiMiddleware:
228
249
  logger.debug("[ASGI] Started transaction: %s", span)
229
250
  span.set_tag("asgi.type", ty)
230
251
 
231
- async def _sentry_wrapped_send(event):
232
- # type: (Dict[str, Any]) -> Any
252
+ async def _sentry_wrapped_send(
253
+ event: Dict[str, Any],
254
+ ) -> Any:
233
255
  is_http_response = (
234
256
  event.get("type") == "http.response.start"
235
257
  and span is not None
@@ -241,13 +263,18 @@ class SentryAsgiMiddleware:
241
263
  return await send(event)
242
264
 
243
265
  return await self._run_original_app(
244
- scope, receive, _sentry_wrapped_send, asgi_version
266
+ scope,
267
+ receive,
268
+ _sentry_wrapped_send,
269
+ asgi_version,
270
+ is_lifespan,
245
271
  )
246
272
  finally:
247
273
  _asgi_middleware_applied.set(False)
248
274
 
249
- def event_processor(self, event, hint, asgi_scope):
250
- # type: (Event, Hint, Any) -> Optional[Event]
275
+ def event_processor(
276
+ self, event: Event, hint: Hint, asgi_scope: Any
277
+ ) -> Optional[Event]:
251
278
  request_data = event.get("request", {})
252
279
  request_data.update(_get_request_data(asgi_scope))
253
280
  event["request"] = deepcopy(request_data)
@@ -286,11 +313,11 @@ class SentryAsgiMiddleware:
286
313
  # data to your liking it's recommended to use the `before_send` callback
287
314
  # for that.
288
315
 
289
- def _get_transaction_name_and_source(self, transaction_style, asgi_scope):
290
- # type: (SentryAsgiMiddleware, str, Any) -> Tuple[str, str]
316
+ def _get_transaction_name_and_source(
317
+ self: SentryAsgiMiddleware, transaction_style: str, asgi_scope: Any
318
+ ) -> Tuple[str, str]:
291
319
  name = None
292
320
  source = SOURCE_FOR_STYLE[transaction_style]
293
- ty = asgi_scope.get("type")
294
321
 
295
322
  if transaction_style == "endpoint":
296
323
  endpoint = asgi_scope.get("endpoint")
@@ -300,7 +327,7 @@ class SentryAsgiMiddleware:
300
327
  if endpoint:
301
328
  name = transaction_from_function(endpoint) or ""
302
329
  else:
303
- name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None)
330
+ name = _get_url(asgi_scope)
304
331
  source = TransactionSource.URL
305
332
 
306
333
  elif transaction_style == "url":
@@ -312,7 +339,7 @@ class SentryAsgiMiddleware:
312
339
  if path is not None:
313
340
  name = path
314
341
  else:
315
- name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None)
342
+ name = _get_url(asgi_scope)
316
343
  source = TransactionSource.URL
317
344
 
318
345
  if name is None:
@@ -323,8 +350,7 @@ class SentryAsgiMiddleware:
323
350
  return name, source
324
351
 
325
352
 
326
- def _prepopulate_attributes(scope):
327
- # type: (Any) -> dict[str, Any]
353
+ def _prepopulate_attributes(scope: Any) -> dict[str, Any]:
328
354
  """Unpack ASGI scope into serializable OTel attributes."""
329
355
  scope = scope or {}
330
356
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sys
2
3
 
3
4
  import sentry_sdk
@@ -11,7 +12,7 @@ try:
11
12
  except ImportError:
12
13
  raise DidNotEnable("asyncio not available")
13
14
 
14
- from typing import cast, TYPE_CHECKING
15
+ from typing import TYPE_CHECKING
15
16
 
16
17
  if TYPE_CHECKING:
17
18
  from typing import Any
@@ -20,8 +21,7 @@ if TYPE_CHECKING:
20
21
  from sentry_sdk._types import ExcInfo
21
22
 
22
23
 
23
- def get_name(coro):
24
- # type: (Any) -> str
24
+ def get_name(coro: Any) -> str:
25
25
  return (
26
26
  getattr(coro, "__qualname__", None)
27
27
  or getattr(coro, "__name__", None)
@@ -29,18 +29,19 @@ def get_name(coro):
29
29
  )
30
30
 
31
31
 
32
- def patch_asyncio():
33
- # type: () -> None
32
+ def patch_asyncio() -> None:
34
33
  orig_task_factory = None
35
34
  try:
36
35
  loop = asyncio.get_running_loop()
37
36
  orig_task_factory = loop.get_task_factory()
38
37
 
39
- def _sentry_task_factory(loop, coro, **kwargs):
40
- # type: (asyncio.AbstractEventLoop, Coroutine[Any, Any, Any], Any) -> asyncio.Future[Any]
38
+ def _sentry_task_factory(
39
+ loop: asyncio.AbstractEventLoop,
40
+ coro: Coroutine[Any, Any, Any],
41
+ **kwargs: Any,
42
+ ) -> asyncio.Future[Any]:
41
43
 
42
- async def _task_with_sentry_span_creation():
43
- # type: () -> Any
44
+ async def _task_with_sentry_span_creation() -> Any:
44
45
  result = None
45
46
 
46
47
  with sentry_sdk.isolation_scope():
@@ -79,9 +80,8 @@ def patch_asyncio():
79
80
 
80
81
  # Set the task name to include the original coroutine's name
81
82
  try:
82
- cast("asyncio.Task[Any]", task).set_name(
83
- f"{get_name(coro)} (Sentry-wrapped)"
84
- )
83
+ if isinstance(task, asyncio.Task):
84
+ task.set_name(f"{get_name(coro)} (Sentry-wrapped)")
85
85
  except AttributeError:
86
86
  # set_name might not be available in all Python versions
87
87
  pass
@@ -100,8 +100,7 @@ def patch_asyncio():
100
100
  )
101
101
 
102
102
 
103
- def _capture_exception():
104
- # type: () -> ExcInfo
103
+ def _capture_exception() -> ExcInfo:
105
104
  exc_info = sys.exc_info()
106
105
 
107
106
  client = sentry_sdk.get_client()
@@ -123,6 +122,5 @@ class AsyncioIntegration(Integration):
123
122
  origin = f"auto.function.{identifier}"
124
123
 
125
124
  @staticmethod
126
- def setup_once():
127
- # type: () -> None
125
+ def setup_once() -> None:
128
126
  patch_asyncio()
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import os
2
3
  import sys
3
4
  import atexit
@@ -12,15 +13,13 @@ if TYPE_CHECKING:
12
13
  from typing import Optional
13
14
 
14
15
 
15
- def default_callback(pending, timeout):
16
- # type: (int, int) -> None
16
+ def default_callback(pending: int, timeout: int) -> None:
17
17
  """This is the default shutdown callback that is set on the options.
18
18
  It prints out a message to stderr that informs the user that some events
19
19
  are still pending and the process is waiting for them to flush out.
20
20
  """
21
21
 
22
- def echo(msg):
23
- # type: (str) -> None
22
+ def echo(msg: str) -> None:
24
23
  sys.stderr.write(msg + "\n")
25
24
 
26
25
  echo("Sentry is attempting to send %i pending events" % pending)
@@ -32,18 +31,15 @@ def default_callback(pending, timeout):
32
31
  class AtexitIntegration(Integration):
33
32
  identifier = "atexit"
34
33
 
35
- def __init__(self, callback=None):
36
- # type: (Optional[Any]) -> None
34
+ def __init__(self, callback: Optional[Any] = None) -> None:
37
35
  if callback is None:
38
36
  callback = default_callback
39
37
  self.callback = callback
40
38
 
41
39
  @staticmethod
42
- def setup_once():
43
- # type: () -> None
40
+ def setup_once() -> None:
44
41
  @atexit.register
45
- def _shutdown():
46
- # type: () -> None
42
+ def _shutdown() -> None:
47
43
  client = sentry_sdk.get_client()
48
44
  integration = client.get_integration(AtexitIntegration)
49
45
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import functools
2
3
  import json
3
4
  import re
@@ -54,11 +55,9 @@ CONTEXT_TO_ATTRIBUTES = {
54
55
  }
55
56
 
56
57
 
57
- def _wrap_init_error(init_error):
58
- # type: (F) -> F
58
+ def _wrap_init_error(init_error: F) -> F:
59
59
  @ensure_integration_enabled(AwsLambdaIntegration, init_error)
60
- def sentry_init_error(*args, **kwargs):
61
- # type: (*Any, **Any) -> Any
60
+ def sentry_init_error(*args: Any, **kwargs: Any) -> Any:
62
61
  client = sentry_sdk.get_client()
63
62
 
64
63
  with capture_internal_exceptions():
@@ -86,11 +85,11 @@ def _wrap_init_error(init_error):
86
85
  return sentry_init_error # type: ignore
87
86
 
88
87
 
89
- def _wrap_handler(handler):
90
- # type: (F) -> F
88
+ def _wrap_handler(handler: F) -> F:
91
89
  @functools.wraps(handler)
92
- def sentry_handler(aws_event, aws_context, *args, **kwargs):
93
- # type: (Any, Any, *Any, **Any) -> Any
90
+ def sentry_handler(
91
+ aws_event: Any, aws_context: Any, *args: Any, **kwargs: Any
92
+ ) -> Any:
94
93
 
95
94
  # Per https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html,
96
95
  # `event` here is *likely* a dictionary, but also might be a number of
@@ -192,8 +191,7 @@ def _wrap_handler(handler):
192
191
  return sentry_handler # type: ignore
193
192
 
194
193
 
195
- def _drain_queue():
196
- # type: () -> None
194
+ def _drain_queue() -> None:
197
195
  with capture_internal_exceptions():
198
196
  client = sentry_sdk.get_client()
199
197
  integration = client.get_integration(AwsLambdaIntegration)
@@ -207,13 +205,11 @@ class AwsLambdaIntegration(Integration):
207
205
  identifier = "aws_lambda"
208
206
  origin = f"auto.function.{identifier}"
209
207
 
210
- def __init__(self, timeout_warning=False):
211
- # type: (bool) -> None
208
+ def __init__(self, timeout_warning: bool = False) -> None:
212
209
  self.timeout_warning = timeout_warning
213
210
 
214
211
  @staticmethod
215
- def setup_once():
216
- # type: () -> None
212
+ def setup_once() -> None:
217
213
 
218
214
  lambda_bootstrap = get_lambda_bootstrap()
219
215
  if not lambda_bootstrap:
@@ -249,10 +245,8 @@ class AwsLambdaIntegration(Integration):
249
245
  # Patch the runtime client to drain the queue. This should work
250
246
  # even when the SDK is initialized inside of the handler
251
247
 
252
- def _wrap_post_function(f):
253
- # type: (F) -> F
254
- def inner(*args, **kwargs):
255
- # type: (*Any, **Any) -> Any
248
+ def _wrap_post_function(f: F) -> F:
249
+ def inner(*args: Any, **kwargs: Any) -> Any:
256
250
  _drain_queue()
257
251
  return f(*args, **kwargs)
258
252
 
@@ -270,8 +264,7 @@ class AwsLambdaIntegration(Integration):
270
264
  )
271
265
 
272
266
 
273
- def get_lambda_bootstrap():
274
- # type: () -> Optional[Any]
267
+ def get_lambda_bootstrap() -> Optional[Any]:
275
268
 
276
269
  # Python 3.7: If the bootstrap module is *already imported*, it is the
277
270
  # one we actually want to use (no idea what's in __main__)
@@ -307,12 +300,14 @@ def get_lambda_bootstrap():
307
300
  return None
308
301
 
309
302
 
310
- def _make_request_event_processor(aws_event, aws_context, configured_timeout):
311
- # type: (Any, Any, Any) -> EventProcessor
303
+ def _make_request_event_processor(
304
+ aws_event: Any, aws_context: Any, configured_timeout: Any
305
+ ) -> EventProcessor:
312
306
  start_time = datetime.now(timezone.utc)
313
307
 
314
- def event_processor(sentry_event, hint, start_time=start_time):
315
- # type: (Event, Hint, datetime) -> Optional[Event]
308
+ def event_processor(
309
+ sentry_event: Event, hint: Hint, start_time: datetime = start_time
310
+ ) -> Optional[Event]:
316
311
  remaining_time_in_milis = aws_context.get_remaining_time_in_millis()
317
312
  exec_duration = configured_timeout - remaining_time_in_milis
318
313
 
@@ -375,8 +370,7 @@ def _make_request_event_processor(aws_event, aws_context, configured_timeout):
375
370
  return event_processor
376
371
 
377
372
 
378
- def _get_url(aws_event, aws_context):
379
- # type: (Any, Any) -> str
373
+ def _get_url(aws_event: Any, aws_context: Any) -> str:
380
374
  path = aws_event.get("path", None)
381
375
 
382
376
  headers = aws_event.get("headers")
@@ -392,8 +386,7 @@ def _get_url(aws_event, aws_context):
392
386
  return "awslambda:///{}".format(aws_context.function_name)
393
387
 
394
388
 
395
- def _get_cloudwatch_logs_url(aws_context, start_time):
396
- # type: (Any, datetime) -> str
389
+ def _get_cloudwatch_logs_url(aws_context: Any, start_time: datetime) -> str:
397
390
  """
398
391
  Generates a CloudWatchLogs console URL based on the context object
399
392
 
@@ -424,8 +417,7 @@ def _get_cloudwatch_logs_url(aws_context, start_time):
424
417
  return url
425
418
 
426
419
 
427
- def _parse_formatted_traceback(formatted_tb):
428
- # type: (list[str]) -> list[dict[str, Any]]
420
+ def _parse_formatted_traceback(formatted_tb: list[str]) -> list[dict[str, Any]]:
429
421
  frames = []
430
422
  for frame in formatted_tb:
431
423
  match = re.match(r'File "(.+)", line (\d+), in (.+)', frame.strip())
@@ -446,8 +438,7 @@ def _parse_formatted_traceback(formatted_tb):
446
438
  return frames
447
439
 
448
440
 
449
- def _event_from_error_json(error_json):
450
- # type: (dict[str, Any]) -> Event
441
+ def _event_from_error_json(error_json: dict[str, Any]) -> Event:
451
442
  """
452
443
  Converts the error JSON from AWS Lambda into a Sentry error event.
453
444
  This is not a full fletched event, but better than nothing.
@@ -455,7 +446,7 @@ def _event_from_error_json(error_json):
455
446
  This is an example of where AWS creates the error JSON:
456
447
  https://github.com/aws/aws-lambda-python-runtime-interface-client/blob/2.2.1/awslambdaric/bootstrap.py#L479
457
448
  """
458
- event = {
449
+ event: Event = {
459
450
  "level": "error",
460
451
  "exception": {
461
452
  "values": [
@@ -474,13 +465,12 @@ def _event_from_error_json(error_json):
474
465
  }
475
466
  ],
476
467
  },
477
- } # type: Event
468
+ }
478
469
 
479
470
  return event
480
471
 
481
472
 
482
- def _prepopulate_attributes(aws_event, aws_context):
483
- # type: (Any, Any) -> dict[str, Any]
473
+ def _prepopulate_attributes(aws_event: Any, aws_context: Any) -> dict[str, Any]:
484
474
  attributes = {
485
475
  "cloud.provider": "aws",
486
476
  }