sentry-sdk 3.0.0a3__py2.py3-none-any.whl → 3.0.0a5__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 (59) hide show
  1. sentry_sdk/__init__.py +3 -0
  2. sentry_sdk/ai/monitoring.py +7 -7
  3. sentry_sdk/ai/utils.py +5 -1
  4. sentry_sdk/api.py +73 -0
  5. sentry_sdk/client.py +10 -7
  6. sentry_sdk/consts.py +148 -8
  7. sentry_sdk/integrations/aiohttp.py +1 -1
  8. sentry_sdk/integrations/anthropic.py +1 -1
  9. sentry_sdk/integrations/arq.py +1 -1
  10. sentry_sdk/integrations/asyncio.py +1 -1
  11. sentry_sdk/integrations/asyncpg.py +1 -1
  12. sentry_sdk/integrations/boto3.py +2 -2
  13. sentry_sdk/integrations/celery/__init__.py +4 -3
  14. sentry_sdk/integrations/clickhouse_driver.py +1 -1
  15. sentry_sdk/integrations/cohere.py +2 -2
  16. sentry_sdk/integrations/django/__init__.py +12 -2
  17. sentry_sdk/integrations/django/asgi.py +1 -1
  18. sentry_sdk/integrations/django/caching.py +1 -1
  19. sentry_sdk/integrations/django/middleware.py +1 -1
  20. sentry_sdk/integrations/django/signals_handlers.py +1 -1
  21. sentry_sdk/integrations/django/templates.py +2 -2
  22. sentry_sdk/integrations/django/views.py +2 -2
  23. sentry_sdk/integrations/gnu_backtrace.py +3 -14
  24. sentry_sdk/integrations/graphene.py +1 -1
  25. sentry_sdk/integrations/grpc/aio/client.py +2 -2
  26. sentry_sdk/integrations/grpc/client.py +2 -2
  27. sentry_sdk/integrations/httpx.py +2 -2
  28. sentry_sdk/integrations/huey.py +1 -1
  29. sentry_sdk/integrations/huggingface_hub.py +1 -1
  30. sentry_sdk/integrations/langchain.py +1 -1
  31. sentry_sdk/integrations/litestar.py +3 -3
  32. sentry_sdk/integrations/logging.py +1 -1
  33. sentry_sdk/integrations/loguru.py +1 -1
  34. sentry_sdk/integrations/openai.py +339 -134
  35. sentry_sdk/integrations/openai_agents/utils.py +1 -49
  36. sentry_sdk/integrations/openfeature.py +4 -5
  37. sentry_sdk/integrations/pymongo.py +1 -1
  38. sentry_sdk/integrations/ray.py +1 -1
  39. sentry_sdk/integrations/redis/_async_common.py +3 -3
  40. sentry_sdk/integrations/redis/_sync_common.py +3 -3
  41. sentry_sdk/integrations/rust_tracing.py +1 -1
  42. sentry_sdk/integrations/socket.py +2 -2
  43. sentry_sdk/integrations/starlette.py +3 -3
  44. sentry_sdk/integrations/starlite.py +4 -4
  45. sentry_sdk/integrations/stdlib.py +4 -4
  46. sentry_sdk/integrations/strawberry.py +1 -1
  47. sentry_sdk/integrations/threading.py +1 -1
  48. sentry_sdk/opentelemetry/scope.py +13 -1
  49. sentry_sdk/opentelemetry/span_processor.py +1 -0
  50. sentry_sdk/serializer.py +8 -11
  51. sentry_sdk/tracing.py +9 -4
  52. sentry_sdk/tracing_utils.py +3 -3
  53. sentry_sdk/utils.py +46 -0
  54. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/METADATA +1 -1
  55. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/RECORD +59 -59
  56. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/WHEEL +0 -0
  57. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/entry_points.txt +0 -0
  58. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/licenses/LICENSE +0 -0
  59. {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a5.dist-info}/top_level.txt +0 -0
@@ -66,7 +66,7 @@ def _sentry_request_created(
66
66
  op=OP.HTTP_CLIENT,
67
67
  name=description,
68
68
  origin=Boto3Integration.origin,
69
- only_if_parent=True,
69
+ only_as_child_span=True,
70
70
  )
71
71
 
72
72
  data = {
@@ -120,7 +120,7 @@ def _sentry_after_call(
120
120
  op=OP.HTTP_CLIENT_STREAM,
121
121
  name=span.name,
122
122
  origin=Boto3Integration.origin,
123
- only_if_parent=True,
123
+ only_as_child_span=True,
124
124
  )
125
125
 
126
126
  orig_read = body.read
@@ -269,7 +269,7 @@ def _wrap_task_run(f: F) -> F:
269
269
  op=OP.QUEUE_SUBMIT_CELERY,
270
270
  name=task_name,
271
271
  origin=CeleryIntegration.origin,
272
- only_if_parent=True,
272
+ only_as_child_span=True,
273
273
  )
274
274
  if not task_started_from_beat
275
275
  else NoOpMgr()
@@ -354,7 +354,7 @@ def _wrap_task_call(task: Any, f: F) -> F:
354
354
  op=OP.QUEUE_PROCESS,
355
355
  name=task.name,
356
356
  origin=CeleryIntegration.origin,
357
- only_if_parent=True,
357
+ only_as_child_span=True,
358
358
  ) as span:
359
359
  _set_messaging_destination_name(task, span)
360
360
 
@@ -369,6 +369,7 @@ def _wrap_task_call(task: Any, f: F) -> F:
369
369
  )
370
370
 
371
371
  if latency is not None:
372
+ latency *= 1000 # milliseconds
372
373
  span.set_attribute(
373
374
  SPANDATA.MESSAGING_MESSAGE_RECEIVE_LATENCY, latency
374
375
  )
@@ -479,7 +480,7 @@ def _patch_producer_publish() -> None:
479
480
  op=OP.QUEUE_PUBLISH,
480
481
  name=task_name,
481
482
  origin=CeleryIntegration.origin,
482
- only_if_parent=True,
483
+ only_as_child_span=True,
483
484
  ) as span:
484
485
  if task_id is not None:
485
486
  span.set_attribute(SPANDATA.MESSAGING_MESSAGE_ID, task_id)
@@ -71,7 +71,7 @@ def _wrap_start(f: Callable[P, T]) -> Callable[P, T]:
71
71
  op=OP.DB,
72
72
  name=query,
73
73
  origin=ClickhouseDriverIntegration.origin,
74
- only_if_parent=True,
74
+ only_as_child_span=True,
75
75
  )
76
76
 
77
77
  connection._sentry_span = span # type: ignore[attr-defined]
@@ -144,7 +144,7 @@ def _wrap_chat(f: Callable[..., Any], streaming: bool) -> Callable[..., Any]:
144
144
  op=consts.OP.COHERE_CHAT_COMPLETIONS_CREATE,
145
145
  name="cohere.client.Chat",
146
146
  origin=CohereIntegration.origin,
147
- only_if_parent=True,
147
+ only_as_child_span=True,
148
148
  )
149
149
  span.__enter__()
150
150
  try:
@@ -228,7 +228,7 @@ def _wrap_embed(f: Callable[..., Any]) -> Callable[..., Any]:
228
228
  op=consts.OP.COHERE_EMBEDDINGS_CREATE,
229
229
  name="Cohere Embedding Creation",
230
230
  origin=CohereIntegration.origin,
231
- only_if_parent=True,
231
+ only_as_child_span=True,
232
232
  ) as span:
233
233
  if "texts" in kwargs and (
234
234
  should_send_default_pii() and integration.include_prompts
@@ -9,7 +9,7 @@ from importlib import import_module
9
9
  import sentry_sdk
10
10
  from sentry_sdk.consts import OP, SPANDATA, SOURCE_FOR_STYLE, TransactionSource
11
11
  from sentry_sdk.scope import add_global_event_processor, should_send_default_pii
12
- from sentry_sdk.serializer import add_global_repr_processor
12
+ from sentry_sdk.serializer import add_global_repr_processor, add_repr_sequence_type
13
13
  from sentry_sdk.tracing_utils import add_query_source, record_sql_queries
14
14
  from sentry_sdk.utils import (
15
15
  AnnotatedValue,
@@ -254,6 +254,7 @@ class DjangoIntegration(Integration):
254
254
  patch_views()
255
255
  patch_templates()
256
256
  patch_signals()
257
+ add_template_context_repr_sequence()
257
258
 
258
259
  if patch_caching is not None:
259
260
  patch_caching()
@@ -649,7 +650,7 @@ def install_sql_hook() -> None:
649
650
  op=OP.DB,
650
651
  name="connect",
651
652
  origin=DjangoIntegration.origin_db,
652
- only_if_parent=True,
653
+ only_as_child_span=True,
653
654
  ) as span:
654
655
  _set_db_data(span, self)
655
656
  return real_connect(self)
@@ -709,3 +710,12 @@ def _set_db_data(span: Span, cursor_or_db: Any) -> None:
709
710
  server_socket_address = connection_params.get("unix_socket")
710
711
  if server_socket_address is not None:
711
712
  span.set_attribute(SPANDATA.SERVER_SOCKET_ADDRESS, server_socket_address)
713
+
714
+
715
+ def add_template_context_repr_sequence() -> None:
716
+ try:
717
+ from django.template.context import BaseContext
718
+
719
+ add_repr_sequence_type(BaseContext)
720
+ except Exception:
721
+ pass
@@ -184,7 +184,7 @@ def wrap_async_view(callback: Any) -> Any:
184
184
  op=OP.VIEW_RENDER,
185
185
  name=request.resolver_match.view_name,
186
186
  origin=DjangoIntegration.origin,
187
- only_if_parent=True,
187
+ only_as_child_span=True,
188
188
  ):
189
189
  return await callback(request, *args, **kwargs)
190
190
 
@@ -62,7 +62,7 @@ def _patch_cache_method(
62
62
  op=op,
63
63
  name=description,
64
64
  origin=DjangoIntegration.origin,
65
- only_if_parent=True,
65
+ only_as_child_span=True,
66
66
  ) as span:
67
67
  value = original_method(*args, **kwargs)
68
68
 
@@ -86,7 +86,7 @@ def _wrap_middleware(middleware: Any, middleware_name: str) -> Any:
86
86
  op=OP.MIDDLEWARE_DJANGO,
87
87
  name=description,
88
88
  origin=DjangoIntegration.origin,
89
- only_if_parent=True,
89
+ only_as_child_span=True,
90
90
  )
91
91
  middleware_span.set_tag("django.function_name", function_name)
92
92
  middleware_span.set_tag("django.middleware_name", middleware_name)
@@ -70,7 +70,7 @@ def patch_signals() -> None:
70
70
  op=OP.EVENT_DJANGO,
71
71
  name=signal_name,
72
72
  origin=DjangoIntegration.origin,
73
- only_if_parent=True,
73
+ only_as_child_span=True,
74
74
  ) as span:
75
75
  span.set_attribute("signal", signal_name)
76
76
  return receiver(*args, **kwargs)
@@ -64,7 +64,7 @@ def patch_templates() -> None:
64
64
  op=OP.TEMPLATE_RENDER,
65
65
  name=_get_template_name_description(self.template_name),
66
66
  origin=DjangoIntegration.origin,
67
- only_if_parent=True,
67
+ only_as_child_span=True,
68
68
  ) as span:
69
69
  if isinstance(self.context_data, dict):
70
70
  for k, v in self.context_data.items():
@@ -98,7 +98,7 @@ def patch_templates() -> None:
98
98
  op=OP.TEMPLATE_RENDER,
99
99
  name=_get_template_name_description(template_name),
100
100
  origin=DjangoIntegration.origin,
101
- only_if_parent=True,
101
+ only_as_child_span=True,
102
102
  ) as span:
103
103
  for k, v in context.items():
104
104
  span.set_attribute(f"context.{k}", v)
@@ -37,7 +37,7 @@ def patch_views() -> None:
37
37
  op=OP.VIEW_RESPONSE_RENDER,
38
38
  name="serialize response",
39
39
  origin=DjangoIntegration.origin,
40
- only_if_parent=True,
40
+ only_as_child_span=True,
41
41
  ):
42
42
  return old_render(self)
43
43
 
@@ -88,7 +88,7 @@ def _wrap_sync_view(callback: Any) -> Any:
88
88
  op=OP.VIEW_RENDER,
89
89
  name=request.resolver_match.view_name,
90
90
  origin=DjangoIntegration.origin,
91
- only_if_parent=True,
91
+ only_as_child_span=True,
92
92
  ):
93
93
  return callback(request, *args, **kwargs)
94
94
 
@@ -13,23 +13,12 @@ if TYPE_CHECKING:
13
13
  from sentry_sdk._types import Event
14
14
 
15
15
 
16
- MODULE_RE = r"[a-zA-Z0-9/._:\\-]+"
17
- TYPE_RE = r"[a-zA-Z0-9._:<>,-]+"
18
- HEXVAL_RE = r"[A-Fa-f0-9]+"
19
-
16
+ FUNCTION_RE = r"[^@]+?)\s+@\s+0x[0-9a-fA-F]+"
20
17
 
21
18
  FRAME_RE = r"""
22
- ^(?P<index>\d+)\.\s
23
- (?P<package>{MODULE_RE})\(
24
- (?P<retval>{TYPE_RE}\ )?
25
- ((?P<function>{TYPE_RE})
26
- (?P<args>\(.*\))?
27
- )?
28
- ((?P<constoffset>\ const)?\+0x(?P<offset>{HEXVAL_RE}))?
29
- \)\s
30
- \[0x(?P<retaddr>{HEXVAL_RE})\]$
19
+ ^(?P<index>\d+)\.\s+(?P<function>{FUNCTION_RE}\s+in\s+(?P<package>.+)$
31
20
  """.format(
32
- MODULE_RE=MODULE_RE, HEXVAL_RE=HEXVAL_RE, TYPE_RE=TYPE_RE
21
+ FUNCTION_RE=FUNCTION_RE,
33
22
  )
34
23
 
35
24
  FRAME_RE = re.compile(FRAME_RE, re.MULTILINE | re.VERBOSE)
@@ -137,7 +137,7 @@ def graphql_span(
137
137
  )
138
138
 
139
139
  with sentry_sdk.start_span(
140
- op=op, name=operation_name, only_if_parent=True
140
+ op=op, name=operation_name, only_as_child_span=True
141
141
  ) as graphql_span:
142
142
  graphql_span.set_attribute("graphql.document", source)
143
143
  graphql_span.set_attribute("graphql.operation.name", operation_name)
@@ -51,7 +51,7 @@ class SentryUnaryUnaryClientInterceptor(ClientInterceptor, UnaryUnaryClientInter
51
51
  op=OP.GRPC_CLIENT,
52
52
  name="unary unary call to %s" % method,
53
53
  origin=SPAN_ORIGIN,
54
- only_if_parent=True,
54
+ only_as_child_span=True,
55
55
  ) as span:
56
56
  span.set_attribute("type", "unary unary")
57
57
  span.set_attribute("method", method)
@@ -84,7 +84,7 @@ class SentryUnaryStreamClientInterceptor(
84
84
  op=OP.GRPC_CLIENT,
85
85
  name="unary stream call to %s" % method,
86
86
  origin=SPAN_ORIGIN,
87
- only_if_parent=True,
87
+ only_as_child_span=True,
88
88
  ) as span:
89
89
  span.set_attribute("type", "unary stream")
90
90
  span.set_attribute("method", method)
@@ -36,7 +36,7 @@ class ClientInterceptor(
36
36
  op=OP.GRPC_CLIENT,
37
37
  name="unary unary call to %s" % method,
38
38
  origin=SPAN_ORIGIN,
39
- only_if_parent=True,
39
+ only_as_child_span=True,
40
40
  ) as span:
41
41
  span.set_attribute("type", "unary unary")
42
42
  span.set_attribute("method", method)
@@ -64,7 +64,7 @@ class ClientInterceptor(
64
64
  op=OP.GRPC_CLIENT,
65
65
  name="unary stream call to %s" % method,
66
66
  origin=SPAN_ORIGIN,
67
- only_if_parent=True,
67
+ only_as_child_span=True,
68
68
  ) as span:
69
69
  span.set_attribute("type", "unary stream")
70
70
  span.set_attribute("method", method)
@@ -59,7 +59,7 @@ def _install_httpx_client() -> None:
59
59
  parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE,
60
60
  ),
61
61
  origin=HttpxIntegration.origin,
62
- only_if_parent=True,
62
+ only_as_child_span=True,
63
63
  ) as span:
64
64
  data = {
65
65
  SPANDATA.HTTP_METHOD: request.method,
@@ -129,7 +129,7 @@ def _install_httpx_async_client() -> None:
129
129
  parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE,
130
130
  ),
131
131
  origin=HttpxIntegration.origin,
132
- only_if_parent=True,
132
+ only_as_child_span=True,
133
133
  ) as span:
134
134
  data = {
135
135
  SPANDATA.HTTP_METHOD: request.method,
@@ -60,7 +60,7 @@ def patch_enqueue() -> None:
60
60
  op=OP.QUEUE_SUBMIT_HUEY,
61
61
  name=task.name,
62
62
  origin=HueyIntegration.origin,
63
- only_if_parent=True,
63
+ only_as_child_span=True,
64
64
  ):
65
65
  if not isinstance(task, PeriodicTask):
66
66
  # Attach trace propagation data to task kwargs. We do
@@ -73,7 +73,7 @@ def _wrap_text_generation(f: Callable[..., Any]) -> Callable[..., Any]:
73
73
  op=consts.OP.HUGGINGFACE_HUB_CHAT_COMPLETIONS_CREATE,
74
74
  name="Text Generation",
75
75
  origin=HuggingfaceHubIntegration.origin,
76
- only_if_parent=True,
76
+ only_as_child_span=True,
77
77
  )
78
78
  span.__enter__()
79
79
  try:
@@ -144,7 +144,7 @@ class SentryLangchainCallback(BaseCallbackHandler): # type: ignore[misc]
144
144
  parent_watched_span = self.span_map.get(parent_id) if parent_id else None
145
145
  sentry_span = sentry_sdk.start_span(
146
146
  parent_span=parent_watched_span.span if parent_watched_span else None,
147
- only_if_parent=True,
147
+ only_as_child_span=True,
148
148
  **kwargs,
149
149
  )
150
150
  watched_span = WatchedSpan(sentry_span)
@@ -157,7 +157,7 @@ def enable_span_for_middleware(middleware: Middleware) -> Middleware:
157
157
  op=OP.MIDDLEWARE_LITESTAR,
158
158
  name=middleware_name,
159
159
  origin=LitestarIntegration.origin,
160
- only_if_parent=True,
160
+ only_as_child_span=True,
161
161
  ) as middleware_span:
162
162
  middleware_span.set_tag("litestar.middleware_name", middleware_name)
163
163
 
@@ -171,7 +171,7 @@ def enable_span_for_middleware(middleware: Middleware) -> Middleware:
171
171
  op=OP.MIDDLEWARE_LITESTAR_RECEIVE,
172
172
  name=getattr(receive, "__qualname__", str(receive)),
173
173
  origin=LitestarIntegration.origin,
174
- only_if_parent=True,
174
+ only_as_child_span=True,
175
175
  ) as span:
176
176
  span.set_tag("litestar.middleware_name", middleware_name)
177
177
  return await receive(*args, **kwargs)
@@ -188,7 +188,7 @@ def enable_span_for_middleware(middleware: Middleware) -> Middleware:
188
188
  op=OP.MIDDLEWARE_LITESTAR_SEND,
189
189
  name=getattr(send, "__qualname__", str(send)),
190
190
  origin=LitestarIntegration.origin,
191
- only_if_parent=True,
191
+ only_as_child_span=True,
192
192
  ) as span:
193
193
  span.set_tag("litestar.middleware_name", middleware_name)
194
194
  return await send(message)
@@ -336,7 +336,7 @@ class SentryLogsHandler(_BaseHandler):
336
336
  if not client.is_active():
337
337
  return
338
338
 
339
- if not client.options["_experiments"].get("enable_logs", False):
339
+ if client.options.get("enable_logs") is not True:
340
340
  return
341
341
 
342
342
  self._capture_log_from_record(client, record)
@@ -147,7 +147,7 @@ def loguru_sentry_logs_handler(message: Message) -> None:
147
147
  if not client.is_active():
148
148
  return
149
149
 
150
- if not client.options["_experiments"].get("enable_logs", False):
150
+ if client.options.get("enable_logs") is not True:
151
151
  return
152
152
 
153
153
  record = message.record