sentry-sdk 2.26.1__py2.py3-none-any.whl → 3.0.0a1__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/__init__.py +4 -8
- sentry_sdk/_compat.py +0 -1
- sentry_sdk/_init_implementation.py +6 -44
- sentry_sdk/_log_batcher.py +47 -28
- sentry_sdk/_types.py +8 -64
- sentry_sdk/ai/monitoring.py +14 -10
- sentry_sdk/ai/utils.py +1 -1
- sentry_sdk/api.py +69 -163
- sentry_sdk/client.py +25 -72
- sentry_sdk/consts.py +42 -23
- sentry_sdk/debug.py +0 -10
- sentry_sdk/envelope.py +2 -10
- sentry_sdk/feature_flags.py +5 -1
- sentry_sdk/integrations/__init__.py +5 -2
- sentry_sdk/integrations/_asgi_common.py +3 -3
- sentry_sdk/integrations/_wsgi_common.py +11 -40
- sentry_sdk/integrations/aiohttp.py +104 -57
- sentry_sdk/integrations/anthropic.py +10 -7
- sentry_sdk/integrations/arq.py +24 -13
- sentry_sdk/integrations/asgi.py +103 -83
- sentry_sdk/integrations/asyncio.py +1 -0
- sentry_sdk/integrations/asyncpg.py +45 -30
- sentry_sdk/integrations/aws_lambda.py +109 -92
- sentry_sdk/integrations/boto3.py +38 -9
- sentry_sdk/integrations/bottle.py +1 -1
- sentry_sdk/integrations/celery/__init__.py +48 -38
- sentry_sdk/integrations/clickhouse_driver.py +59 -28
- sentry_sdk/integrations/cohere.py +2 -0
- sentry_sdk/integrations/django/__init__.py +25 -46
- sentry_sdk/integrations/django/asgi.py +6 -2
- sentry_sdk/integrations/django/caching.py +13 -22
- sentry_sdk/integrations/django/middleware.py +1 -0
- sentry_sdk/integrations/django/signals_handlers.py +3 -1
- sentry_sdk/integrations/django/templates.py +8 -12
- sentry_sdk/integrations/django/transactions.py +1 -6
- sentry_sdk/integrations/django/views.py +5 -2
- sentry_sdk/integrations/falcon.py +7 -25
- sentry_sdk/integrations/fastapi.py +3 -3
- sentry_sdk/integrations/flask.py +1 -1
- sentry_sdk/integrations/gcp.py +63 -38
- sentry_sdk/integrations/graphene.py +6 -13
- sentry_sdk/integrations/grpc/aio/client.py +14 -8
- sentry_sdk/integrations/grpc/aio/server.py +19 -21
- sentry_sdk/integrations/grpc/client.py +8 -6
- sentry_sdk/integrations/grpc/server.py +12 -14
- sentry_sdk/integrations/httpx.py +47 -12
- sentry_sdk/integrations/huey.py +26 -22
- sentry_sdk/integrations/huggingface_hub.py +1 -0
- sentry_sdk/integrations/langchain.py +22 -15
- sentry_sdk/integrations/launchdarkly.py +3 -3
- sentry_sdk/integrations/litestar.py +4 -2
- sentry_sdk/integrations/logging.py +12 -3
- sentry_sdk/integrations/openai.py +2 -0
- sentry_sdk/integrations/openfeature.py +3 -5
- sentry_sdk/integrations/pymongo.py +18 -25
- sentry_sdk/integrations/pyramid.py +1 -1
- sentry_sdk/integrations/quart.py +3 -3
- sentry_sdk/integrations/ray.py +23 -17
- sentry_sdk/integrations/redis/_async_common.py +30 -18
- sentry_sdk/integrations/redis/_sync_common.py +28 -18
- sentry_sdk/integrations/redis/modules/caches.py +13 -10
- sentry_sdk/integrations/redis/modules/queries.py +14 -11
- sentry_sdk/integrations/redis/rb.py +4 -4
- sentry_sdk/integrations/redis/redis.py +6 -6
- sentry_sdk/integrations/redis/redis_cluster.py +18 -16
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +4 -4
- sentry_sdk/integrations/redis/utils.py +63 -19
- sentry_sdk/integrations/rq.py +68 -23
- sentry_sdk/integrations/rust_tracing.py +28 -43
- sentry_sdk/integrations/sanic.py +23 -13
- sentry_sdk/integrations/socket.py +9 -5
- sentry_sdk/integrations/sqlalchemy.py +8 -8
- sentry_sdk/integrations/starlette.py +11 -31
- sentry_sdk/integrations/starlite.py +4 -2
- sentry_sdk/integrations/stdlib.py +56 -9
- sentry_sdk/integrations/strawberry.py +40 -59
- sentry_sdk/integrations/threading.py +10 -26
- sentry_sdk/integrations/tornado.py +57 -18
- sentry_sdk/integrations/trytond.py +4 -1
- sentry_sdk/integrations/unleash.py +2 -3
- sentry_sdk/integrations/wsgi.py +84 -38
- sentry_sdk/opentelemetry/__init__.py +9 -0
- sentry_sdk/opentelemetry/consts.py +33 -0
- sentry_sdk/opentelemetry/contextvars_context.py +73 -0
- sentry_sdk/{integrations/opentelemetry → opentelemetry}/propagator.py +19 -28
- sentry_sdk/opentelemetry/sampler.py +326 -0
- sentry_sdk/opentelemetry/scope.py +218 -0
- sentry_sdk/opentelemetry/span_processor.py +329 -0
- sentry_sdk/opentelemetry/tracing.py +35 -0
- sentry_sdk/opentelemetry/utils.py +476 -0
- sentry_sdk/profiler/__init__.py +0 -40
- sentry_sdk/profiler/continuous_profiler.py +1 -30
- sentry_sdk/profiler/transaction_profiler.py +5 -56
- sentry_sdk/scope.py +107 -351
- sentry_sdk/sessions.py +0 -87
- sentry_sdk/tracing.py +418 -1134
- sentry_sdk/tracing_utils.py +134 -169
- sentry_sdk/transport.py +4 -104
- sentry_sdk/types.py +26 -2
- sentry_sdk/utils.py +169 -152
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/METADATA +3 -5
- sentry_sdk-3.0.0a1.dist-info/RECORD +154 -0
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/WHEEL +1 -1
- sentry_sdk-3.0.0a1.dist-info/entry_points.txt +2 -0
- sentry_sdk/hub.py +0 -739
- sentry_sdk/integrations/opentelemetry/__init__.py +0 -7
- sentry_sdk/integrations/opentelemetry/consts.py +0 -5
- sentry_sdk/integrations/opentelemetry/integration.py +0 -58
- sentry_sdk/integrations/opentelemetry/span_processor.py +0 -391
- sentry_sdk/metrics.py +0 -965
- sentry_sdk-2.26.1.dist-info/RECORD +0 -152
- sentry_sdk-2.26.1.dist-info/entry_points.txt +0 -2
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/top_level.txt +0 -0
sentry_sdk/__init__.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# TODO-neel scope switch
|
|
2
|
+
# TODO-neel avoid duplication between api and __init__
|
|
3
|
+
from sentry_sdk.opentelemetry.scope import PotelScope as Scope
|
|
2
4
|
from sentry_sdk.transport import Transport, HttpTransport
|
|
3
5
|
from sentry_sdk.client import Client
|
|
4
6
|
|
|
@@ -7,7 +9,6 @@ from sentry_sdk.api import * # noqa
|
|
|
7
9
|
from sentry_sdk.consts import VERSION # noqa
|
|
8
10
|
|
|
9
11
|
__all__ = [ # noqa
|
|
10
|
-
"Hub",
|
|
11
12
|
"Scope",
|
|
12
13
|
"Client",
|
|
13
14
|
"Transport",
|
|
@@ -15,11 +16,11 @@ __all__ = [ # noqa
|
|
|
15
16
|
"integrations",
|
|
16
17
|
# From sentry_sdk.api
|
|
17
18
|
"init",
|
|
19
|
+
"add_attachment",
|
|
18
20
|
"add_breadcrumb",
|
|
19
21
|
"capture_event",
|
|
20
22
|
"capture_exception",
|
|
21
23
|
"capture_message",
|
|
22
|
-
"configure_scope",
|
|
23
24
|
"continue_trace",
|
|
24
25
|
"flush",
|
|
25
26
|
"get_baggage",
|
|
@@ -33,11 +34,9 @@ __all__ = [ # noqa
|
|
|
33
34
|
"isolation_scope",
|
|
34
35
|
"last_event_id",
|
|
35
36
|
"new_scope",
|
|
36
|
-
"push_scope",
|
|
37
37
|
"set_context",
|
|
38
38
|
"set_extra",
|
|
39
39
|
"set_level",
|
|
40
|
-
"set_measurement",
|
|
41
40
|
"set_tag",
|
|
42
41
|
"set_tags",
|
|
43
42
|
"set_user",
|
|
@@ -53,6 +52,3 @@ from sentry_sdk.debug import init_debug_support
|
|
|
53
52
|
|
|
54
53
|
init_debug_support()
|
|
55
54
|
del init_debug_support
|
|
56
|
-
|
|
57
|
-
# circular imports
|
|
58
|
-
from sentry_sdk.hub import Hub
|
sentry_sdk/_compat.py
CHANGED
|
@@ -9,7 +9,6 @@ if TYPE_CHECKING:
|
|
|
9
9
|
T = TypeVar("T")
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
PY37 = sys.version_info[0] == 3 and sys.version_info[1] >= 7
|
|
13
12
|
PY38 = sys.version_info[0] == 3 and sys.version_info[1] >= 8
|
|
14
13
|
PY310 = sys.version_info[0] == 3 and sys.version_info[1] >= 10
|
|
15
14
|
PY311 = sys.version_info[0] == 3 and sys.version_info[1] >= 11
|
|
@@ -1,48 +1,11 @@
|
|
|
1
|
-
import warnings
|
|
2
|
-
|
|
3
1
|
from typing import TYPE_CHECKING
|
|
4
2
|
|
|
5
3
|
import sentry_sdk
|
|
4
|
+
from sentry_sdk.consts import ClientConstructor
|
|
5
|
+
from sentry_sdk.opentelemetry.scope import setup_scope_context_management
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from typing import Any,
|
|
9
|
-
|
|
10
|
-
import sentry_sdk.consts
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class _InitGuard:
|
|
14
|
-
_CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE = (
|
|
15
|
-
"Using the return value of sentry_sdk.init as a context manager "
|
|
16
|
-
"and manually calling the __enter__ and __exit__ methods on the "
|
|
17
|
-
"return value are deprecated. We are no longer maintaining this "
|
|
18
|
-
"functionality, and we will remove it in the next major release."
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
def __init__(self, client):
|
|
22
|
-
# type: (sentry_sdk.Client) -> None
|
|
23
|
-
self._client = client
|
|
24
|
-
|
|
25
|
-
def __enter__(self):
|
|
26
|
-
# type: () -> _InitGuard
|
|
27
|
-
warnings.warn(
|
|
28
|
-
self._CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE,
|
|
29
|
-
stacklevel=2,
|
|
30
|
-
category=DeprecationWarning,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
return self
|
|
34
|
-
|
|
35
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
36
|
-
# type: (Any, Any, Any) -> None
|
|
37
|
-
warnings.warn(
|
|
38
|
-
self._CONTEXT_MANAGER_DEPRECATION_WARNING_MESSAGE,
|
|
39
|
-
stacklevel=2,
|
|
40
|
-
category=DeprecationWarning,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
c = self._client
|
|
44
|
-
if c is not None:
|
|
45
|
-
c.close()
|
|
8
|
+
from typing import Any, Optional
|
|
46
9
|
|
|
47
10
|
|
|
48
11
|
def _check_python_deprecations():
|
|
@@ -54,16 +17,15 @@ def _check_python_deprecations():
|
|
|
54
17
|
|
|
55
18
|
|
|
56
19
|
def _init(*args, **kwargs):
|
|
57
|
-
# type: (*Optional[str], **Any) ->
|
|
20
|
+
# type: (*Optional[str], **Any) -> None
|
|
58
21
|
"""Initializes the SDK and optionally integrations.
|
|
59
22
|
|
|
60
23
|
This takes the same arguments as the client constructor.
|
|
61
24
|
"""
|
|
25
|
+
setup_scope_context_management()
|
|
62
26
|
client = sentry_sdk.Client(*args, **kwargs)
|
|
63
27
|
sentry_sdk.get_global_scope().set_client(client)
|
|
64
28
|
_check_python_deprecations()
|
|
65
|
-
rv = _InitGuard(client)
|
|
66
|
-
return rv
|
|
67
29
|
|
|
68
30
|
|
|
69
31
|
if TYPE_CHECKING:
|
|
@@ -73,7 +35,7 @@ if TYPE_CHECKING:
|
|
|
73
35
|
# Use `ClientConstructor` to define the argument types of `init` and
|
|
74
36
|
# `ContextManager[Any]` to tell static analyzers about the return type.
|
|
75
37
|
|
|
76
|
-
class init(
|
|
38
|
+
class init(ClientConstructor): # noqa: N801
|
|
77
39
|
pass
|
|
78
40
|
|
|
79
41
|
else:
|
sentry_sdk/_log_batcher.py
CHANGED
|
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
|
|
5
5
|
from typing import Optional, List, Callable, TYPE_CHECKING, Any
|
|
6
6
|
|
|
7
7
|
from sentry_sdk.utils import format_timestamp, safe_repr
|
|
8
|
-
from sentry_sdk.envelope import Envelope
|
|
8
|
+
from sentry_sdk.envelope import Envelope, Item, PayloadRef
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from sentry_sdk._types import Log
|
|
@@ -97,34 +97,36 @@ class LogBatcher:
|
|
|
97
97
|
self._flush()
|
|
98
98
|
|
|
99
99
|
@staticmethod
|
|
100
|
-
def
|
|
100
|
+
def _log_to_transport_format(log):
|
|
101
101
|
# type: (Log) -> Any
|
|
102
|
-
def format_attribute(
|
|
103
|
-
# type: (
|
|
102
|
+
def format_attribute(val):
|
|
103
|
+
# type: (int | float | str | bool) -> Any
|
|
104
104
|
if isinstance(val, bool):
|
|
105
|
-
return {"
|
|
105
|
+
return {"value": val, "type": "boolean"}
|
|
106
106
|
if isinstance(val, int):
|
|
107
|
-
return {"
|
|
107
|
+
return {"value": val, "type": "integer"}
|
|
108
108
|
if isinstance(val, float):
|
|
109
|
-
return {"
|
|
109
|
+
return {"value": val, "type": "double"}
|
|
110
110
|
if isinstance(val, str):
|
|
111
|
-
return {"
|
|
112
|
-
return {"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
"
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
return {"value": val, "type": "string"}
|
|
112
|
+
return {"value": safe_repr(val), "type": "string"}
|
|
113
|
+
|
|
114
|
+
if "sentry.severity_number" not in log["attributes"]:
|
|
115
|
+
log["attributes"]["sentry.severity_number"] = log["severity_number"]
|
|
116
|
+
if "sentry.severity_text" not in log["attributes"]:
|
|
117
|
+
log["attributes"]["sentry.severity_text"] = log["severity_text"]
|
|
118
|
+
|
|
119
|
+
res = {
|
|
120
|
+
"timestamp": int(log["time_unix_nano"]) / 1.0e9,
|
|
121
|
+
"trace_id": log.get("trace_id", "00000000-0000-0000-0000-000000000000"),
|
|
122
|
+
"level": str(log["severity_text"]),
|
|
123
|
+
"body": str(log["body"]),
|
|
124
|
+
"attributes": {
|
|
125
|
+
k: format_attribute(v) for (k, v) in log["attributes"].items()
|
|
126
|
+
},
|
|
122
127
|
}
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
otel_log["traceId"] = log["trace_id"]
|
|
126
|
-
|
|
127
|
-
return otel_log
|
|
129
|
+
return res
|
|
128
130
|
|
|
129
131
|
def _flush(self):
|
|
130
132
|
# type: (...) -> Optional[Envelope]
|
|
@@ -133,10 +135,27 @@ class LogBatcher:
|
|
|
133
135
|
headers={"sent_at": format_timestamp(datetime.now(timezone.utc))}
|
|
134
136
|
)
|
|
135
137
|
with self._lock:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
if len(self._log_buffer) == 0:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
envelope.add_item(
|
|
142
|
+
Item(
|
|
143
|
+
type="log",
|
|
144
|
+
content_type="application/vnd.sentry.items.log+json",
|
|
145
|
+
headers={
|
|
146
|
+
"item_count": len(self._log_buffer),
|
|
147
|
+
},
|
|
148
|
+
payload=PayloadRef(
|
|
149
|
+
json={
|
|
150
|
+
"items": [
|
|
151
|
+
self._log_to_transport_format(log)
|
|
152
|
+
for log in self._log_buffer
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
)
|
|
157
|
+
)
|
|
138
158
|
self._log_buffer.clear()
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return None
|
|
159
|
+
|
|
160
|
+
self._capture_func(envelope)
|
|
161
|
+
return envelope
|
sentry_sdk/_types.py
CHANGED
|
@@ -107,9 +107,7 @@ if TYPE_CHECKING:
|
|
|
107
107
|
from typing import Callable
|
|
108
108
|
from typing import Dict
|
|
109
109
|
from typing import Mapping
|
|
110
|
-
from typing import NotRequired
|
|
111
110
|
from typing import Optional
|
|
112
|
-
from typing import Tuple
|
|
113
111
|
from typing import Type
|
|
114
112
|
from typing_extensions import Literal, TypedDict
|
|
115
113
|
|
|
@@ -121,45 +119,6 @@ if TYPE_CHECKING:
|
|
|
121
119
|
# "critical" is an alias of "fatal" recognized by Relay
|
|
122
120
|
LogLevelStr = Literal["fatal", "critical", "error", "warning", "info", "debug"]
|
|
123
121
|
|
|
124
|
-
DurationUnit = Literal[
|
|
125
|
-
"nanosecond",
|
|
126
|
-
"microsecond",
|
|
127
|
-
"millisecond",
|
|
128
|
-
"second",
|
|
129
|
-
"minute",
|
|
130
|
-
"hour",
|
|
131
|
-
"day",
|
|
132
|
-
"week",
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
InformationUnit = Literal[
|
|
136
|
-
"bit",
|
|
137
|
-
"byte",
|
|
138
|
-
"kilobyte",
|
|
139
|
-
"kibibyte",
|
|
140
|
-
"megabyte",
|
|
141
|
-
"mebibyte",
|
|
142
|
-
"gigabyte",
|
|
143
|
-
"gibibyte",
|
|
144
|
-
"terabyte",
|
|
145
|
-
"tebibyte",
|
|
146
|
-
"petabyte",
|
|
147
|
-
"pebibyte",
|
|
148
|
-
"exabyte",
|
|
149
|
-
"exbibyte",
|
|
150
|
-
]
|
|
151
|
-
|
|
152
|
-
FractionUnit = Literal["ratio", "percent"]
|
|
153
|
-
MeasurementUnit = Union[DurationUnit, InformationUnit, FractionUnit, str]
|
|
154
|
-
|
|
155
|
-
MeasurementValue = TypedDict(
|
|
156
|
-
"MeasurementValue",
|
|
157
|
-
{
|
|
158
|
-
"value": float,
|
|
159
|
-
"unit": NotRequired[Optional[MeasurementUnit]],
|
|
160
|
-
},
|
|
161
|
-
)
|
|
162
|
-
|
|
163
122
|
Event = TypedDict(
|
|
164
123
|
"Event",
|
|
165
124
|
{
|
|
@@ -181,7 +140,6 @@ if TYPE_CHECKING:
|
|
|
181
140
|
"level": LogLevelStr,
|
|
182
141
|
"logentry": Mapping[str, object],
|
|
183
142
|
"logger": str,
|
|
184
|
-
"measurements": dict[str, MeasurementValue],
|
|
185
143
|
"message": str,
|
|
186
144
|
"modules": dict[str, str],
|
|
187
145
|
"monitor_config": Mapping[str, object],
|
|
@@ -210,7 +168,6 @@ if TYPE_CHECKING:
|
|
|
210
168
|
"type": Literal["check_in", "transaction"],
|
|
211
169
|
"user": dict[str, object],
|
|
212
170
|
"_dropped_spans": int,
|
|
213
|
-
"_metrics_summary": dict[str, object],
|
|
214
171
|
},
|
|
215
172
|
total=False,
|
|
216
173
|
)
|
|
@@ -220,7 +177,9 @@ if TYPE_CHECKING:
|
|
|
220
177
|
tuple[None, None, None],
|
|
221
178
|
]
|
|
222
179
|
|
|
180
|
+
# TODO: Make a proper type definition for this (PRs welcome!)
|
|
223
181
|
Hint = Dict[str, Any]
|
|
182
|
+
|
|
224
183
|
Log = TypedDict(
|
|
225
184
|
"Log",
|
|
226
185
|
{
|
|
@@ -233,9 +192,13 @@ if TYPE_CHECKING:
|
|
|
233
192
|
},
|
|
234
193
|
)
|
|
235
194
|
|
|
195
|
+
# TODO: Make a proper type definition for this (PRs welcome!)
|
|
236
196
|
Breadcrumb = Dict[str, Any]
|
|
197
|
+
|
|
198
|
+
# TODO: Make a proper type definition for this (PRs welcome!)
|
|
237
199
|
BreadcrumbHint = Dict[str, Any]
|
|
238
200
|
|
|
201
|
+
# TODO: Make a proper type definition for this (PRs welcome!)
|
|
239
202
|
SamplingContext = Dict[str, Any]
|
|
240
203
|
|
|
241
204
|
EventProcessor = Callable[[Event, Hint], Optional[Event]]
|
|
@@ -260,7 +223,6 @@ if TYPE_CHECKING:
|
|
|
260
223
|
"internal",
|
|
261
224
|
"profile",
|
|
262
225
|
"profile_chunk",
|
|
263
|
-
"metric_bucket",
|
|
264
226
|
"monitor",
|
|
265
227
|
"span",
|
|
266
228
|
"log",
|
|
@@ -270,26 +232,6 @@ if TYPE_CHECKING:
|
|
|
270
232
|
ContinuousProfilerMode = Literal["thread", "gevent", "unknown"]
|
|
271
233
|
ProfilerMode = Union[ContinuousProfilerMode, Literal["sleep"]]
|
|
272
234
|
|
|
273
|
-
# Type of the metric.
|
|
274
|
-
MetricType = Literal["d", "s", "g", "c"]
|
|
275
|
-
|
|
276
|
-
# Value of the metric.
|
|
277
|
-
MetricValue = Union[int, float, str]
|
|
278
|
-
|
|
279
|
-
# Internal representation of tags as a tuple of tuples (this is done in order to allow for the same key to exist
|
|
280
|
-
# multiple times).
|
|
281
|
-
MetricTagsInternal = Tuple[Tuple[str, str], ...]
|
|
282
|
-
|
|
283
|
-
# External representation of tags as a dictionary.
|
|
284
|
-
MetricTagValue = Union[str, int, float, None]
|
|
285
|
-
MetricTags = Mapping[str, MetricTagValue]
|
|
286
|
-
|
|
287
|
-
# Value inside the generator for the metric value.
|
|
288
|
-
FlushedMetricValue = Union[int, float]
|
|
289
|
-
|
|
290
|
-
BucketKey = Tuple[MetricType, str, MeasurementUnit, MetricTagsInternal]
|
|
291
|
-
MetricMetaKey = Tuple[MetricType, str, MeasurementUnit]
|
|
292
|
-
|
|
293
235
|
MonitorConfigScheduleType = Literal["crontab", "interval"]
|
|
294
236
|
MonitorConfigScheduleUnit = Literal[
|
|
295
237
|
"year",
|
|
@@ -325,3 +267,5 @@ if TYPE_CHECKING:
|
|
|
325
267
|
)
|
|
326
268
|
|
|
327
269
|
HttpStatusCodeRange = Union[int, Container[int]]
|
|
270
|
+
|
|
271
|
+
OtelExtractedSpanData = tuple[str, str, Optional[str], Optional[int], Optional[str]]
|
sentry_sdk/ai/monitoring.py
CHANGED
|
@@ -33,13 +33,15 @@ def ai_track(description, **span_kwargs):
|
|
|
33
33
|
curr_pipeline = _ai_pipeline_name.get()
|
|
34
34
|
op = span_kwargs.get("op", "ai.run" if curr_pipeline else "ai.pipeline")
|
|
35
35
|
|
|
36
|
-
with start_span(
|
|
36
|
+
with start_span(
|
|
37
|
+
name=description, op=op, only_if_parent=True, **span_kwargs
|
|
38
|
+
) as span:
|
|
37
39
|
for k, v in kwargs.pop("sentry_tags", {}).items():
|
|
38
40
|
span.set_tag(k, v)
|
|
39
41
|
for k, v in kwargs.pop("sentry_data", {}).items():
|
|
40
|
-
span.
|
|
42
|
+
span.set_attribute(k, v)
|
|
41
43
|
if curr_pipeline:
|
|
42
|
-
span.
|
|
44
|
+
span.set_attribute("ai.pipeline.name", curr_pipeline)
|
|
43
45
|
return f(*args, **kwargs)
|
|
44
46
|
else:
|
|
45
47
|
_ai_pipeline_name.set(description)
|
|
@@ -62,13 +64,15 @@ def ai_track(description, **span_kwargs):
|
|
|
62
64
|
curr_pipeline = _ai_pipeline_name.get()
|
|
63
65
|
op = span_kwargs.get("op", "ai.run" if curr_pipeline else "ai.pipeline")
|
|
64
66
|
|
|
65
|
-
with start_span(
|
|
67
|
+
with start_span(
|
|
68
|
+
name=description, op=op, only_if_parent=True, **span_kwargs
|
|
69
|
+
) as span:
|
|
66
70
|
for k, v in kwargs.pop("sentry_tags", {}).items():
|
|
67
71
|
span.set_tag(k, v)
|
|
68
72
|
for k, v in kwargs.pop("sentry_data", {}).items():
|
|
69
|
-
span.
|
|
73
|
+
span.set_attribute(k, v)
|
|
70
74
|
if curr_pipeline:
|
|
71
|
-
span.
|
|
75
|
+
span.set_attribute("ai.pipeline.name", curr_pipeline)
|
|
72
76
|
return await f(*args, **kwargs)
|
|
73
77
|
else:
|
|
74
78
|
_ai_pipeline_name.set(description)
|
|
@@ -100,11 +104,11 @@ def record_token_usage(
|
|
|
100
104
|
# type: (Span, Optional[int], Optional[int], Optional[int]) -> None
|
|
101
105
|
ai_pipeline_name = get_ai_pipeline_name()
|
|
102
106
|
if ai_pipeline_name:
|
|
103
|
-
span.
|
|
107
|
+
span.set_attribute("ai.pipeline.name", ai_pipeline_name)
|
|
104
108
|
if prompt_tokens is not None:
|
|
105
|
-
span.
|
|
109
|
+
span.set_attribute("ai.prompt_tokens.used", prompt_tokens)
|
|
106
110
|
if completion_tokens is not None:
|
|
107
|
-
span.
|
|
111
|
+
span.set_attribute("ai.completion_tokens.used", completion_tokens)
|
|
108
112
|
if (
|
|
109
113
|
total_tokens is None
|
|
110
114
|
and prompt_tokens is not None
|
|
@@ -112,4 +116,4 @@ def record_token_usage(
|
|
|
112
116
|
):
|
|
113
117
|
total_tokens = prompt_tokens + completion_tokens
|
|
114
118
|
if total_tokens is not None:
|
|
115
|
-
span.
|
|
119
|
+
span.set_attribute("ai.total_tokens.used", total_tokens)
|
sentry_sdk/ai/utils.py
CHANGED