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.
- sentry_sdk/ai/utils.py +7 -8
- sentry_sdk/api.py +13 -2
- sentry_sdk/client.py +93 -17
- sentry_sdk/consts.py +14 -6
- sentry_sdk/crons/api.py +5 -0
- sentry_sdk/integrations/anthropic.py +133 -73
- sentry_sdk/integrations/asgi.py +10 -9
- sentry_sdk/integrations/asyncio.py +85 -20
- sentry_sdk/integrations/clickhouse_driver.py +55 -28
- sentry_sdk/integrations/fastapi.py +1 -7
- sentry_sdk/integrations/gnu_backtrace.py +6 -3
- sentry_sdk/integrations/langchain.py +462 -218
- sentry_sdk/integrations/litestar.py +1 -1
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +0 -2
- sentry_sdk/integrations/openai_agents/patches/runner.py +18 -15
- sentry_sdk/integrations/quart.py +1 -1
- sentry_sdk/integrations/starlette.py +1 -5
- sentry_sdk/integrations/starlite.py +2 -2
- sentry_sdk/scope.py +11 -11
- sentry_sdk/tracing.py +94 -17
- sentry_sdk/tracing_utils.py +330 -33
- sentry_sdk/transport.py +357 -62
- sentry_sdk/utils.py +23 -5
- sentry_sdk/worker.py +197 -3
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/METADATA +3 -1
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/RECORD +30 -30
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/WHEEL +0 -0
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a5.dist-info → sentry_sdk-3.0.0a6.dist-info}/top_level.txt +0 -0
|
@@ -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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
span
|
|
39
|
-
|
|
40
|
-
|
|
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
|
sentry_sdk/integrations/quart.py
CHANGED
|
@@ -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
|
|
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 =
|
|
204
|
+
rv._transaction_info = self._transaction_info.copy()
|
|
205
205
|
rv._user = self._user
|
|
206
206
|
|
|
207
|
-
rv._tags =
|
|
208
|
-
rv._contexts =
|
|
209
|
-
rv._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 =
|
|
213
|
-
rv._event_processors =
|
|
214
|
-
rv._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 =
|
|
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:
|
|
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:
|
|
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(
|
|
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
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
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
|
|
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
|
|
656
|
+
return decorator(func)
|
|
580
657
|
else:
|
|
581
|
-
return
|
|
658
|
+
return decorator
|