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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
|
-
import sentry_sdk
|
|
3
2
|
|
|
3
|
+
from sentry_sdk.feature_flags import add_feature_flag
|
|
4
4
|
from sentry_sdk.integrations import DidNotEnable, Integration
|
|
5
5
|
|
|
6
6
|
try:
|
|
@@ -53,8 +53,8 @@ class LaunchDarklyHook(Hook):
|
|
|
53
53
|
def after_evaluation(self, series_context, data, detail):
|
|
54
54
|
# type: (EvaluationSeriesContext, dict[Any, Any], EvaluationDetail) -> dict[Any, Any]
|
|
55
55
|
if isinstance(detail.value, bool):
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
add_feature_flag(series_context.key, detail.value)
|
|
57
|
+
|
|
58
58
|
return data
|
|
59
59
|
|
|
60
60
|
def before_evaluation(self, series_context, data):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Set
|
|
2
2
|
import sentry_sdk
|
|
3
|
-
from sentry_sdk.consts import OP
|
|
3
|
+
from sentry_sdk.consts import OP, TransactionSource, SOURCE_FOR_STYLE
|
|
4
4
|
from sentry_sdk.integrations import (
|
|
5
5
|
_DEFAULT_FAILED_REQUEST_STATUS_CODES,
|
|
6
6
|
DidNotEnable,
|
|
@@ -9,7 +9,6 @@ from sentry_sdk.integrations import (
|
|
|
9
9
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
|
10
10
|
from sentry_sdk.integrations.logging import ignore_logger
|
|
11
11
|
from sentry_sdk.scope import should_send_default_pii
|
|
12
|
-
from sentry_sdk.tracing import TransactionSource, SOURCE_FOR_STYLE
|
|
13
12
|
from sentry_sdk.utils import (
|
|
14
13
|
ensure_integration_enabled,
|
|
15
14
|
event_from_exception,
|
|
@@ -153,6 +152,7 @@ def enable_span_for_middleware(middleware):
|
|
|
153
152
|
op=OP.MIDDLEWARE_LITESTAR,
|
|
154
153
|
name=middleware_name,
|
|
155
154
|
origin=LitestarIntegration.origin,
|
|
155
|
+
only_if_parent=True,
|
|
156
156
|
) as middleware_span:
|
|
157
157
|
middleware_span.set_tag("litestar.middleware_name", middleware_name)
|
|
158
158
|
|
|
@@ -165,6 +165,7 @@ def enable_span_for_middleware(middleware):
|
|
|
165
165
|
op=OP.MIDDLEWARE_LITESTAR_RECEIVE,
|
|
166
166
|
name=getattr(receive, "__qualname__", str(receive)),
|
|
167
167
|
origin=LitestarIntegration.origin,
|
|
168
|
+
only_if_parent=True,
|
|
168
169
|
) as span:
|
|
169
170
|
span.set_tag("litestar.middleware_name", middleware_name)
|
|
170
171
|
return await receive(*args, **kwargs)
|
|
@@ -182,6 +183,7 @@ def enable_span_for_middleware(middleware):
|
|
|
182
183
|
op=OP.MIDDLEWARE_LITESTAR_SEND,
|
|
183
184
|
name=getattr(send, "__qualname__", str(send)),
|
|
184
185
|
origin=LitestarIntegration.origin,
|
|
186
|
+
only_if_parent=True,
|
|
185
187
|
) as span:
|
|
186
188
|
span.set_tag("litestar.middleware_name", middleware_name)
|
|
187
189
|
return await send(message)
|
|
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
|
|
|
24
24
|
from typing import Optional
|
|
25
25
|
|
|
26
26
|
DEFAULT_LEVEL = logging.INFO
|
|
27
|
-
DEFAULT_EVENT_LEVEL =
|
|
27
|
+
DEFAULT_EVENT_LEVEL = None # None means no events are captured
|
|
28
28
|
LOGGING_TO_EVENT_LEVEL = {
|
|
29
29
|
logging.NOTSET: "notset",
|
|
30
30
|
logging.DEBUG: "debug",
|
|
@@ -43,7 +43,12 @@ LOGGING_TO_EVENT_LEVEL = {
|
|
|
43
43
|
# Note: Ignoring by logger name here is better than mucking with thread-locals.
|
|
44
44
|
# We do not necessarily know whether thread-locals work 100% correctly in the user's environment.
|
|
45
45
|
_IGNORED_LOGGERS = set(
|
|
46
|
-
[
|
|
46
|
+
[
|
|
47
|
+
"sentry_sdk.errors",
|
|
48
|
+
"urllib3.connectionpool",
|
|
49
|
+
"urllib3.connection",
|
|
50
|
+
"opentelemetry.*",
|
|
51
|
+
]
|
|
47
52
|
)
|
|
48
53
|
|
|
49
54
|
|
|
@@ -355,6 +360,7 @@ class SentryLogsHandler(_BaseHandler):
|
|
|
355
360
|
# type: (BaseClient, LogRecord) -> None
|
|
356
361
|
scope = sentry_sdk.get_current_scope()
|
|
357
362
|
otel_severity_number, otel_severity_text = _python_level_to_otel(record.levelno)
|
|
363
|
+
project_root = client.options["project_root"]
|
|
358
364
|
attrs = {
|
|
359
365
|
"sentry.origin": "auto.logger.log",
|
|
360
366
|
} # type: dict[str, str | bool | float | int]
|
|
@@ -374,7 +380,10 @@ class SentryLogsHandler(_BaseHandler):
|
|
|
374
380
|
if record.lineno:
|
|
375
381
|
attrs["code.line.number"] = record.lineno
|
|
376
382
|
if record.pathname:
|
|
377
|
-
|
|
383
|
+
if project_root is not None and record.pathname.startswith(project_root):
|
|
384
|
+
attrs["code.file.path"] = record.pathname[len(project_root) + 1 :]
|
|
385
|
+
else:
|
|
386
|
+
attrs["code.file.path"] = record.pathname
|
|
378
387
|
if record.funcName:
|
|
379
388
|
attrs["code.function.name"] = record.funcName
|
|
380
389
|
|
|
@@ -139,6 +139,7 @@ def _new_chat_completion_common(f, *args, **kwargs):
|
|
|
139
139
|
op=consts.OP.OPENAI_CHAT_COMPLETIONS_CREATE,
|
|
140
140
|
name="Chat Completion",
|
|
141
141
|
origin=OpenAIIntegration.origin,
|
|
142
|
+
only_if_parent=True,
|
|
142
143
|
)
|
|
143
144
|
span.__enter__()
|
|
144
145
|
|
|
@@ -324,6 +325,7 @@ def _new_embeddings_create_common(f, *args, **kwargs):
|
|
|
324
325
|
op=consts.OP.OPENAI_EMBEDDINGS_CREATE,
|
|
325
326
|
description="OpenAI Embedding Creation",
|
|
326
327
|
origin=OpenAIIntegration.origin,
|
|
328
|
+
only_if_parent=True,
|
|
327
329
|
) as span:
|
|
328
330
|
if "input" in kwargs and (
|
|
329
331
|
should_send_default_pii() and integration.include_prompts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
|
-
import sentry_sdk
|
|
3
2
|
|
|
3
|
+
from sentry_sdk.feature_flags import add_feature_flag
|
|
4
4
|
from sentry_sdk.integrations import DidNotEnable, Integration
|
|
5
5
|
|
|
6
6
|
try:
|
|
@@ -29,11 +29,9 @@ class OpenFeatureHook(Hook):
|
|
|
29
29
|
def after(self, hook_context, details, hints):
|
|
30
30
|
# type: (HookContext, FlagEvaluationDetails[bool], HookHints) -> None
|
|
31
31
|
if isinstance(details.value, bool):
|
|
32
|
-
|
|
33
|
-
flags.set(details.flag_key, details.value)
|
|
32
|
+
add_feature_flag(details.flag_key, details.value)
|
|
34
33
|
|
|
35
34
|
def error(self, hook_context, exception, hints):
|
|
36
35
|
# type: (HookContext, Exception, HookHints) -> None
|
|
37
36
|
if isinstance(hook_context.default_value, bool):
|
|
38
|
-
|
|
39
|
-
flags.set(hook_context.flag_key, hook_context.default_value)
|
|
37
|
+
add_feature_flag(hook_context.flag_key, hook_context.default_value)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import copy
|
|
2
|
-
import json
|
|
3
2
|
|
|
4
3
|
import sentry_sdk
|
|
5
4
|
from sentry_sdk.consts import SPANSTATUS, SPANDATA, OP
|
|
6
5
|
from sentry_sdk.integrations import DidNotEnable, Integration
|
|
7
6
|
from sentry_sdk.scope import should_send_default_pii
|
|
8
7
|
from sentry_sdk.tracing import Span
|
|
9
|
-
from sentry_sdk.utils import capture_internal_exceptions
|
|
8
|
+
from sentry_sdk.utils import capture_internal_exceptions, _serialize_span_attribute
|
|
10
9
|
|
|
11
10
|
try:
|
|
12
11
|
from pymongo import monitoring
|
|
@@ -127,56 +126,50 @@ class CommandTracer(monitoring.CommandListener):
|
|
|
127
126
|
command.pop("$clusterTime", None)
|
|
128
127
|
command.pop("$signature", None)
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
data = {
|
|
130
|
+
SPANDATA.DB_NAME: event.database_name,
|
|
132
131
|
SPANDATA.DB_SYSTEM: "mongodb",
|
|
133
132
|
SPANDATA.DB_OPERATION: event.command_name,
|
|
134
133
|
SPANDATA.DB_MONGODB_COLLECTION: command.get(event.command_name),
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
try:
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
data["net.peer.name"] = event.connection_id[0]
|
|
138
|
+
data["net.peer.port"] = str(event.connection_id[1])
|
|
140
139
|
except TypeError:
|
|
141
140
|
pass
|
|
142
141
|
|
|
143
|
-
data = {"operation_ids": {}} # type: Dict[str, Any]
|
|
144
|
-
data["operation_ids"]["operation"] = event.operation_id
|
|
145
|
-
data["operation_ids"]["request"] = event.request_id
|
|
146
|
-
|
|
147
|
-
data.update(_get_db_data(event))
|
|
148
|
-
|
|
149
142
|
try:
|
|
150
143
|
lsid = command.pop("lsid")["id"]
|
|
151
|
-
data["
|
|
144
|
+
data["session_id"] = str(lsid)
|
|
152
145
|
except KeyError:
|
|
153
146
|
pass
|
|
154
147
|
|
|
155
148
|
if not should_send_default_pii():
|
|
156
149
|
command = _strip_pii(command)
|
|
157
150
|
|
|
158
|
-
query =
|
|
151
|
+
query = _serialize_span_attribute(command)
|
|
159
152
|
span = sentry_sdk.start_span(
|
|
160
153
|
op=OP.DB,
|
|
161
154
|
name=query,
|
|
162
155
|
origin=PyMongoIntegration.origin,
|
|
156
|
+
only_if_parent=True,
|
|
163
157
|
)
|
|
164
158
|
|
|
165
|
-
for tag, value in tags.items():
|
|
166
|
-
# set the tag for backwards-compatibility.
|
|
167
|
-
# TODO: remove the set_tag call in the next major release!
|
|
168
|
-
span.set_tag(tag, value)
|
|
169
|
-
|
|
170
|
-
span.set_data(tag, value)
|
|
171
|
-
|
|
172
|
-
for key, value in data.items():
|
|
173
|
-
span.set_data(key, value)
|
|
174
|
-
|
|
175
159
|
with capture_internal_exceptions():
|
|
176
160
|
sentry_sdk.add_breadcrumb(
|
|
177
|
-
message=query, category="query", type=OP.DB, data=
|
|
161
|
+
message=query, category="query", type=OP.DB, data=data
|
|
178
162
|
)
|
|
179
163
|
|
|
164
|
+
for key, value in data.items():
|
|
165
|
+
span.set_attribute(key, value)
|
|
166
|
+
|
|
167
|
+
for key, value in _get_db_data(event).items():
|
|
168
|
+
span.set_attribute(key, value)
|
|
169
|
+
|
|
170
|
+
span.set_attribute("operation_id", event.operation_id)
|
|
171
|
+
span.set_attribute("request_id", event.request_id)
|
|
172
|
+
|
|
180
173
|
self._ongoing_operations[self._operation_key(event)] = span.__enter__()
|
|
181
174
|
|
|
182
175
|
def failed(self, event):
|
|
@@ -4,11 +4,11 @@ import sys
|
|
|
4
4
|
import weakref
|
|
5
5
|
|
|
6
6
|
import sentry_sdk
|
|
7
|
+
from sentry_sdk.consts import SOURCE_FOR_STYLE
|
|
7
8
|
from sentry_sdk.integrations import Integration, DidNotEnable
|
|
8
9
|
from sentry_sdk.integrations._wsgi_common import RequestExtractor
|
|
9
10
|
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
|
|
10
11
|
from sentry_sdk.scope import should_send_default_pii
|
|
11
|
-
from sentry_sdk.tracing import SOURCE_FOR_STYLE
|
|
12
12
|
from sentry_sdk.utils import (
|
|
13
13
|
capture_internal_exceptions,
|
|
14
14
|
ensure_integration_enabled,
|
sentry_sdk/integrations/quart.py
CHANGED
|
@@ -3,11 +3,11 @@ import inspect
|
|
|
3
3
|
from functools import wraps
|
|
4
4
|
|
|
5
5
|
import sentry_sdk
|
|
6
|
+
from sentry_sdk.consts import SOURCE_FOR_STYLE
|
|
6
7
|
from sentry_sdk.integrations import DidNotEnable, Integration
|
|
7
8
|
from sentry_sdk.integrations._wsgi_common import _filter_headers
|
|
8
9
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
|
9
10
|
from sentry_sdk.scope import should_send_default_pii
|
|
10
|
-
from sentry_sdk.tracing import SOURCE_FOR_STYLE
|
|
11
11
|
from sentry_sdk.utils import (
|
|
12
12
|
capture_internal_exceptions,
|
|
13
13
|
ensure_integration_enabled,
|
|
@@ -122,8 +122,8 @@ def patch_scaffold_route():
|
|
|
122
122
|
def _sentry_func(*args, **kwargs):
|
|
123
123
|
# type: (*Any, **Any) -> Any
|
|
124
124
|
current_scope = sentry_sdk.get_current_scope()
|
|
125
|
-
if current_scope.
|
|
126
|
-
current_scope.
|
|
125
|
+
if current_scope.root_span is not None:
|
|
126
|
+
current_scope.root_span.update_active_thread()
|
|
127
127
|
|
|
128
128
|
sentry_scope = sentry_sdk.get_isolation_scope()
|
|
129
129
|
if sentry_scope.profile is not None:
|
sentry_sdk/integrations/ray.py
CHANGED
|
@@ -26,6 +26,8 @@ if TYPE_CHECKING:
|
|
|
26
26
|
from typing import Any, Optional
|
|
27
27
|
from sentry_sdk.utils import ExcInfo
|
|
28
28
|
|
|
29
|
+
DEFAULT_TRANSACTION_NAME = "unknown Ray function"
|
|
30
|
+
|
|
29
31
|
|
|
30
32
|
def _check_sentry_initialized():
|
|
31
33
|
# type: () -> None
|
|
@@ -58,25 +60,28 @@ def _patch_ray_remote():
|
|
|
58
60
|
"""
|
|
59
61
|
_check_sentry_initialized()
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
name=qualname_from_function(f),
|
|
65
|
-
origin=RayIntegration.origin,
|
|
63
|
+
root_span_name = qualname_from_function(f) or DEFAULT_TRANSACTION_NAME
|
|
64
|
+
sentry_sdk.get_current_scope().set_transaction_name(
|
|
65
|
+
root_span_name,
|
|
66
66
|
source=TransactionSource.TASK,
|
|
67
67
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
with sentry_sdk.continue_trace(_tracing or {}):
|
|
69
|
+
with sentry_sdk.start_span(
|
|
70
|
+
op=OP.QUEUE_TASK_RAY,
|
|
71
|
+
name=root_span_name,
|
|
72
|
+
origin=RayIntegration.origin,
|
|
73
|
+
source=TransactionSource.TASK,
|
|
74
|
+
) as root_span:
|
|
75
|
+
try:
|
|
76
|
+
result = f(*f_args, **f_kwargs)
|
|
77
|
+
root_span.set_status(SPANSTATUS.OK)
|
|
78
|
+
except Exception:
|
|
79
|
+
root_span.set_status(SPANSTATUS.INTERNAL_ERROR)
|
|
80
|
+
exc_info = sys.exc_info()
|
|
81
|
+
_capture_exception(exc_info)
|
|
82
|
+
reraise(*exc_info)
|
|
83
|
+
|
|
84
|
+
return result
|
|
80
85
|
|
|
81
86
|
rv = old_remote(_f, *args, *kwargs)
|
|
82
87
|
old_remote_method = rv.remote
|
|
@@ -90,6 +95,7 @@ def _patch_ray_remote():
|
|
|
90
95
|
op=OP.QUEUE_SUBMIT_RAY,
|
|
91
96
|
name=qualname_from_function(f),
|
|
92
97
|
origin=RayIntegration.origin,
|
|
98
|
+
only_if_parent=True,
|
|
93
99
|
) as span:
|
|
94
100
|
tracing = {
|
|
95
101
|
k: v
|
|
@@ -3,14 +3,15 @@ from sentry_sdk.consts import OP
|
|
|
3
3
|
from sentry_sdk.integrations.redis.consts import SPAN_ORIGIN
|
|
4
4
|
from sentry_sdk.integrations.redis.modules.caches import (
|
|
5
5
|
_compile_cache_span_properties,
|
|
6
|
-
|
|
6
|
+
_get_cache_data,
|
|
7
7
|
)
|
|
8
8
|
from sentry_sdk.integrations.redis.modules.queries import _compile_db_span_properties
|
|
9
9
|
from sentry_sdk.integrations.redis.utils import (
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
_create_breadcrumb,
|
|
11
|
+
_get_client_data,
|
|
12
|
+
_get_pipeline_data,
|
|
13
|
+
_update_span,
|
|
12
14
|
)
|
|
13
|
-
from sentry_sdk.tracing import Span
|
|
14
15
|
from sentry_sdk.utils import capture_internal_exceptions
|
|
15
16
|
|
|
16
17
|
from typing import TYPE_CHECKING
|
|
@@ -23,9 +24,9 @@ if TYPE_CHECKING:
|
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def patch_redis_async_pipeline(
|
|
26
|
-
pipeline_cls, is_cluster, get_command_args_fn,
|
|
27
|
+
pipeline_cls, is_cluster, get_command_args_fn, get_db_data_fn
|
|
27
28
|
):
|
|
28
|
-
# type: (Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]], bool, Any, Callable[[
|
|
29
|
+
# type: (Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]], bool, Any, Callable[[Any], dict[str, Any]]) -> None
|
|
29
30
|
old_execute = pipeline_cls.execute
|
|
30
31
|
|
|
31
32
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
@@ -39,24 +40,28 @@ def patch_redis_async_pipeline(
|
|
|
39
40
|
op=OP.DB_REDIS,
|
|
40
41
|
name="redis.pipeline.execute",
|
|
41
42
|
origin=SPAN_ORIGIN,
|
|
43
|
+
only_if_parent=True,
|
|
42
44
|
) as span:
|
|
43
45
|
with capture_internal_exceptions():
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
span_data = get_db_data_fn(self)
|
|
47
|
+
pipeline_data = _get_pipeline_data(
|
|
48
|
+
is_cluster=is_cluster,
|
|
49
|
+
get_command_args_fn=get_command_args_fn,
|
|
50
|
+
is_transaction=False if is_cluster else self.is_transaction,
|
|
51
|
+
command_stack=(
|
|
52
|
+
self._command_stack if is_cluster else self.command_stack
|
|
53
|
+
),
|
|
51
54
|
)
|
|
55
|
+
_update_span(span, span_data, pipeline_data)
|
|
56
|
+
_create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)
|
|
52
57
|
|
|
53
58
|
return await old_execute(self, *args, **kwargs)
|
|
54
59
|
|
|
55
60
|
pipeline_cls.execute = _sentry_execute # type: ignore
|
|
56
61
|
|
|
57
62
|
|
|
58
|
-
def patch_redis_async_client(cls, is_cluster,
|
|
59
|
-
# type: (Union[type[StrictRedis[Any]], type[RedisCluster[Any]]], bool, Callable[[
|
|
63
|
+
def patch_redis_async_client(cls, is_cluster, get_db_data_fn):
|
|
64
|
+
# type: (Union[type[StrictRedis[Any]], type[RedisCluster[Any]]], bool, Callable[[Any], dict[str, Any]]) -> None
|
|
60
65
|
old_execute_command = cls.execute_command
|
|
61
66
|
|
|
62
67
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
@@ -80,6 +85,7 @@ def patch_redis_async_client(cls, is_cluster, set_db_data_fn):
|
|
|
80
85
|
op=cache_properties["op"],
|
|
81
86
|
name=cache_properties["description"],
|
|
82
87
|
origin=SPAN_ORIGIN,
|
|
88
|
+
only_if_parent=True,
|
|
83
89
|
)
|
|
84
90
|
cache_span.__enter__()
|
|
85
91
|
|
|
@@ -89,18 +95,24 @@ def patch_redis_async_client(cls, is_cluster, set_db_data_fn):
|
|
|
89
95
|
op=db_properties["op"],
|
|
90
96
|
name=db_properties["description"],
|
|
91
97
|
origin=SPAN_ORIGIN,
|
|
98
|
+
only_if_parent=True,
|
|
92
99
|
)
|
|
93
100
|
db_span.__enter__()
|
|
94
101
|
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
db_span_data = get_db_data_fn(self)
|
|
103
|
+
db_client_span_data = _get_client_data(is_cluster, name, *args)
|
|
104
|
+
_update_span(db_span, db_span_data, db_client_span_data)
|
|
105
|
+
_create_breadcrumb(
|
|
106
|
+
db_properties["description"], db_span_data, db_client_span_data
|
|
107
|
+
)
|
|
97
108
|
|
|
98
109
|
value = await old_execute_command(self, name, *args, **kwargs)
|
|
99
110
|
|
|
100
111
|
db_span.__exit__(None, None, None)
|
|
101
112
|
|
|
102
113
|
if cache_span:
|
|
103
|
-
|
|
114
|
+
cache_span_data = _get_cache_data(self, cache_properties, value)
|
|
115
|
+
_update_span(cache_span, cache_span_data)
|
|
104
116
|
cache_span.__exit__(None, None, None)
|
|
105
117
|
|
|
106
118
|
return value
|
|
@@ -3,14 +3,15 @@ from sentry_sdk.consts import OP
|
|
|
3
3
|
from sentry_sdk.integrations.redis.consts import SPAN_ORIGIN
|
|
4
4
|
from sentry_sdk.integrations.redis.modules.caches import (
|
|
5
5
|
_compile_cache_span_properties,
|
|
6
|
-
|
|
6
|
+
_get_cache_data,
|
|
7
7
|
)
|
|
8
8
|
from sentry_sdk.integrations.redis.modules.queries import _compile_db_span_properties
|
|
9
9
|
from sentry_sdk.integrations.redis.utils import (
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
_create_breadcrumb,
|
|
11
|
+
_get_client_data,
|
|
12
|
+
_get_pipeline_data,
|
|
13
|
+
_update_span,
|
|
12
14
|
)
|
|
13
|
-
from sentry_sdk.tracing import Span
|
|
14
15
|
from sentry_sdk.utils import capture_internal_exceptions
|
|
15
16
|
|
|
16
17
|
from typing import TYPE_CHECKING
|
|
@@ -24,9 +25,9 @@ def patch_redis_pipeline(
|
|
|
24
25
|
pipeline_cls,
|
|
25
26
|
is_cluster,
|
|
26
27
|
get_command_args_fn,
|
|
27
|
-
|
|
28
|
+
get_db_data_fn,
|
|
28
29
|
):
|
|
29
|
-
# type: (Any, bool, Any, Callable[[
|
|
30
|
+
# type: (Any, bool, Any, Callable[[Any], dict[str, Any]]) -> None
|
|
30
31
|
old_execute = pipeline_cls.execute
|
|
31
32
|
|
|
32
33
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
@@ -40,24 +41,26 @@ def patch_redis_pipeline(
|
|
|
40
41
|
op=OP.DB_REDIS,
|
|
41
42
|
name="redis.pipeline.execute",
|
|
42
43
|
origin=SPAN_ORIGIN,
|
|
44
|
+
only_if_parent=True,
|
|
43
45
|
) as span:
|
|
44
46
|
with capture_internal_exceptions():
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.command_stack,
|
|
47
|
+
span_data = get_db_data_fn(self)
|
|
48
|
+
pipeline_data = _get_pipeline_data(
|
|
49
|
+
is_cluster=is_cluster,
|
|
50
|
+
get_command_args_fn=get_command_args_fn,
|
|
51
|
+
is_transaction=False if is_cluster else self.transaction,
|
|
52
|
+
command_stack=self.command_stack,
|
|
52
53
|
)
|
|
54
|
+
_update_span(span, span_data, pipeline_data)
|
|
55
|
+
_create_breadcrumb("redis.pipeline.execute", span_data, pipeline_data)
|
|
53
56
|
|
|
54
57
|
return old_execute(self, *args, **kwargs)
|
|
55
58
|
|
|
56
59
|
pipeline_cls.execute = sentry_patched_execute
|
|
57
60
|
|
|
58
61
|
|
|
59
|
-
def patch_redis_client(cls, is_cluster,
|
|
60
|
-
# type: (Any, bool, Callable[[
|
|
62
|
+
def patch_redis_client(cls, is_cluster, get_db_data_fn):
|
|
63
|
+
# type: (Any, bool, Callable[[Any], dict[str, Any]]) -> None
|
|
61
64
|
"""
|
|
62
65
|
This function can be used to instrument custom redis client classes or
|
|
63
66
|
subclasses.
|
|
@@ -85,6 +88,7 @@ def patch_redis_client(cls, is_cluster, set_db_data_fn):
|
|
|
85
88
|
op=cache_properties["op"],
|
|
86
89
|
name=cache_properties["description"],
|
|
87
90
|
origin=SPAN_ORIGIN,
|
|
91
|
+
only_if_parent=True,
|
|
88
92
|
)
|
|
89
93
|
cache_span.__enter__()
|
|
90
94
|
|
|
@@ -94,18 +98,24 @@ def patch_redis_client(cls, is_cluster, set_db_data_fn):
|
|
|
94
98
|
op=db_properties["op"],
|
|
95
99
|
name=db_properties["description"],
|
|
96
100
|
origin=SPAN_ORIGIN,
|
|
101
|
+
only_if_parent=True,
|
|
97
102
|
)
|
|
98
103
|
db_span.__enter__()
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
db_span_data = get_db_data_fn(self)
|
|
106
|
+
db_client_span_data = _get_client_data(is_cluster, name, *args)
|
|
107
|
+
_update_span(db_span, db_span_data, db_client_span_data)
|
|
108
|
+
_create_breadcrumb(
|
|
109
|
+
db_properties["description"], db_span_data, db_client_span_data
|
|
110
|
+
)
|
|
102
111
|
|
|
103
112
|
value = old_execute_command(self, name, *args, **kwargs)
|
|
104
113
|
|
|
105
114
|
db_span.__exit__(None, None, None)
|
|
106
115
|
|
|
107
116
|
if cache_span:
|
|
108
|
-
|
|
117
|
+
cache_span_data = _get_cache_data(self, cache_properties, value)
|
|
118
|
+
_update_span(cache_span, cache_span_data)
|
|
109
119
|
cache_span.__exit__(None, None, None)
|
|
110
120
|
|
|
111
121
|
return value
|
|
@@ -13,7 +13,6 @@ from typing import TYPE_CHECKING
|
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
16
|
-
from sentry_sdk.tracing import Span
|
|
17
16
|
from typing import Any, Optional
|
|
18
17
|
|
|
19
18
|
|
|
@@ -75,22 +74,24 @@ def _get_cache_span_description(redis_command, args, kwargs, integration):
|
|
|
75
74
|
return description
|
|
76
75
|
|
|
77
76
|
|
|
78
|
-
def
|
|
79
|
-
# type: (
|
|
77
|
+
def _get_cache_data(redis_client, properties, return_value):
|
|
78
|
+
# type: (Any, dict[str, Any], Optional[Any]) -> dict[str, Any]
|
|
79
|
+
data = {}
|
|
80
|
+
|
|
80
81
|
with capture_internal_exceptions():
|
|
81
|
-
|
|
82
|
+
data[SPANDATA.CACHE_KEY] = properties["key"]
|
|
82
83
|
|
|
83
84
|
if properties["redis_command"] in GET_COMMANDS:
|
|
84
85
|
if return_value is not None:
|
|
85
|
-
|
|
86
|
+
data[SPANDATA.CACHE_HIT] = True
|
|
86
87
|
size = (
|
|
87
88
|
len(str(return_value).encode("utf-8"))
|
|
88
89
|
if not isinstance(return_value, bytes)
|
|
89
90
|
else len(return_value)
|
|
90
91
|
)
|
|
91
|
-
|
|
92
|
+
data[SPANDATA.CACHE_ITEM_SIZE] = size
|
|
92
93
|
else:
|
|
93
|
-
|
|
94
|
+
data[SPANDATA.CACHE_HIT] = False
|
|
94
95
|
|
|
95
96
|
elif properties["redis_command"] in SET_COMMANDS:
|
|
96
97
|
if properties["value"] is not None:
|
|
@@ -99,7 +100,7 @@ def _set_cache_data(span, redis_client, properties, return_value):
|
|
|
99
100
|
if not isinstance(properties["value"], bytes)
|
|
100
101
|
else len(properties["value"])
|
|
101
102
|
)
|
|
102
|
-
|
|
103
|
+
data[SPANDATA.CACHE_ITEM_SIZE] = size
|
|
103
104
|
|
|
104
105
|
try:
|
|
105
106
|
connection_params = redis_client.connection_pool.connection_kwargs
|
|
@@ -114,8 +115,10 @@ def _set_cache_data(span, redis_client, properties, return_value):
|
|
|
114
115
|
|
|
115
116
|
host = connection_params.get("host")
|
|
116
117
|
if host is not None:
|
|
117
|
-
|
|
118
|
+
data[SPANDATA.NETWORK_PEER_ADDRESS] = host
|
|
118
119
|
|
|
119
120
|
port = connection_params.get("port")
|
|
120
121
|
if port is not None:
|
|
121
|
-
|
|
122
|
+
data[SPANDATA.NETWORK_PEER_PORT] = port
|
|
123
|
+
|
|
124
|
+
return data
|
|
@@ -11,7 +11,6 @@ from typing import TYPE_CHECKING
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from redis import Redis
|
|
13
13
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
14
|
-
from sentry_sdk.tracing import Span
|
|
15
14
|
from typing import Any
|
|
16
15
|
|
|
17
16
|
|
|
@@ -43,26 +42,30 @@ def _get_db_span_description(integration, command_name, args):
|
|
|
43
42
|
return description
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
def
|
|
47
|
-
# type: (
|
|
48
|
-
|
|
45
|
+
def _get_connection_data(connection_params):
|
|
46
|
+
# type: (dict[str, Any]) -> dict[str, Any]
|
|
47
|
+
data = {
|
|
48
|
+
SPANDATA.DB_SYSTEM: "redis",
|
|
49
|
+
}
|
|
49
50
|
|
|
50
51
|
db = connection_params.get("db")
|
|
51
52
|
if db is not None:
|
|
52
|
-
|
|
53
|
+
data[SPANDATA.DB_NAME] = str(db)
|
|
53
54
|
|
|
54
55
|
host = connection_params.get("host")
|
|
55
56
|
if host is not None:
|
|
56
|
-
|
|
57
|
+
data[SPANDATA.SERVER_ADDRESS] = host
|
|
57
58
|
|
|
58
59
|
port = connection_params.get("port")
|
|
59
60
|
if port is not None:
|
|
60
|
-
|
|
61
|
+
data[SPANDATA.SERVER_PORT] = port
|
|
62
|
+
|
|
63
|
+
return data
|
|
61
64
|
|
|
62
65
|
|
|
63
|
-
def
|
|
64
|
-
# type: (
|
|
66
|
+
def _get_db_data(redis_instance):
|
|
67
|
+
# type: (Redis[Any]) -> dict[str, Any]
|
|
65
68
|
try:
|
|
66
|
-
|
|
69
|
+
return _get_connection_data(redis_instance.connection_pool.connection_kwargs)
|
|
67
70
|
except AttributeError:
|
|
68
|
-
|
|
71
|
+
return {} # connections_kwargs may be missing in some cases
|