sentry-sdk 3.0.0a5__py2.py3-none-any.whl → 3.0.0a6__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.

@@ -85,6 +85,7 @@ class SentryLitestarASGIMiddleware(SentryAsgiMiddleware):
85
85
  transaction_style="endpoint",
86
86
  mechanism_type="asgi",
87
87
  span_origin=span_origin,
88
+ asgi_version=3,
88
89
  )
89
90
 
90
91
  def _capture_request_exception(self, exc: Exception) -> None:
@@ -113,7 +114,6 @@ def patch_app_init() -> None:
113
114
  *(kwargs.get("after_exception") or []),
114
115
  ]
115
116
 
116
- SentryLitestarASGIMiddleware.__call__ = SentryLitestarASGIMiddleware._run_asgi3 # type: ignore
117
117
  middleware = kwargs.get("middleware") or []
118
118
  kwargs["middleware"] = [SentryLitestarASGIMiddleware, *middleware]
119
119
  old__init__(self, *args, **kwargs)
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from functools import wraps
4
4
 
5
5
  from sentry_sdk.integrations import DidNotEnable
6
-
7
6
  from ..spans import invoke_agent_span, update_invoke_agent_span, handoff_span
8
7
 
9
8
  from typing import TYPE_CHECKING
@@ -11,7 +10,6 @@ from typing import TYPE_CHECKING
11
10
  if TYPE_CHECKING:
12
11
  from typing import Any, Optional
13
12
 
14
-
15
13
  try:
16
14
  import agents
17
15
  except ImportError:
@@ -23,20 +23,23 @@ def _create_run_wrapper(original_func: Callable[..., Any]) -> Callable[..., Any]
23
23
 
24
24
  @wraps(original_func)
25
25
  async def wrapper(*args: Any, **kwargs: Any) -> Any:
26
- agent = args[0]
27
- with agent_workflow_span(agent):
28
- result = None
29
- try:
30
- result = await original_func(*args, **kwargs)
31
- return result
32
- except Exception as exc:
33
- _capture_exception(exc)
34
-
35
- # It could be that there is a "invoke agent" span still open
36
- span = sentry_sdk.get_current_span()
37
- if span is not None and span.timestamp is None:
38
- span.__exit__(None, None, None)
39
-
40
- raise exc from None
26
+ # Isolate each workflow so that when agents are run in asyncio tasks they
27
+ # don't touch each other's scopes
28
+ with sentry_sdk.isolation_scope():
29
+ agent = args[0]
30
+ with agent_workflow_span(agent):
31
+ result = None
32
+ try:
33
+ result = await original_func(*args, **kwargs)
34
+ return result
35
+ except Exception as exc:
36
+ _capture_exception(exc)
37
+
38
+ # It could be that there is a "invoke agent" span still open
39
+ current_span = sentry_sdk.get_current_span()
40
+ if current_span is not None and current_span.timestamp is None:
41
+ current_span.__exit__(None, None, None)
42
+
43
+ raise exc from None
41
44
 
42
45
  return wrapper
@@ -94,8 +94,8 @@ def patch_asgi_app() -> None:
94
94
  middleware = SentryAsgiMiddleware(
95
95
  lambda *a, **kw: old_app(self, *a, **kw),
96
96
  span_origin=QuartIntegration.origin,
97
+ asgi_version=3,
97
98
  )
98
- middleware.__call__ = middleware._run_asgi3
99
99
  return await middleware(scope, receive, send)
100
100
 
101
101
  Quart.__call__ = sentry_patched_asgi_app
@@ -24,7 +24,6 @@ from sentry_sdk.utils import (
24
24
  capture_internal_exceptions,
25
25
  ensure_integration_enabled,
26
26
  event_from_exception,
27
- logger,
28
27
  parse_version,
29
28
  transaction_from_function,
30
29
  )
@@ -388,9 +387,9 @@ def patch_asgi_app() -> None:
388
387
  if integration
389
388
  else DEFAULT_HTTP_METHODS_TO_CAPTURE
390
389
  ),
390
+ asgi_version=3,
391
391
  )
392
392
 
393
- middleware.__call__ = middleware._run_asgi3
394
393
  return await middleware(scope, receive, send)
395
394
 
396
395
  Starlette.__call__ = _sentry_patched_asgi_app
@@ -698,9 +697,6 @@ def _set_transaction_name_and_source(
698
697
  source = TransactionSource.ROUTE
699
698
 
700
699
  scope.set_transaction_name(name, source=source)
701
- logger.debug(
702
- "[Starlette] Set transaction name and source on scope: %s / %s", name, source
703
- )
704
700
 
705
701
 
706
702
  def _get_transaction_from_middleware(
@@ -17,7 +17,7 @@ try:
17
17
  from starlite.plugins.base import get_plugin_for_value # type: ignore
18
18
  from starlite.routes.http import HTTPRoute # type: ignore
19
19
  from starlite.utils import ConnectionDataExtractor, is_async_callable, Ref # type: ignore
20
- from pydantic import BaseModel
20
+ from pydantic import BaseModel # type: ignore
21
21
  except ImportError:
22
22
  raise DidNotEnable("Starlite is not installed")
23
23
 
@@ -65,6 +65,7 @@ class SentryStarliteASGIMiddleware(SentryAsgiMiddleware):
65
65
  transaction_style="endpoint",
66
66
  mechanism_type="asgi",
67
67
  span_origin=span_origin,
68
+ asgi_version=3,
68
69
  )
69
70
 
70
71
 
@@ -92,7 +93,6 @@ def patch_app_init() -> None:
92
93
  ]
93
94
  )
94
95
 
95
- SentryStarliteASGIMiddleware.__call__ = SentryStarliteASGIMiddleware._run_asgi3 # type: ignore
96
96
  middleware = kwargs.get("middleware") or []
97
97
  kwargs["middleware"] = [SentryStarliteASGIMiddleware, *middleware]
98
98
  old__init__(self, *args, **kwargs)
sentry_sdk/scope.py CHANGED
@@ -61,7 +61,7 @@ if TYPE_CHECKING:
61
61
  Self,
62
62
  )
63
63
 
64
- from collections.abc import Mapping, MutableMapping
64
+ from collections.abc import Mapping
65
65
 
66
66
  import sentry_sdk
67
67
  from sentry_sdk._types import (
@@ -201,24 +201,24 @@ class Scope:
201
201
  rv._name = self._name
202
202
  rv._fingerprint = self._fingerprint
203
203
  rv._transaction = self._transaction
204
- rv._transaction_info = dict(self._transaction_info)
204
+ rv._transaction_info = self._transaction_info.copy()
205
205
  rv._user = self._user
206
206
 
207
- rv._tags = dict(self._tags)
208
- rv._contexts = dict(self._contexts)
209
- rv._extras = dict(self._extras)
207
+ rv._tags = self._tags.copy()
208
+ rv._contexts = self._contexts.copy()
209
+ rv._extras = self._extras.copy()
210
210
 
211
211
  rv._breadcrumbs = copy(self._breadcrumbs)
212
- rv._n_breadcrumbs_truncated = copy(self._n_breadcrumbs_truncated)
213
- rv._event_processors = list(self._event_processors)
214
- rv._error_processors = list(self._error_processors)
212
+ rv._n_breadcrumbs_truncated = self._n_breadcrumbs_truncated
213
+ rv._event_processors = self._event_processors.copy()
214
+ rv._error_processors = self._error_processors.copy()
215
215
  rv._propagation_context = self._propagation_context
216
216
 
217
217
  rv._should_capture = self._should_capture
218
218
  rv._span = self._span
219
219
  rv._session = self._session
220
220
  rv._force_auto_session_tracking = self._force_auto_session_tracking
221
- rv._attachments = list(self._attachments)
221
+ rv._attachments = self._attachments.copy()
222
222
 
223
223
  rv._profile = self._profile
224
224
 
@@ -627,12 +627,12 @@ class Scope:
627
627
  self._level: Optional[LogLevelStr] = None
628
628
  self._fingerprint: Optional[List[str]] = None
629
629
  self._transaction: Optional[str] = None
630
- self._transaction_info: MutableMapping[str, str] = {}
630
+ self._transaction_info: Dict[str, str] = {}
631
631
  self._user: Optional[Dict[str, Any]] = None
632
632
 
633
633
  self._tags: Dict[str, Any] = {}
634
634
  self._contexts: Dict[str, Dict[str, Any]] = {}
635
- self._extras: MutableMapping[str, Any] = {}
635
+ self._extras: Dict[str, Any] = {}
636
636
  self._attachments: List[Attachment] = []
637
637
 
638
638
  self.clear_breadcrumbs()
sentry_sdk/tracing.py CHANGED
@@ -23,6 +23,7 @@ from sentry_sdk.consts import (
23
23
  SENTRY_TRACE_HEADER_NAME,
24
24
  SPANSTATUS,
25
25
  SPANDATA,
26
+ SPANTEMPLATE,
26
27
  TransactionSource,
27
28
  )
28
29
  from sentry_sdk.opentelemetry.consts import (
@@ -278,6 +279,14 @@ class Span:
278
279
  self.finish()
279
280
  self.deactivate()
280
281
 
282
+ async def __aenter__(self) -> Span:
283
+ return self.__enter__()
284
+
285
+ async def __aexit__(
286
+ self, ty: Optional[Any], value: Optional[Any], tb: Optional[Any]
287
+ ) -> None:
288
+ return self.__exit__(ty, value, tb)
289
+
281
290
  @property
282
291
  def description(self) -> Optional[str]:
283
292
  return self.get_attribute(SentrySpanAttribute.DESCRIPTION)
@@ -543,39 +552,107 @@ Transaction = Span
543
552
  if TYPE_CHECKING:
544
553
 
545
554
  @overload
546
- def trace(func: None = None) -> Callable[[Callable[P, R]], Callable[P, R]]:
555
+ def trace(
556
+ func: Optional[Callable[P, R]] = None,
557
+ *,
558
+ op: Optional[str] = None,
559
+ name: Optional[str] = None,
560
+ attributes: Optional[dict[str, Any]] = None,
561
+ template: SPANTEMPLATE = SPANTEMPLATE.DEFAULT,
562
+ ) -> Union[Callable[P, R], Callable[[Callable[P, R]], Callable[P, R]]]:
563
+ # Handles: @trace() and @trace(op="custom")
547
564
  pass
548
565
 
549
566
  @overload
550
567
  def trace(func: Callable[P, R]) -> Callable[P, R]:
568
+ # Handles: @trace
551
569
  pass
552
570
 
553
571
 
554
572
  def trace(
555
573
  func: Optional[Callable[P, R]] = None,
574
+ *,
575
+ op: Optional[str] = None,
576
+ name: Optional[str] = None,
577
+ attributes: Optional[dict[str, Any]] = None,
578
+ template: SPANTEMPLATE = SPANTEMPLATE.DEFAULT,
556
579
  ) -> Union[Callable[P, R], Callable[[Callable[P, R]], Callable[P, R]]]:
557
580
  """
558
- Decorator to start a child span under the existing current transaction.
559
- If there is no current transaction, then nothing will be traced.
560
-
561
- .. code-block::
562
- :caption: Usage
581
+ Decorator to start a child span around a function call.
582
+
583
+ This decorator automatically creates a new span when the decorated function
584
+ is called, and finishes the span when the function returns or raises an exception.
585
+
586
+ :param func: The function to trace. When used as a decorator without parentheses,
587
+ this is the function being decorated. When used with parameters (e.g.,
588
+ ``@trace(op="custom")``, this should be None.
589
+ :type func: Callable or None
590
+
591
+ :param op: The operation name for the span. This is a high-level description
592
+ of what the span represents (e.g., "http.client", "db.query").
593
+ You can use predefined constants from :py:class:`sentry_sdk.consts.OP`
594
+ or provide your own string. If not provided, a default operation will
595
+ be assigned based on the template.
596
+ :type op: str or None
597
+
598
+ :param name: The human-readable name/description for the span. If not provided,
599
+ defaults to the function name. This provides more specific details about
600
+ what the span represents (e.g., "GET /api/users", "process_user_data").
601
+ :type name: str or None
602
+
603
+ :param attributes: A dictionary of key-value pairs to add as attributes to the span.
604
+ Attribute values must be strings, integers, floats, or booleans. These
605
+ attributes provide additional context about the span's execution.
606
+ :type attributes: dict[str, Any] or None
607
+
608
+ :param template: The type of span to create. This determines what kind of
609
+ span instrumentation and data collection will be applied. Use predefined
610
+ constants from :py:class:`sentry_sdk.consts.SPANTEMPLATE`.
611
+ The default is `SPANTEMPLATE.DEFAULT` which is the right choice for most
612
+ use cases.
613
+ :type template: :py:class:`sentry_sdk.consts.SPANTEMPLATE`
614
+
615
+ :returns: When used as ``@trace``, returns the decorated function. When used as
616
+ ``@trace(...)`` with parameters, returns a decorator function.
617
+ :rtype: Callable or decorator function
618
+
619
+ Example::
563
620
 
564
621
  import sentry_sdk
622
+ from sentry_sdk.consts import OP, SPANTEMPLATE
565
623
 
624
+ # Simple usage with default values
566
625
  @sentry_sdk.trace
567
- def my_function():
568
- ...
569
-
570
- @sentry_sdk.trace
571
- async def my_async_function():
572
- ...
626
+ def process_data():
627
+ # Function implementation
628
+ pass
629
+
630
+ # With custom parameters
631
+ @sentry_sdk.trace(
632
+ op=OP.DB_QUERY,
633
+ name="Get user data",
634
+ attributes={"postgres": True}
635
+ )
636
+ def make_db_query(sql):
637
+ # Function implementation
638
+ pass
639
+
640
+ # With a custom template
641
+ @sentry_sdk.trace(template=SPANTEMPLATE.AI_TOOL)
642
+ def calculate_interest_rate(amount, rate, years):
643
+ # Function implementation
644
+ pass
573
645
  """
574
- from sentry_sdk.tracing_utils import start_child_span_decorator
646
+ from sentry_sdk.tracing_utils import create_span_decorator
647
+
648
+ decorator = create_span_decorator(
649
+ op=op,
650
+ name=name,
651
+ attributes=attributes,
652
+ template=template,
653
+ )
575
654
 
576
- # This patterns allows usage of both @sentry_traced and @sentry_traced(...)
577
- # See https://stackoverflow.com/questions/52126071/decorator-with-arguments-avoid-parenthesis-when-no-arguments/52126278
578
655
  if func:
579
- return start_child_span_decorator(func)
656
+ return decorator(func)
580
657
  else:
581
- return start_child_span_decorator
658
+ return decorator