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 functools
2
3
  import os
3
4
  import sys
@@ -40,8 +41,7 @@ if TYPE_CHECKING:
40
41
 
41
42
  if getattr(Request, "authenticated_userid", None):
42
43
 
43
- def authenticated_userid(request):
44
- # type: (Request) -> Optional[Any]
44
+ def authenticated_userid(request: Request) -> Optional[Any]:
45
45
  return request.authenticated_userid
46
46
 
47
47
  else:
@@ -58,8 +58,7 @@ class PyramidIntegration(Integration):
58
58
 
59
59
  transaction_style = ""
60
60
 
61
- def __init__(self, transaction_style="route_name"):
62
- # type: (str) -> None
61
+ def __init__(self, transaction_style: str = "route_name") -> None:
63
62
  if transaction_style not in TRANSACTION_STYLE_VALUES:
64
63
  raise ValueError(
65
64
  "Invalid value for transaction_style: %s (must be in %s)"
@@ -68,15 +67,15 @@ class PyramidIntegration(Integration):
68
67
  self.transaction_style = transaction_style
69
68
 
70
69
  @staticmethod
71
- def setup_once():
72
- # type: () -> None
70
+ def setup_once() -> None:
73
71
  from pyramid import router
74
72
 
75
73
  old_call_view = router._call_view
76
74
 
77
75
  @functools.wraps(old_call_view)
78
- def sentry_patched_call_view(registry, request, *args, **kwargs):
79
- # type: (Any, Request, *Any, **Any) -> Response
76
+ def sentry_patched_call_view(
77
+ registry: Any, request: Request, *args: Any, **kwargs: Any
78
+ ) -> Response:
80
79
  integration = sentry_sdk.get_client().get_integration(PyramidIntegration)
81
80
  if integration is None:
82
81
  return old_call_view(registry, request, *args, **kwargs)
@@ -96,8 +95,9 @@ class PyramidIntegration(Integration):
96
95
  if hasattr(Request, "invoke_exception_view"):
97
96
  old_invoke_exception_view = Request.invoke_exception_view
98
97
 
99
- def sentry_patched_invoke_exception_view(self, *args, **kwargs):
100
- # type: (Request, *Any, **Any) -> Any
98
+ def sentry_patched_invoke_exception_view(
99
+ self: Request, *args: Any, **kwargs: Any
100
+ ) -> Any:
101
101
  rv = old_invoke_exception_view(self, *args, **kwargs)
102
102
 
103
103
  if (
@@ -116,10 +116,12 @@ class PyramidIntegration(Integration):
116
116
  old_wsgi_call = router.Router.__call__
117
117
 
118
118
  @ensure_integration_enabled(PyramidIntegration, old_wsgi_call)
119
- def sentry_patched_wsgi_call(self, environ, start_response):
120
- # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse
121
- def sentry_patched_inner_wsgi_call(environ, start_response):
122
- # type: (Dict[str, Any], Callable[..., Any]) -> Any
119
+ def sentry_patched_wsgi_call(
120
+ self: Any, environ: Dict[str, str], start_response: Callable[..., Any]
121
+ ) -> _ScopedResponse:
122
+ def sentry_patched_inner_wsgi_call(
123
+ environ: Dict[str, Any], start_response: Callable[..., Any]
124
+ ) -> Any:
123
125
  try:
124
126
  return old_wsgi_call(self, environ, start_response)
125
127
  except Exception:
@@ -137,8 +139,7 @@ class PyramidIntegration(Integration):
137
139
 
138
140
 
139
141
  @ensure_integration_enabled(PyramidIntegration)
140
- def _capture_exception(exc_info):
141
- # type: (ExcInfo) -> None
142
+ def _capture_exception(exc_info: ExcInfo) -> None:
142
143
  if exc_info[0] is None or issubclass(exc_info[0], HTTPException):
143
144
  return
144
145
 
@@ -151,8 +152,9 @@ def _capture_exception(exc_info):
151
152
  sentry_sdk.capture_event(event, hint=hint)
152
153
 
153
154
 
154
- def _set_transaction_name_and_source(scope, transaction_style, request):
155
- # type: (sentry_sdk.Scope, str, Request) -> None
155
+ def _set_transaction_name_and_source(
156
+ scope: sentry_sdk.Scope, transaction_style: str, request: Request
157
+ ) -> None:
156
158
  try:
157
159
  name_for_style = {
158
160
  "route_name": request.matched_route.name,
@@ -167,40 +169,33 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
167
169
 
168
170
 
169
171
  class PyramidRequestExtractor(RequestExtractor):
170
- def url(self):
171
- # type: () -> str
172
+ def url(self) -> str:
172
173
  return self.request.path_url
173
174
 
174
- def env(self):
175
- # type: () -> Dict[str, str]
175
+ def env(self) -> Dict[str, str]:
176
176
  return self.request.environ
177
177
 
178
- def cookies(self):
179
- # type: () -> RequestCookies
178
+ def cookies(self) -> RequestCookies:
180
179
  return self.request.cookies
181
180
 
182
- def raw_data(self):
183
- # type: () -> str
181
+ def raw_data(self) -> str:
184
182
  return self.request.text
185
183
 
186
- def form(self):
187
- # type: () -> Dict[str, str]
184
+ def form(self) -> Dict[str, str]:
188
185
  return {
189
186
  key: value
190
187
  for key, value in self.request.POST.items()
191
188
  if not getattr(value, "filename", None)
192
189
  }
193
190
 
194
- def files(self):
195
- # type: () -> Dict[str, _FieldStorageWithFile]
191
+ def files(self) -> Dict[str, _FieldStorageWithFile]:
196
192
  return {
197
193
  key: value
198
194
  for key, value in self.request.POST.items()
199
195
  if getattr(value, "filename", None)
200
196
  }
201
197
 
202
- def size_of_file(self, postdata):
203
- # type: (_FieldStorageWithFile) -> int
198
+ def size_of_file(self, postdata: _FieldStorageWithFile) -> int:
204
199
  file = postdata.file
205
200
  try:
206
201
  return os.fstat(file.fileno()).st_size
@@ -208,10 +203,10 @@ class PyramidRequestExtractor(RequestExtractor):
208
203
  return 0
209
204
 
210
205
 
211
- def _make_event_processor(weak_request, integration):
212
- # type: (Callable[[], Request], PyramidIntegration) -> EventProcessor
213
- def pyramid_event_processor(event, hint):
214
- # type: (Event, Dict[str, Any]) -> Event
206
+ def _make_event_processor(
207
+ weak_request: Callable[[], Request], integration: PyramidIntegration
208
+ ) -> EventProcessor:
209
+ def pyramid_event_processor(event: Event, hint: Dict[str, Any]) -> Event:
215
210
  request = weak_request()
216
211
  if request is None:
217
212
  return event
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import asyncio
2
3
  import inspect
3
4
  from functools import wraps
@@ -60,8 +61,7 @@ class QuartIntegration(Integration):
60
61
 
61
62
  transaction_style = ""
62
63
 
63
- def __init__(self, transaction_style="endpoint"):
64
- # type: (str) -> None
64
+ def __init__(self, transaction_style: str = "endpoint") -> None:
65
65
  if transaction_style not in TRANSACTION_STYLE_VALUES:
66
66
  raise ValueError(
67
67
  "Invalid value for transaction_style: %s (must be in %s)"
@@ -70,8 +70,7 @@ class QuartIntegration(Integration):
70
70
  self.transaction_style = transaction_style
71
71
 
72
72
  @staticmethod
73
- def setup_once():
74
- # type: () -> None
73
+ def setup_once() -> None:
75
74
 
76
75
  request_started.connect(_request_websocket_started)
77
76
  websocket_started.connect(_request_websocket_started)
@@ -83,12 +82,12 @@ class QuartIntegration(Integration):
83
82
  patch_scaffold_route()
84
83
 
85
84
 
86
- def patch_asgi_app():
87
- # type: () -> None
85
+ def patch_asgi_app() -> None:
88
86
  old_app = Quart.__call__
89
87
 
90
- async def sentry_patched_asgi_app(self, scope, receive, send):
91
- # type: (Any, Any, Any, Any) -> Any
88
+ async def sentry_patched_asgi_app(
89
+ self: Any, scope: Any, receive: Any, send: Any
90
+ ) -> Any:
92
91
  if sentry_sdk.get_client().get_integration(QuartIntegration) is None:
93
92
  return await old_app(self, scope, receive, send)
94
93
 
@@ -102,16 +101,13 @@ def patch_asgi_app():
102
101
  Quart.__call__ = sentry_patched_asgi_app
103
102
 
104
103
 
105
- def patch_scaffold_route():
106
- # type: () -> None
104
+ def patch_scaffold_route() -> None:
107
105
  old_route = Scaffold.route
108
106
 
109
- def _sentry_route(*args, **kwargs):
110
- # type: (*Any, **Any) -> Any
107
+ def _sentry_route(*args: Any, **kwargs: Any) -> Any:
111
108
  old_decorator = old_route(*args, **kwargs)
112
109
 
113
- def decorator(old_func):
114
- # type: (Any) -> Any
110
+ def decorator(old_func: Any) -> Any:
115
111
 
116
112
  if inspect.isfunction(old_func) and not asyncio.iscoroutinefunction(
117
113
  old_func
@@ -119,8 +115,7 @@ def patch_scaffold_route():
119
115
 
120
116
  @wraps(old_func)
121
117
  @ensure_integration_enabled(QuartIntegration, old_func)
122
- def _sentry_func(*args, **kwargs):
123
- # type: (*Any, **Any) -> Any
118
+ def _sentry_func(*args: Any, **kwargs: Any) -> Any:
124
119
  current_scope = sentry_sdk.get_current_scope()
125
120
  if current_scope.root_span is not None:
126
121
  current_scope.root_span.update_active_thread()
@@ -140,8 +135,9 @@ def patch_scaffold_route():
140
135
  Scaffold.route = _sentry_route
141
136
 
142
137
 
143
- def _set_transaction_name_and_source(scope, transaction_style, request):
144
- # type: (sentry_sdk.Scope, str, Request) -> None
138
+ def _set_transaction_name_and_source(
139
+ scope: sentry_sdk.Scope, transaction_style: str, request: Request
140
+ ) -> None:
145
141
 
146
142
  try:
147
143
  name_for_style = {
@@ -156,8 +152,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
156
152
  pass
157
153
 
158
154
 
159
- async def _request_websocket_started(app, **kwargs):
160
- # type: (Quart, **Any) -> None
155
+ async def _request_websocket_started(app: Quart, **kwargs: Any) -> None:
161
156
  integration = sentry_sdk.get_client().get_integration(QuartIntegration)
162
157
  if integration is None:
163
158
  return
@@ -178,10 +173,10 @@ async def _request_websocket_started(app, **kwargs):
178
173
  scope.add_event_processor(evt_processor)
179
174
 
180
175
 
181
- def _make_request_event_processor(app, request, integration):
182
- # type: (Quart, Request, QuartIntegration) -> EventProcessor
183
- def inner(event, hint):
184
- # type: (Event, dict[str, Any]) -> Event
176
+ def _make_request_event_processor(
177
+ app: Quart, request: Request, integration: QuartIntegration
178
+ ) -> EventProcessor:
179
+ def inner(event: Event, hint: dict[str, Any]) -> Event:
185
180
  # if the request is gone we are fine not logging the data from
186
181
  # it. This might happen if the processor is pushed away to
187
182
  # another thread.
@@ -207,8 +202,9 @@ def _make_request_event_processor(app, request, integration):
207
202
  return inner
208
203
 
209
204
 
210
- async def _capture_exception(sender, exception, **kwargs):
211
- # type: (Quart, Union[ValueError, BaseException], **Any) -> None
205
+ async def _capture_exception(
206
+ sender: Quart, exception: Union[ValueError, BaseException], **kwargs: Any
207
+ ) -> None:
212
208
  integration = sentry_sdk.get_client().get_integration(QuartIntegration)
213
209
  if integration is None:
214
210
  return
@@ -222,8 +218,7 @@ async def _capture_exception(sender, exception, **kwargs):
222
218
  sentry_sdk.capture_event(event, hint=hint)
223
219
 
224
220
 
225
- def _add_user_to_event(event):
226
- # type: (Event) -> None
221
+ def _add_user_to_event(event: Event) -> None:
227
222
  if quart_auth is None:
228
223
  return
229
224
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import inspect
2
3
  import sys
3
4
 
@@ -29,8 +30,7 @@ if TYPE_CHECKING:
29
30
  DEFAULT_TRANSACTION_NAME = "unknown Ray function"
30
31
 
31
32
 
32
- def _check_sentry_initialized():
33
- # type: () -> None
33
+ def _check_sentry_initialized() -> None:
34
34
  if sentry_sdk.get_client().is_active():
35
35
  return
36
36
 
@@ -39,88 +39,98 @@ def _check_sentry_initialized():
39
39
  )
40
40
 
41
41
 
42
- def _patch_ray_remote():
43
- # type: () -> None
42
+ def _patch_ray_remote() -> None:
44
43
  old_remote = ray.remote
45
44
 
46
45
  @functools.wraps(old_remote)
47
- def new_remote(f, *args, **kwargs):
48
- # type: (Callable[..., Any], *Any, **Any) -> Callable[..., Any]
46
+ def new_remote(
47
+ f: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any
48
+ ) -> Callable[..., Any]:
49
+
49
50
  if inspect.isclass(f):
50
51
  # Ray Actors
51
52
  # (https://docs.ray.io/en/latest/ray-core/actors.html)
52
53
  # are not supported
53
54
  # (Only Ray Tasks are supported)
54
- return old_remote(f, *args, *kwargs)
55
-
56
- def _f(*f_args, _tracing=None, **f_kwargs):
57
- # type: (Any, Optional[dict[str, Any]], Any) -> Any
58
- """
59
- Ray Worker
60
- """
61
- _check_sentry_initialized()
62
-
63
- root_span_name = qualname_from_function(f) or DEFAULT_TRANSACTION_NAME
64
- sentry_sdk.get_current_scope().set_transaction_name(
65
- root_span_name,
66
- source=TransactionSource.TASK,
67
- )
68
- with sentry_sdk.continue_trace(_tracing or {}):
55
+ return old_remote(f, *args, **kwargs)
56
+
57
+ def wrapper(user_f: Callable[..., Any]) -> Any:
58
+ def new_func(
59
+ *f_args: Any, _tracing: Optional[dict[str, Any]] = None, **f_kwargs: Any
60
+ ) -> Any:
61
+ _check_sentry_initialized()
62
+
63
+ root_span_name = (
64
+ qualname_from_function(user_f) or DEFAULT_TRANSACTION_NAME
65
+ )
66
+ sentry_sdk.get_current_scope().set_transaction_name(
67
+ root_span_name,
68
+ source=TransactionSource.TASK,
69
+ )
70
+ with sentry_sdk.continue_trace(_tracing or {}):
71
+ with sentry_sdk.start_span(
72
+ op=OP.QUEUE_TASK_RAY,
73
+ name=qualname_from_function(user_f),
74
+ origin=RayIntegration.origin,
75
+ source=TransactionSource.TASK,
76
+ ) as root_span:
77
+ try:
78
+ result = user_f(*f_args, **f_kwargs)
79
+ root_span.set_status(SPANSTATUS.OK)
80
+ except Exception:
81
+ root_span.set_status(SPANSTATUS.INTERNAL_ERROR)
82
+ exc_info = sys.exc_info()
83
+ _capture_exception(exc_info)
84
+ reraise(*exc_info)
85
+
86
+ return result
87
+
88
+ if f:
89
+ rv = old_remote(new_func)
90
+ else:
91
+ rv = old_remote(*args, **kwargs)(new_func)
92
+ old_remote_method = rv.remote
93
+
94
+ def _remote_method_with_header_propagation(
95
+ *args: Any, **kwargs: Any
96
+ ) -> Any:
97
+ """
98
+ Ray Client
99
+ """
69
100
  with sentry_sdk.start_span(
70
- op=OP.QUEUE_TASK_RAY,
71
- name=root_span_name,
101
+ op=OP.QUEUE_SUBMIT_RAY,
102
+ name=qualname_from_function(user_f),
72
103
  origin=RayIntegration.origin,
73
- source=TransactionSource.TASK,
74
- ) as root_span:
104
+ only_if_parent=True,
105
+ ) as span:
106
+ tracing = {
107
+ k: v
108
+ for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers()
109
+ }
75
110
  try:
76
- result = f(*f_args, **f_kwargs)
77
- root_span.set_status(SPANSTATUS.OK)
111
+ result = old_remote_method(*args, **kwargs, _tracing=tracing)
112
+ span.set_status(SPANSTATUS.OK)
78
113
  except Exception:
79
- root_span.set_status(SPANSTATUS.INTERNAL_ERROR)
114
+ span.set_status(SPANSTATUS.INTERNAL_ERROR)
80
115
  exc_info = sys.exc_info()
81
116
  _capture_exception(exc_info)
82
117
  reraise(*exc_info)
83
118
 
84
119
  return result
85
120
 
86
- rv = old_remote(_f, *args, *kwargs)
87
- old_remote_method = rv.remote
88
-
89
- def _remote_method_with_header_propagation(*args, **kwargs):
90
- # type: (*Any, **Any) -> Any
91
- """
92
- Ray Client
93
- """
94
- with sentry_sdk.start_span(
95
- op=OP.QUEUE_SUBMIT_RAY,
96
- name=qualname_from_function(f),
97
- origin=RayIntegration.origin,
98
- only_if_parent=True,
99
- ) as span:
100
- tracing = {
101
- k: v
102
- for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers()
103
- }
104
- try:
105
- result = old_remote_method(*args, **kwargs, _tracing=tracing)
106
- span.set_status(SPANSTATUS.OK)
107
- except Exception:
108
- span.set_status(SPANSTATUS.INTERNAL_ERROR)
109
- exc_info = sys.exc_info()
110
- _capture_exception(exc_info)
111
- reraise(*exc_info)
112
-
113
- return result
114
-
115
- rv.remote = _remote_method_with_header_propagation
116
-
117
- return rv
121
+ rv.remote = _remote_method_with_header_propagation
122
+
123
+ return rv
124
+
125
+ if f is not None:
126
+ return wrapper(f)
127
+ else:
128
+ return wrapper
118
129
 
119
130
  ray.remote = new_remote
120
131
 
121
132
 
122
- def _capture_exception(exc_info, **kwargs):
123
- # type: (ExcInfo, **Any) -> None
133
+ def _capture_exception(exc_info: ExcInfo, **kwargs: Any) -> None:
124
134
  client = sentry_sdk.get_client()
125
135
 
126
136
  event, hint = event_from_exception(
@@ -139,8 +149,7 @@ class RayIntegration(Integration):
139
149
  origin = f"auto.queue.{identifier}"
140
150
 
141
151
  @staticmethod
142
- def setup_once():
143
- # type: () -> None
152
+ def setup_once() -> None:
144
153
  version = package_version("ray")
145
154
  _check_minimum_version(RayIntegration, version)
146
155
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from sentry_sdk.integrations import Integration, DidNotEnable
2
3
  from sentry_sdk.integrations.redis.consts import _DEFAULT_MAX_DATA_SIZE
3
4
  from sentry_sdk.integrations.redis.rb import _patch_rb
@@ -15,14 +16,16 @@ if TYPE_CHECKING:
15
16
  class RedisIntegration(Integration):
16
17
  identifier = "redis"
17
18
 
18
- def __init__(self, max_data_size=_DEFAULT_MAX_DATA_SIZE, cache_prefixes=None):
19
- # type: (int, Optional[list[str]]) -> None
19
+ def __init__(
20
+ self,
21
+ max_data_size: int = _DEFAULT_MAX_DATA_SIZE,
22
+ cache_prefixes: Optional[list[str]] = None,
23
+ ) -> None:
20
24
  self.max_data_size = max_data_size
21
25
  self.cache_prefixes = cache_prefixes if cache_prefixes is not None else []
22
26
 
23
27
  @staticmethod
24
- def setup_once():
25
- # type: () -> None
28
+ def setup_once() -> None:
26
29
  try:
27
30
  from redis import StrictRedis, client
28
31
  except ImportError:
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sentry_sdk
2
3
  from sentry_sdk.consts import OP
3
4
  from sentry_sdk.integrations.redis.consts import SPAN_ORIGIN
@@ -24,15 +25,16 @@ if TYPE_CHECKING:
24
25
 
25
26
 
26
27
  def patch_redis_async_pipeline(
27
- pipeline_cls, is_cluster, get_command_args_fn, get_db_data_fn
28
- ):
29
- # type: (Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]], bool, Any, Callable[[Any], dict[str, Any]]) -> None
28
+ pipeline_cls: Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]],
29
+ is_cluster: bool,
30
+ get_command_args_fn: Any,
31
+ get_db_data_fn: Callable[[Any], dict[str, Any]],
32
+ ) -> None:
30
33
  old_execute = pipeline_cls.execute
31
34
 
32
35
  from sentry_sdk.integrations.redis import RedisIntegration
33
36
 
34
- async def _sentry_execute(self, *args, **kwargs):
35
- # type: (Any, *Any, **Any) -> Any
37
+ async def _sentry_execute(self: Any, *args: Any, **kwargs: Any) -> Any:
36
38
  if sentry_sdk.get_client().get_integration(RedisIntegration) is None:
37
39
  return await old_execute(self, *args, **kwargs)
38
40
 
@@ -44,13 +46,20 @@ def patch_redis_async_pipeline(
44
46
  ) as span:
45
47
  with capture_internal_exceptions():
46
48
  span_data = get_db_data_fn(self)
49
+
50
+ try:
51
+ command_seq = self._execution_strategy._command_queue
52
+ except AttributeError:
53
+ if is_cluster:
54
+ command_seq = self._command_stack
55
+ else:
56
+ command_seq = self.command_stack
57
+
47
58
  pipeline_data = _get_pipeline_data(
48
59
  is_cluster=is_cluster,
49
60
  get_command_args_fn=get_command_args_fn,
50
61
  is_transaction=False if is_cluster else self.is_transaction,
51
- command_stack=(
52
- self._command_stack if is_cluster else self.command_stack
53
- ),
62
+ command_seq=command_seq,
54
63
  )
55
64
  _update_span(span, span_data, pipeline_data)
56
65
  _create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)
@@ -60,14 +69,18 @@ def patch_redis_async_pipeline(
60
69
  pipeline_cls.execute = _sentry_execute # type: ignore
61
70
 
62
71
 
63
- def patch_redis_async_client(cls, is_cluster, get_db_data_fn):
64
- # type: (Union[type[StrictRedis[Any]], type[RedisCluster[Any]]], bool, Callable[[Any], dict[str, Any]]) -> None
72
+ def patch_redis_async_client(
73
+ cls: Union[type[StrictRedis[Any]], type[RedisCluster[Any]]],
74
+ is_cluster: bool,
75
+ get_db_data_fn: Callable[[Any], dict[str, Any]],
76
+ ) -> None:
65
77
  old_execute_command = cls.execute_command
66
78
 
67
79
  from sentry_sdk.integrations.redis import RedisIntegration
68
80
 
69
- async def _sentry_execute_command(self, name, *args, **kwargs):
70
- # type: (Any, str, *Any, **Any) -> Any
81
+ async def _sentry_execute_command(
82
+ self: Any, name: str, *args: Any, **kwargs: Any
83
+ ) -> Any:
71
84
  integration = sentry_sdk.get_client().get_integration(RedisIntegration)
72
85
  if integration is None:
73
86
  return await old_execute_command(self, name, *args, **kwargs)
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sentry_sdk
2
3
  from sentry_sdk.consts import OP
3
4
  from sentry_sdk.integrations.redis.consts import SPAN_ORIGIN
@@ -22,18 +23,16 @@ if TYPE_CHECKING:
22
23
 
23
24
 
24
25
  def patch_redis_pipeline(
25
- pipeline_cls,
26
- is_cluster,
27
- get_command_args_fn,
28
- get_db_data_fn,
29
- ):
30
- # type: (Any, bool, Any, Callable[[Any], dict[str, Any]]) -> None
26
+ pipeline_cls: Any,
27
+ is_cluster: bool,
28
+ get_command_args_fn: Any,
29
+ get_db_data_fn: Callable[[Any], dict[str, Any]],
30
+ ) -> None:
31
31
  old_execute = pipeline_cls.execute
32
32
 
33
33
  from sentry_sdk.integrations.redis import RedisIntegration
34
34
 
35
- def sentry_patched_execute(self, *args, **kwargs):
36
- # type: (Any, *Any, **Any) -> Any
35
+ def sentry_patched_execute(self: Any, *args: Any, **kwargs: Any) -> Any:
37
36
  if sentry_sdk.get_client().get_integration(RedisIntegration) is None:
38
37
  return old_execute(self, *args, **kwargs)
39
38
 
@@ -44,12 +43,17 @@ def patch_redis_pipeline(
44
43
  only_if_parent=True,
45
44
  ) as span:
46
45
  with capture_internal_exceptions():
46
+ try:
47
+ command_seq = self._execution_strategy.command_queue
48
+ except AttributeError:
49
+ command_seq = self.command_stack
50
+
47
51
  span_data = get_db_data_fn(self)
48
52
  pipeline_data = _get_pipeline_data(
49
53
  is_cluster=is_cluster,
50
54
  get_command_args_fn=get_command_args_fn,
51
55
  is_transaction=False if is_cluster else self.transaction,
52
- command_stack=self.command_stack,
56
+ command_seq=command_seq,
53
57
  )
54
58
  _update_span(span, span_data, pipeline_data)
55
59
  _create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)
@@ -59,8 +63,9 @@ def patch_redis_pipeline(
59
63
  pipeline_cls.execute = sentry_patched_execute
60
64
 
61
65
 
62
- def patch_redis_client(cls, is_cluster, get_db_data_fn):
63
- # type: (Any, bool, Callable[[Any], dict[str, Any]]) -> None
66
+ def patch_redis_client(
67
+ cls: Any, is_cluster: bool, get_db_data_fn: Callable[[Any], dict[str, Any]]
68
+ ) -> None:
64
69
  """
65
70
  This function can be used to instrument custom redis client classes or
66
71
  subclasses.
@@ -69,8 +74,9 @@ def patch_redis_client(cls, is_cluster, get_db_data_fn):
69
74
 
70
75
  from sentry_sdk.integrations.redis import RedisIntegration
71
76
 
72
- def sentry_patched_execute_command(self, name, *args, **kwargs):
73
- # type: (Any, str, *Any, **Any) -> Any
77
+ def sentry_patched_execute_command(
78
+ self: Any, name: str, *args: Any, **kwargs: Any
79
+ ) -> Any:
74
80
  integration = sentry_sdk.get_client().get_integration(RedisIntegration)
75
81
  if integration is None:
76
82
  return old_execute_command(self, name, *args, **kwargs)