sentry-sdk 3.0.0a2__py2.py3-none-any.whl → 3.0.0a4__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 (159) hide show
  1. sentry_sdk/__init__.py +4 -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 +45 -33
  10. sentry_sdk/ai/utils.py +8 -5
  11. sentry_sdk/api.py +91 -87
  12. sentry_sdk/attachments.py +10 -12
  13. sentry_sdk/client.py +119 -159
  14. sentry_sdk/consts.py +432 -223
  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 +33 -31
  24. sentry_sdk/integrations/anthropic.py +43 -38
  25. sentry_sdk/integrations/argv.py +3 -4
  26. sentry_sdk/integrations/ariadne.py +16 -18
  27. sentry_sdk/integrations/arq.py +20 -29
  28. sentry_sdk/integrations/asgi.py +63 -37
  29. sentry_sdk/integrations/asyncio.py +15 -17
  30. sentry_sdk/integrations/asyncpg.py +1 -1
  31. sentry_sdk/integrations/atexit.py +6 -10
  32. sentry_sdk/integrations/aws_lambda.py +26 -36
  33. sentry_sdk/integrations/beam.py +10 -18
  34. sentry_sdk/integrations/boto3.py +20 -18
  35. sentry_sdk/integrations/bottle.py +25 -34
  36. sentry_sdk/integrations/celery/__init__.py +40 -59
  37. sentry_sdk/integrations/celery/beat.py +22 -26
  38. sentry_sdk/integrations/celery/utils.py +15 -17
  39. sentry_sdk/integrations/chalice.py +8 -10
  40. sentry_sdk/integrations/clickhouse_driver.py +22 -32
  41. sentry_sdk/integrations/cloud_resource_context.py +9 -16
  42. sentry_sdk/integrations/cohere.py +19 -25
  43. sentry_sdk/integrations/dedupe.py +5 -8
  44. sentry_sdk/integrations/django/__init__.py +69 -74
  45. sentry_sdk/integrations/django/asgi.py +25 -33
  46. sentry_sdk/integrations/django/caching.py +24 -20
  47. sentry_sdk/integrations/django/middleware.py +18 -21
  48. sentry_sdk/integrations/django/signals_handlers.py +12 -11
  49. sentry_sdk/integrations/django/templates.py +21 -18
  50. sentry_sdk/integrations/django/transactions.py +16 -11
  51. sentry_sdk/integrations/django/views.py +8 -12
  52. sentry_sdk/integrations/dramatiq.py +21 -21
  53. sentry_sdk/integrations/excepthook.py +10 -10
  54. sentry_sdk/integrations/executing.py +3 -4
  55. sentry_sdk/integrations/falcon.py +27 -42
  56. sentry_sdk/integrations/fastapi.py +13 -16
  57. sentry_sdk/integrations/flask.py +31 -38
  58. sentry_sdk/integrations/gcp.py +13 -16
  59. sentry_sdk/integrations/gnu_backtrace.py +7 -20
  60. sentry_sdk/integrations/gql.py +16 -17
  61. sentry_sdk/integrations/graphene.py +14 -13
  62. sentry_sdk/integrations/grpc/__init__.py +3 -2
  63. sentry_sdk/integrations/grpc/aio/client.py +2 -2
  64. sentry_sdk/integrations/grpc/aio/server.py +15 -14
  65. sentry_sdk/integrations/grpc/client.py +21 -11
  66. sentry_sdk/integrations/grpc/consts.py +2 -0
  67. sentry_sdk/integrations/grpc/server.py +12 -8
  68. sentry_sdk/integrations/httpx.py +11 -14
  69. sentry_sdk/integrations/huey.py +14 -21
  70. sentry_sdk/integrations/huggingface_hub.py +17 -17
  71. sentry_sdk/integrations/langchain.py +204 -114
  72. sentry_sdk/integrations/launchdarkly.py +13 -10
  73. sentry_sdk/integrations/litestar.py +40 -38
  74. sentry_sdk/integrations/logging.py +29 -36
  75. sentry_sdk/integrations/loguru.py +16 -20
  76. sentry_sdk/integrations/modules.py +3 -4
  77. sentry_sdk/integrations/openai.py +421 -204
  78. sentry_sdk/integrations/openai_agents/__init__.py +49 -0
  79. sentry_sdk/integrations/openai_agents/consts.py +1 -0
  80. sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
  81. sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
  82. sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
  83. sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
  84. sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
  85. sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
  86. sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
  87. sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
  88. sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
  89. sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
  90. sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
  91. sentry_sdk/integrations/openai_agents/utils.py +153 -0
  92. sentry_sdk/integrations/openfeature.py +12 -8
  93. sentry_sdk/integrations/pure_eval.py +6 -10
  94. sentry_sdk/integrations/pymongo.py +14 -18
  95. sentry_sdk/integrations/pyramid.py +31 -36
  96. sentry_sdk/integrations/quart.py +23 -28
  97. sentry_sdk/integrations/ray.py +73 -64
  98. sentry_sdk/integrations/redis/__init__.py +7 -4
  99. sentry_sdk/integrations/redis/_async_common.py +18 -12
  100. sentry_sdk/integrations/redis/_sync_common.py +16 -15
  101. sentry_sdk/integrations/redis/modules/caches.py +17 -8
  102. sentry_sdk/integrations/redis/modules/queries.py +9 -8
  103. sentry_sdk/integrations/redis/rb.py +3 -2
  104. sentry_sdk/integrations/redis/redis.py +4 -4
  105. sentry_sdk/integrations/redis/redis_cluster.py +10 -8
  106. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  107. sentry_sdk/integrations/redis/utils.py +21 -22
  108. sentry_sdk/integrations/rq.py +13 -16
  109. sentry_sdk/integrations/rust_tracing.py +10 -7
  110. sentry_sdk/integrations/sanic.py +34 -46
  111. sentry_sdk/integrations/serverless.py +22 -27
  112. sentry_sdk/integrations/socket.py +29 -17
  113. sentry_sdk/integrations/spark/__init__.py +1 -0
  114. sentry_sdk/integrations/spark/spark_driver.py +45 -83
  115. sentry_sdk/integrations/spark/spark_worker.py +7 -11
  116. sentry_sdk/integrations/sqlalchemy.py +22 -19
  117. sentry_sdk/integrations/starlette.py +89 -93
  118. sentry_sdk/integrations/starlite.py +31 -37
  119. sentry_sdk/integrations/statsig.py +5 -4
  120. sentry_sdk/integrations/stdlib.py +32 -28
  121. sentry_sdk/integrations/strawberry.py +63 -50
  122. sentry_sdk/integrations/sys_exit.py +7 -11
  123. sentry_sdk/integrations/threading.py +13 -15
  124. sentry_sdk/integrations/tornado.py +28 -32
  125. sentry_sdk/integrations/trytond.py +4 -3
  126. sentry_sdk/integrations/typer.py +8 -6
  127. sentry_sdk/integrations/unleash.py +5 -4
  128. sentry_sdk/integrations/wsgi.py +47 -46
  129. sentry_sdk/logger.py +13 -9
  130. sentry_sdk/monitor.py +16 -28
  131. sentry_sdk/opentelemetry/consts.py +11 -4
  132. sentry_sdk/opentelemetry/contextvars_context.py +17 -15
  133. sentry_sdk/opentelemetry/propagator.py +38 -21
  134. sentry_sdk/opentelemetry/sampler.py +51 -34
  135. sentry_sdk/opentelemetry/scope.py +46 -37
  136. sentry_sdk/opentelemetry/span_processor.py +43 -59
  137. sentry_sdk/opentelemetry/tracing.py +32 -12
  138. sentry_sdk/opentelemetry/utils.py +180 -196
  139. sentry_sdk/profiler/continuous_profiler.py +108 -97
  140. sentry_sdk/profiler/transaction_profiler.py +70 -97
  141. sentry_sdk/profiler/utils.py +11 -15
  142. sentry_sdk/scope.py +251 -264
  143. sentry_sdk/scrubber.py +22 -26
  144. sentry_sdk/serializer.py +48 -65
  145. sentry_sdk/session.py +44 -61
  146. sentry_sdk/sessions.py +35 -49
  147. sentry_sdk/spotlight.py +15 -21
  148. sentry_sdk/tracing.py +118 -184
  149. sentry_sdk/tracing_utils.py +103 -123
  150. sentry_sdk/transport.py +131 -157
  151. sentry_sdk/utils.py +278 -309
  152. sentry_sdk/worker.py +16 -28
  153. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
  154. sentry_sdk-3.0.0a4.dist-info/RECORD +168 -0
  155. sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
  156. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
  157. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
  158. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
  159. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/top_level.txt +0 -0
@@ -1,26 +1,25 @@
1
+ from __future__ import annotations
1
2
  import urllib
2
3
 
3
4
  from sentry_sdk.scope import should_send_default_pii
4
5
  from sentry_sdk.integrations._wsgi_common import _filter_headers
5
6
 
6
- from typing import TYPE_CHECKING, cast
7
+ from typing import TYPE_CHECKING
7
8
 
8
9
  if TYPE_CHECKING:
9
10
  from typing import Any
10
11
  from typing import Dict
11
12
  from typing import Optional
12
13
  from typing import Union
13
- from typing_extensions import Literal
14
14
 
15
15
  from sentry_sdk.utils import AnnotatedValue
16
16
 
17
17
 
18
- def _get_headers(asgi_scope):
19
- # type: (Any) -> Dict[str, str]
18
+ def _get_headers(asgi_scope: Any) -> Dict[str, str]:
20
19
  """
21
20
  Extract headers from the ASGI scope, in the format that the Sentry protocol expects.
22
21
  """
23
- headers = {} # type: Dict[str, str]
22
+ headers: Dict[str, str] = {}
24
23
  for raw_key, raw_value in asgi_scope.get("headers", {}):
25
24
  key = raw_key.decode("latin-1")
26
25
  value = raw_value.decode("latin-1")
@@ -32,12 +31,16 @@ def _get_headers(asgi_scope):
32
31
  return headers
33
32
 
34
33
 
35
- def _get_url(asgi_scope, default_scheme=None, host=None):
36
- # type: (Dict[str, Any], Optional[Literal["ws", "http"]], Optional[Union[AnnotatedValue, str]]) -> str
34
+ def _get_url(
35
+ asgi_scope: Dict[str, Any],
36
+ host: Optional[Union[AnnotatedValue, str]] = None,
37
+ ) -> str:
37
38
  """
38
39
  Extract URL from the ASGI scope, without also including the querystring.
39
40
  """
40
- scheme = cast(str, asgi_scope.get("scheme", default_scheme))
41
+ scheme = asgi_scope.get(
42
+ "scheme", "http" if asgi_scope.get("type") == "http" else "ws"
43
+ )
41
44
  server = asgi_scope.get("server", None)
42
45
  path = asgi_scope.get("root_path", "") + asgi_scope.get("path", "")
43
46
 
@@ -53,8 +56,7 @@ def _get_url(asgi_scope, default_scheme=None, host=None):
53
56
  return path
54
57
 
55
58
 
56
- def _get_query(asgi_scope):
57
- # type: (Any) -> Any
59
+ def _get_query(asgi_scope: Any) -> Any:
58
60
  """
59
61
  Extract querystring from the ASGI scope, in the format that the Sentry protocol expects.
60
62
  """
@@ -64,8 +66,7 @@ def _get_query(asgi_scope):
64
66
  return urllib.parse.unquote(qs.decode("latin-1"))
65
67
 
66
68
 
67
- def _get_ip(asgi_scope):
68
- # type: (Any) -> str
69
+ def _get_ip(asgi_scope: Any) -> str:
69
70
  """
70
71
  Extract IP Address from the ASGI scope based on request headers with fallback to scope client.
71
72
  """
@@ -83,12 +84,11 @@ def _get_ip(asgi_scope):
83
84
  return asgi_scope.get("client")[0]
84
85
 
85
86
 
86
- def _get_request_data(asgi_scope):
87
- # type: (Any) -> Dict[str, Any]
87
+ def _get_request_data(asgi_scope: Any) -> Dict[str, Any]:
88
88
  """
89
89
  Returns data related to the HTTP request from the ASGI scope.
90
90
  """
91
- request_data = {} # type: Dict[str, Any]
91
+ request_data: Dict[str, Any] = {}
92
92
  ty = asgi_scope["type"]
93
93
  if ty in ("http", "websocket"):
94
94
  request_data["method"] = asgi_scope.get("method")
@@ -96,9 +96,7 @@ def _get_request_data(asgi_scope):
96
96
  request_data["headers"] = headers = _filter_headers(_get_headers(asgi_scope))
97
97
  request_data["query_string"] = _get_query(asgi_scope)
98
98
 
99
- request_data["url"] = _get_url(
100
- asgi_scope, "http" if ty == "http" else "ws", headers.get("host")
101
- )
99
+ request_data["url"] = _get_url(asgi_scope, headers.get("host"))
102
100
 
103
101
  client = asgi_scope.get("client")
104
102
  if client and should_send_default_pii():
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import json
2
3
  from copy import deepcopy
3
4
 
@@ -50,8 +51,9 @@ DEFAULT_HTTP_METHODS_TO_CAPTURE = (
50
51
  )
51
52
 
52
53
 
53
- def request_body_within_bounds(client, content_length):
54
- # type: (Optional[sentry_sdk.client.BaseClient], int) -> bool
54
+ def request_body_within_bounds(
55
+ client: Optional[sentry_sdk.client.BaseClient], content_length: int
56
+ ) -> bool:
55
57
  if client is None:
56
58
  return False
57
59
 
@@ -73,17 +75,15 @@ class RequestExtractor:
73
75
  # it. Only some child classes implement all methods that raise
74
76
  # NotImplementedError in this class.
75
77
 
76
- def __init__(self, request):
77
- # type: (Any) -> None
78
+ def __init__(self, request: Any) -> None:
78
79
  self.request = request
79
80
 
80
- def extract_into_event(self, event):
81
- # type: (Event) -> None
81
+ def extract_into_event(self, event: Event) -> None:
82
82
  client = sentry_sdk.get_client()
83
83
  if not client.is_active():
84
84
  return
85
85
 
86
- data = None # type: Optional[Union[AnnotatedValue, Dict[str, Any]]]
86
+ data: Optional[Union[AnnotatedValue, Dict[str, Any]]] = None
87
87
 
88
88
  content_length = self.content_length()
89
89
  request_info = event.get("request", {})
@@ -119,27 +119,22 @@ class RequestExtractor:
119
119
 
120
120
  event["request"] = deepcopy(request_info)
121
121
 
122
- def content_length(self):
123
- # type: () -> int
122
+ def content_length(self) -> int:
124
123
  try:
125
124
  return int(self.env().get("CONTENT_LENGTH", 0))
126
125
  except ValueError:
127
126
  return 0
128
127
 
129
- def cookies(self):
130
- # type: () -> MutableMapping[str, Any]
128
+ def cookies(self) -> MutableMapping[str, Any]:
131
129
  raise NotImplementedError()
132
130
 
133
- def raw_data(self):
134
- # type: () -> Optional[Union[str, bytes]]
131
+ def raw_data(self) -> Optional[Union[str, bytes]]:
135
132
  raise NotImplementedError()
136
133
 
137
- def form(self):
138
- # type: () -> Optional[Dict[str, Any]]
134
+ def form(self) -> Optional[Dict[str, Any]]:
139
135
  raise NotImplementedError()
140
136
 
141
- def parsed_body(self):
142
- # type: () -> Optional[Dict[str, Any]]
137
+ def parsed_body(self) -> Optional[Dict[str, Any]]:
143
138
  try:
144
139
  form = self.form()
145
140
  except Exception:
@@ -161,12 +156,10 @@ class RequestExtractor:
161
156
 
162
157
  return self.json()
163
158
 
164
- def is_json(self):
165
- # type: () -> bool
159
+ def is_json(self) -> bool:
166
160
  return _is_json_content_type(self.env().get("CONTENT_TYPE"))
167
161
 
168
- def json(self):
169
- # type: () -> Optional[Any]
162
+ def json(self) -> Optional[Any]:
170
163
  try:
171
164
  if not self.is_json():
172
165
  return None
@@ -190,21 +183,17 @@ class RequestExtractor:
190
183
 
191
184
  return None
192
185
 
193
- def files(self):
194
- # type: () -> Optional[Dict[str, Any]]
186
+ def files(self) -> Optional[Dict[str, Any]]:
195
187
  raise NotImplementedError()
196
188
 
197
- def size_of_file(self, file):
198
- # type: (Any) -> int
189
+ def size_of_file(self, file: Any) -> int:
199
190
  raise NotImplementedError()
200
191
 
201
- def env(self):
202
- # type: () -> Dict[str, Any]
192
+ def env(self) -> Dict[str, Any]:
203
193
  raise NotImplementedError()
204
194
 
205
195
 
206
- def _is_json_content_type(ct):
207
- # type: (Optional[str]) -> bool
196
+ def _is_json_content_type(ct: Optional[str]) -> bool:
208
197
  mt = (ct or "").split(";", 1)[0]
209
198
  return (
210
199
  mt == "application/json"
@@ -213,8 +202,9 @@ def _is_json_content_type(ct):
213
202
  )
214
203
 
215
204
 
216
- def _filter_headers(headers):
217
- # type: (Mapping[str, str]) -> Mapping[str, Union[AnnotatedValue, str]]
205
+ def _filter_headers(
206
+ headers: Mapping[str, str],
207
+ ) -> Mapping[str, Union[AnnotatedValue, str]]:
218
208
  if should_send_default_pii():
219
209
  return headers
220
210
 
@@ -228,8 +218,7 @@ def _filter_headers(headers):
228
218
  }
229
219
 
230
220
 
231
- def _request_headers_to_span_attributes(headers):
232
- # type: (dict[str, str]) -> dict[str, str]
221
+ def _request_headers_to_span_attributes(headers: dict[str, str]) -> dict[str, str]:
233
222
  attributes = {}
234
223
 
235
224
  headers = _filter_headers(headers)
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sys
2
3
  import weakref
3
4
  from functools import wraps
@@ -85,11 +86,10 @@ class AioHttpIntegration(Integration):
85
86
 
86
87
  def __init__(
87
88
  self,
88
- transaction_style="handler_name", # type: str
89
+ transaction_style: str = "handler_name",
89
90
  *,
90
- failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int]
91
- ):
92
- # type: (...) -> None
91
+ failed_request_status_codes: Set[int] = _DEFAULT_FAILED_REQUEST_STATUS_CODES,
92
+ ) -> None:
93
93
  if transaction_style not in TRANSACTION_STYLE_VALUES:
94
94
  raise ValueError(
95
95
  "Invalid value for transaction_style: %s (must be in %s)"
@@ -99,8 +99,7 @@ class AioHttpIntegration(Integration):
99
99
  self._failed_request_status_codes = failed_request_status_codes
100
100
 
101
101
  @staticmethod
102
- def setup_once():
103
- # type: () -> None
102
+ def setup_once() -> None:
104
103
 
105
104
  version = parse_version(AIOHTTP_VERSION)
106
105
  _check_minimum_version(AioHttpIntegration, version)
@@ -117,8 +116,9 @@ class AioHttpIntegration(Integration):
117
116
 
118
117
  old_handle = Application._handle
119
118
 
120
- async def sentry_app_handle(self, request, *args, **kwargs):
121
- # type: (Any, Request, *Any, **Any) -> Any
119
+ async def sentry_app_handle(
120
+ self: Any, request: Request, *args: Any, **kwargs: Any
121
+ ) -> Any:
122
122
  integration = sentry_sdk.get_client().get_integration(AioHttpIntegration)
123
123
  if integration is None:
124
124
  return await old_handle(self, request, *args, **kwargs)
@@ -172,8 +172,9 @@ class AioHttpIntegration(Integration):
172
172
  old_urldispatcher_resolve = UrlDispatcher.resolve
173
173
 
174
174
  @wraps(old_urldispatcher_resolve)
175
- async def sentry_urldispatcher_resolve(self, request):
176
- # type: (UrlDispatcher, Request) -> UrlMappingMatchInfo
175
+ async def sentry_urldispatcher_resolve(
176
+ self: UrlDispatcher, request: Request
177
+ ) -> UrlMappingMatchInfo:
177
178
  rv = await old_urldispatcher_resolve(self, request)
178
179
 
179
180
  integration = sentry_sdk.get_client().get_integration(AioHttpIntegration)
@@ -205,8 +206,7 @@ class AioHttpIntegration(Integration):
205
206
  old_client_session_init = ClientSession.__init__
206
207
 
207
208
  @ensure_integration_enabled(AioHttpIntegration, old_client_session_init)
208
- def init(*args, **kwargs):
209
- # type: (Any, Any) -> None
209
+ def init(*args: Any, **kwargs: Any) -> None:
210
210
  client_trace_configs = list(kwargs.get("trace_configs") or ())
211
211
  trace_config = create_trace_config()
212
212
  client_trace_configs.append(trace_config)
@@ -217,11 +217,13 @@ class AioHttpIntegration(Integration):
217
217
  ClientSession.__init__ = init
218
218
 
219
219
 
220
- def create_trace_config():
221
- # type: () -> TraceConfig
220
+ def create_trace_config() -> TraceConfig:
222
221
 
223
- async def on_request_start(session, trace_config_ctx, params):
224
- # type: (ClientSession, SimpleNamespace, TraceRequestStartParams) -> None
222
+ async def on_request_start(
223
+ session: ClientSession,
224
+ trace_config_ctx: SimpleNamespace,
225
+ params: TraceRequestStartParams,
226
+ ) -> None:
225
227
  if sentry_sdk.get_client().get_integration(AioHttpIntegration) is None:
226
228
  return
227
229
 
@@ -236,7 +238,7 @@ def create_trace_config():
236
238
  name="%s %s"
237
239
  % (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE),
238
240
  origin=AioHttpIntegration.origin,
239
- only_if_parent=True,
241
+ only_as_child_span=True,
240
242
  )
241
243
 
242
244
  data = {
@@ -277,8 +279,11 @@ def create_trace_config():
277
279
  trace_config_ctx.span = span
278
280
  trace_config_ctx.span_data = data
279
281
 
280
- async def on_request_end(session, trace_config_ctx, params):
281
- # type: (ClientSession, SimpleNamespace, TraceRequestEndParams) -> None
282
+ async def on_request_end(
283
+ session: ClientSession,
284
+ trace_config_ctx: SimpleNamespace,
285
+ params: TraceRequestEndParams,
286
+ ) -> None:
282
287
  if trace_config_ctx.span is None:
283
288
  return
284
289
 
@@ -307,13 +312,13 @@ def create_trace_config():
307
312
  return trace_config
308
313
 
309
314
 
310
- def _make_request_processor(weak_request):
311
- # type: (weakref.ReferenceType[Request]) -> EventProcessor
315
+ def _make_request_processor(
316
+ weak_request: weakref.ReferenceType[Request],
317
+ ) -> EventProcessor:
312
318
  def aiohttp_processor(
313
- event, # type: Event
314
- hint, # type: dict[str, Tuple[type, BaseException, Any]]
315
- ):
316
- # type: (...) -> Event
319
+ event: Event,
320
+ hint: dict[str, Tuple[type, BaseException, Any]],
321
+ ) -> Event:
317
322
  request = weak_request()
318
323
  if request is None:
319
324
  return event
@@ -342,8 +347,7 @@ def _make_request_processor(weak_request):
342
347
  return aiohttp_processor
343
348
 
344
349
 
345
- def _capture_exception():
346
- # type: () -> ExcInfo
350
+ def _capture_exception() -> ExcInfo:
347
351
  exc_info = sys.exc_info()
348
352
  event, hint = event_from_exception(
349
353
  exc_info,
@@ -357,8 +361,7 @@ def _capture_exception():
357
361
  BODY_NOT_READ_MESSAGE = "[Can't show request body due to implementation details.]"
358
362
 
359
363
 
360
- def get_aiohttp_request_data(request):
361
- # type: (Request) -> Union[Optional[str], AnnotatedValue]
364
+ def get_aiohttp_request_data(request: Request) -> Union[Optional[str], AnnotatedValue]:
362
365
  bytes_body = request._read_bytes
363
366
 
364
367
  if bytes_body is not None:
@@ -377,8 +380,7 @@ def get_aiohttp_request_data(request):
377
380
  return None
378
381
 
379
382
 
380
- def _prepopulate_attributes(request):
381
- # type: (Request) -> dict[str, Any]
383
+ def _prepopulate_attributes(request: Request) -> dict[str, Any]:
382
384
  """Construct initial span attributes that can be used in traces sampler."""
383
385
  attributes = {}
384
386
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from functools import wraps
2
3
  from typing import TYPE_CHECKING
3
4
 
@@ -29,13 +30,11 @@ class AnthropicIntegration(Integration):
29
30
  identifier = "anthropic"
30
31
  origin = f"auto.ai.{identifier}"
31
32
 
32
- def __init__(self, include_prompts=True):
33
- # type: (AnthropicIntegration, bool) -> None
33
+ def __init__(self: AnthropicIntegration, include_prompts: bool = True) -> None:
34
34
  self.include_prompts = include_prompts
35
35
 
36
36
  @staticmethod
37
- def setup_once():
38
- # type: () -> None
37
+ def setup_once() -> None:
39
38
  version = package_version("anthropic")
40
39
  _check_minimum_version(AnthropicIntegration, version)
41
40
 
@@ -43,8 +42,7 @@ class AnthropicIntegration(Integration):
43
42
  AsyncMessages.create = _wrap_message_create_async(AsyncMessages.create)
44
43
 
45
44
 
46
- def _capture_exception(exc):
47
- # type: (Any) -> None
45
+ def _capture_exception(exc: Any) -> None:
48
46
  event, hint = event_from_exception(
49
47
  exc,
50
48
  client_options=sentry_sdk.get_client().options,
@@ -53,8 +51,7 @@ def _capture_exception(exc):
53
51
  sentry_sdk.capture_event(event, hint=hint)
54
52
 
55
53
 
56
- def _calculate_token_usage(result, span):
57
- # type: (Messages, Span) -> None
54
+ def _calculate_token_usage(result: Messages, span: Span) -> None:
58
55
  input_tokens = 0
59
56
  output_tokens = 0
60
57
  if hasattr(result, "usage"):
@@ -65,11 +62,16 @@ def _calculate_token_usage(result, span):
65
62
  output_tokens = usage.output_tokens
66
63
 
67
64
  total_tokens = input_tokens + output_tokens
68
- record_token_usage(span, input_tokens, output_tokens, total_tokens)
65
+
66
+ record_token_usage(
67
+ span,
68
+ input_tokens=input_tokens,
69
+ output_tokens=output_tokens,
70
+ total_tokens=total_tokens,
71
+ )
69
72
 
70
73
 
71
- def _get_responses(content):
72
- # type: (list[Any]) -> list[dict[str, Any]]
74
+ def _get_responses(content: list[Any]) -> list[dict[str, Any]]:
73
75
  """
74
76
  Get JSON of a Anthropic responses.
75
77
  """
@@ -85,8 +87,12 @@ def _get_responses(content):
85
87
  return responses
86
88
 
87
89
 
88
- def _collect_ai_data(event, input_tokens, output_tokens, content_blocks):
89
- # type: (MessageStreamEvent, int, int, list[str]) -> tuple[int, int, list[str]]
90
+ def _collect_ai_data(
91
+ event: MessageStreamEvent,
92
+ input_tokens: int,
93
+ output_tokens: int,
94
+ content_blocks: list[str],
95
+ ) -> tuple[int, int, list[str]]:
90
96
  """
91
97
  Count token usage and collect content blocks from the AI streaming response.
92
98
  """
@@ -112,9 +118,12 @@ def _collect_ai_data(event, input_tokens, output_tokens, content_blocks):
112
118
 
113
119
 
114
120
  def _add_ai_data_to_span(
115
- span, integration, input_tokens, output_tokens, content_blocks
116
- ):
117
- # type: (Span, AnthropicIntegration, int, int, list[str]) -> None
121
+ span: Span,
122
+ integration: AnthropicIntegration,
123
+ input_tokens: int,
124
+ output_tokens: int,
125
+ content_blocks: list[str],
126
+ ) -> None:
118
127
  """
119
128
  Add token usage and content blocks from the AI streaming response to the span.
120
129
  """
@@ -126,12 +135,16 @@ def _add_ai_data_to_span(
126
135
  [{"type": "text", "text": complete_message}],
127
136
  )
128
137
  total_tokens = input_tokens + output_tokens
129
- record_token_usage(span, input_tokens, output_tokens, total_tokens)
138
+ record_token_usage(
139
+ span,
140
+ input_tokens=input_tokens,
141
+ output_tokens=output_tokens,
142
+ total_tokens=total_tokens,
143
+ )
130
144
  span.set_attribute(SPANDATA.AI_STREAMING, True)
131
145
 
132
146
 
133
- def _sentry_patched_create_common(f, *args, **kwargs):
134
- # type: (Any, *Any, **Any) -> Any
147
+ def _sentry_patched_create_common(f: Any, *args: Any, **kwargs: Any) -> Any:
135
148
  integration = kwargs.pop("integration")
136
149
  if integration is None:
137
150
  return f(*args, **kwargs)
@@ -148,7 +161,7 @@ def _sentry_patched_create_common(f, *args, **kwargs):
148
161
  op=OP.ANTHROPIC_MESSAGES_CREATE,
149
162
  description="Anthropic messages create",
150
163
  origin=AnthropicIntegration.origin,
151
- only_if_parent=True,
164
+ only_as_child_span=True,
152
165
  )
153
166
  span.__enter__()
154
167
 
@@ -177,11 +190,10 @@ def _sentry_patched_create_common(f, *args, **kwargs):
177
190
  elif hasattr(result, "_iterator"):
178
191
  old_iterator = result._iterator
179
192
 
180
- def new_iterator():
181
- # type: () -> Iterator[MessageStreamEvent]
193
+ def new_iterator() -> Iterator[MessageStreamEvent]:
182
194
  input_tokens = 0
183
195
  output_tokens = 0
184
- content_blocks = [] # type: list[str]
196
+ content_blocks: list[str] = []
185
197
 
186
198
  for event in old_iterator:
187
199
  input_tokens, output_tokens, content_blocks = _collect_ai_data(
@@ -194,11 +206,10 @@ def _sentry_patched_create_common(f, *args, **kwargs):
194
206
  )
195
207
  span.__exit__(None, None, None)
196
208
 
197
- async def new_iterator_async():
198
- # type: () -> AsyncIterator[MessageStreamEvent]
209
+ async def new_iterator_async() -> AsyncIterator[MessageStreamEvent]:
199
210
  input_tokens = 0
200
211
  output_tokens = 0
201
- content_blocks = [] # type: list[str]
212
+ content_blocks: list[str] = []
202
213
 
203
214
  async for event in old_iterator:
204
215
  input_tokens, output_tokens, content_blocks = _collect_ai_data(
@@ -223,10 +234,8 @@ def _sentry_patched_create_common(f, *args, **kwargs):
223
234
  return result
224
235
 
225
236
 
226
- def _wrap_message_create(f):
227
- # type: (Any) -> Any
228
- def _execute_sync(f, *args, **kwargs):
229
- # type: (Any, *Any, **Any) -> Any
237
+ def _wrap_message_create(f: Any) -> Any:
238
+ def _execute_sync(f: Any, *args: Any, **kwargs: Any) -> Any:
230
239
  gen = _sentry_patched_create_common(f, *args, **kwargs)
231
240
 
232
241
  try:
@@ -246,8 +255,7 @@ def _wrap_message_create(f):
246
255
  return e.value
247
256
 
248
257
  @wraps(f)
249
- def _sentry_patched_create_sync(*args, **kwargs):
250
- # type: (*Any, **Any) -> Any
258
+ def _sentry_patched_create_sync(*args: Any, **kwargs: Any) -> Any:
251
259
  integration = sentry_sdk.get_client().get_integration(AnthropicIntegration)
252
260
  kwargs["integration"] = integration
253
261
 
@@ -256,10 +264,8 @@ def _wrap_message_create(f):
256
264
  return _sentry_patched_create_sync
257
265
 
258
266
 
259
- def _wrap_message_create_async(f):
260
- # type: (Any) -> Any
261
- async def _execute_async(f, *args, **kwargs):
262
- # type: (Any, *Any, **Any) -> Any
267
+ def _wrap_message_create_async(f: Any) -> Any:
268
+ async def _execute_async(f: Any, *args: Any, **kwargs: Any) -> Any:
263
269
  gen = _sentry_patched_create_common(f, *args, **kwargs)
264
270
 
265
271
  try:
@@ -279,8 +285,7 @@ def _wrap_message_create_async(f):
279
285
  return e.value
280
286
 
281
287
  @wraps(f)
282
- async def _sentry_patched_create_async(*args, **kwargs):
283
- # type: (*Any, **Any) -> Any
288
+ async def _sentry_patched_create_async(*args: Any, **kwargs: Any) -> Any:
284
289
  integration = sentry_sdk.get_client().get_integration(AnthropicIntegration)
285
290
  kwargs["integration"] = integration
286
291
 
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sys
2
3
 
3
4
  import sentry_sdk
@@ -16,11 +17,9 @@ class ArgvIntegration(Integration):
16
17
  identifier = "argv"
17
18
 
18
19
  @staticmethod
19
- def setup_once():
20
- # type: () -> None
20
+ def setup_once() -> None:
21
21
  @add_global_event_processor
22
- def processor(event, hint):
23
- # type: (Event, Optional[Hint]) -> Optional[Event]
22
+ def processor(event: Event, hint: Optional[Hint]) -> Optional[Event]:
24
23
  if sentry_sdk.get_client().get_integration(ArgvIntegration) is not None:
25
24
  extra = event.setdefault("extra", {})
26
25
  # If some event processor decided to set extra to e.g. an
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from importlib import import_module
2
3
 
3
4
  import sentry_sdk
@@ -33,8 +34,7 @@ class AriadneIntegration(Integration):
33
34
  identifier = "ariadne"
34
35
 
35
36
  @staticmethod
36
- def setup_once():
37
- # type: () -> None
37
+ def setup_once() -> None:
38
38
  version = package_version("ariadne")
39
39
  _check_minimum_version(AriadneIntegration, version)
40
40
 
@@ -43,15 +43,15 @@ class AriadneIntegration(Integration):
43
43
  _patch_graphql()
44
44
 
45
45
 
46
- def _patch_graphql():
47
- # type: () -> None
46
+ def _patch_graphql() -> None:
48
47
  old_parse_query = ariadne_graphql.parse_query
49
48
  old_handle_errors = ariadne_graphql.handle_graphql_errors
50
49
  old_handle_query_result = ariadne_graphql.handle_query_result
51
50
 
52
51
  @ensure_integration_enabled(AriadneIntegration, old_parse_query)
53
- def _sentry_patched_parse_query(context_value, query_parser, data):
54
- # type: (Optional[Any], Optional[QueryParser], Any) -> DocumentNode
52
+ def _sentry_patched_parse_query(
53
+ context_value: Optional[Any], query_parser: Optional[QueryParser], data: Any
54
+ ) -> DocumentNode:
55
55
  event_processor = _make_request_event_processor(data)
56
56
  sentry_sdk.get_isolation_scope().add_event_processor(event_processor)
57
57
 
@@ -59,8 +59,9 @@ def _patch_graphql():
59
59
  return result
60
60
 
61
61
  @ensure_integration_enabled(AriadneIntegration, old_handle_errors)
62
- def _sentry_patched_handle_graphql_errors(errors, *args, **kwargs):
63
- # type: (List[GraphQLError], Any, Any) -> GraphQLResult
62
+ def _sentry_patched_handle_graphql_errors(
63
+ errors: List[GraphQLError], *args: Any, **kwargs: Any
64
+ ) -> GraphQLResult:
64
65
  result = old_handle_errors(errors, *args, **kwargs)
65
66
 
66
67
  event_processor = _make_response_event_processor(result[1])
@@ -83,8 +84,9 @@ def _patch_graphql():
83
84
  return result
84
85
 
85
86
  @ensure_integration_enabled(AriadneIntegration, old_handle_query_result)
86
- def _sentry_patched_handle_query_result(result, *args, **kwargs):
87
- # type: (Any, Any, Any) -> GraphQLResult
87
+ def _sentry_patched_handle_query_result(
88
+ result: Any, *args: Any, **kwargs: Any
89
+ ) -> GraphQLResult:
88
90
  query_result = old_handle_query_result(result, *args, **kwargs)
89
91
 
90
92
  event_processor = _make_response_event_processor(query_result[1])
@@ -111,12 +113,10 @@ def _patch_graphql():
111
113
  ariadne_graphql.handle_query_result = _sentry_patched_handle_query_result # type: ignore
112
114
 
113
115
 
114
- def _make_request_event_processor(data):
115
- # type: (GraphQLSchema) -> EventProcessor
116
+ def _make_request_event_processor(data: GraphQLSchema) -> EventProcessor:
116
117
  """Add request data and api_target to events."""
117
118
 
118
- def inner(event, hint):
119
- # type: (Event, dict[str, Any]) -> Event
119
+ def inner(event: Event, hint: dict[str, Any]) -> Event:
120
120
  if not isinstance(data, dict):
121
121
  return event
122
122
 
@@ -143,12 +143,10 @@ def _make_request_event_processor(data):
143
143
  return inner
144
144
 
145
145
 
146
- def _make_response_event_processor(response):
147
- # type: (Dict[str, Any]) -> EventProcessor
146
+ def _make_response_event_processor(response: Dict[str, Any]) -> EventProcessor:
148
147
  """Add response data to the event's response context."""
149
148
 
150
- def inner(event, hint):
151
- # type: (Event, dict[str, Any]) -> Event
149
+ def inner(event: Event, hint: dict[str, Any]) -> Event:
152
150
  with capture_internal_exceptions():
153
151
  if should_send_default_pii() and response.get("errors"):
154
152
  contexts = event.setdefault("contexts", {})