sentry-sdk 3.0.0a3__py2.py3-none-any.whl → 3.0.0a4__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 +2 -0
- sentry_sdk/ai/monitoring.py +7 -7
- sentry_sdk/ai/utils.py +5 -1
- sentry_sdk/api.py +16 -0
- sentry_sdk/client.py +10 -7
- sentry_sdk/consts.py +38 -7
- sentry_sdk/integrations/aiohttp.py +1 -1
- sentry_sdk/integrations/anthropic.py +1 -1
- sentry_sdk/integrations/arq.py +1 -1
- sentry_sdk/integrations/asyncio.py +1 -1
- sentry_sdk/integrations/asyncpg.py +1 -1
- sentry_sdk/integrations/boto3.py +2 -2
- sentry_sdk/integrations/celery/__init__.py +4 -3
- sentry_sdk/integrations/clickhouse_driver.py +1 -1
- sentry_sdk/integrations/cohere.py +2 -2
- sentry_sdk/integrations/django/__init__.py +12 -2
- sentry_sdk/integrations/django/asgi.py +1 -1
- sentry_sdk/integrations/django/caching.py +1 -1
- sentry_sdk/integrations/django/middleware.py +1 -1
- sentry_sdk/integrations/django/signals_handlers.py +1 -1
- sentry_sdk/integrations/django/templates.py +2 -2
- sentry_sdk/integrations/django/views.py +2 -2
- sentry_sdk/integrations/gnu_backtrace.py +3 -14
- sentry_sdk/integrations/graphene.py +1 -1
- sentry_sdk/integrations/grpc/aio/client.py +2 -2
- sentry_sdk/integrations/grpc/client.py +2 -2
- sentry_sdk/integrations/httpx.py +2 -2
- sentry_sdk/integrations/huey.py +1 -1
- sentry_sdk/integrations/huggingface_hub.py +1 -1
- sentry_sdk/integrations/langchain.py +1 -1
- sentry_sdk/integrations/litestar.py +3 -3
- sentry_sdk/integrations/logging.py +1 -1
- sentry_sdk/integrations/loguru.py +1 -1
- sentry_sdk/integrations/openai.py +339 -134
- sentry_sdk/integrations/openai_agents/utils.py +1 -49
- sentry_sdk/integrations/openfeature.py +4 -5
- sentry_sdk/integrations/pymongo.py +1 -1
- sentry_sdk/integrations/ray.py +1 -1
- sentry_sdk/integrations/redis/_async_common.py +3 -3
- sentry_sdk/integrations/redis/_sync_common.py +3 -3
- sentry_sdk/integrations/rust_tracing.py +1 -1
- sentry_sdk/integrations/socket.py +2 -2
- sentry_sdk/integrations/starlette.py +3 -3
- sentry_sdk/integrations/starlite.py +3 -3
- sentry_sdk/integrations/stdlib.py +4 -4
- sentry_sdk/integrations/strawberry.py +1 -1
- sentry_sdk/integrations/threading.py +1 -1
- sentry_sdk/opentelemetry/scope.py +10 -0
- sentry_sdk/serializer.py +8 -11
- sentry_sdk/tracing.py +3 -3
- sentry_sdk/tracing_utils.py +3 -3
- sentry_sdk/utils.py +46 -0
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/RECORD +58 -58
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a3.dist-info → sentry_sdk-3.0.0a4.dist-info}/top_level.txt +0 -0
sentry_sdk/__init__.py
CHANGED
|
@@ -22,6 +22,7 @@ __all__ = [ # noqa
|
|
|
22
22
|
"capture_exception",
|
|
23
23
|
"capture_message",
|
|
24
24
|
"continue_trace",
|
|
25
|
+
"new_trace",
|
|
25
26
|
"flush",
|
|
26
27
|
"get_baggage",
|
|
27
28
|
"get_client",
|
|
@@ -47,6 +48,7 @@ __all__ = [ # noqa
|
|
|
47
48
|
"logger",
|
|
48
49
|
"start_session",
|
|
49
50
|
"end_session",
|
|
51
|
+
"set_transaction_name",
|
|
50
52
|
]
|
|
51
53
|
|
|
52
54
|
# Initialize the debug support after everything is loaded
|
sentry_sdk/ai/monitoring.py
CHANGED
|
@@ -31,14 +31,14 @@ def ai_track(description: str, **span_kwargs: Any) -> Callable[..., Any]:
|
|
|
31
31
|
op = span_kwargs.pop("op", "ai.run" if curr_pipeline else "ai.pipeline")
|
|
32
32
|
|
|
33
33
|
with start_span(
|
|
34
|
-
name=description, op=op,
|
|
34
|
+
name=description, op=op, only_as_child_span=True, **span_kwargs
|
|
35
35
|
) as span:
|
|
36
36
|
for k, v in kwargs.pop("sentry_tags", {}).items():
|
|
37
37
|
span.set_tag(k, v)
|
|
38
38
|
for k, v in kwargs.pop("sentry_data", {}).items():
|
|
39
39
|
span.set_attribute(k, v)
|
|
40
40
|
if curr_pipeline:
|
|
41
|
-
span.set_attribute(SPANDATA.
|
|
41
|
+
span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline)
|
|
42
42
|
return f(*args, **kwargs)
|
|
43
43
|
else:
|
|
44
44
|
_ai_pipeline_name.set(description)
|
|
@@ -61,14 +61,14 @@ def ai_track(description: str, **span_kwargs: Any) -> Callable[..., Any]:
|
|
|
61
61
|
op = span_kwargs.pop("op", "ai.run" if curr_pipeline else "ai.pipeline")
|
|
62
62
|
|
|
63
63
|
with start_span(
|
|
64
|
-
name=description, op=op,
|
|
64
|
+
name=description, op=op, only_as_child_span=True, **span_kwargs
|
|
65
65
|
) as span:
|
|
66
66
|
for k, v in kwargs.pop("sentry_tags", {}).items():
|
|
67
67
|
span.set_tag(k, v)
|
|
68
68
|
for k, v in kwargs.pop("sentry_data", {}).items():
|
|
69
69
|
span.set_attribute(k, v)
|
|
70
70
|
if curr_pipeline:
|
|
71
|
-
span.set_attribute(SPANDATA.
|
|
71
|
+
span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline)
|
|
72
72
|
return await f(*args, **kwargs)
|
|
73
73
|
else:
|
|
74
74
|
_ai_pipeline_name.set(description)
|
|
@@ -105,7 +105,7 @@ def record_token_usage(
|
|
|
105
105
|
# TODO: move pipeline name elsewhere
|
|
106
106
|
ai_pipeline_name = get_ai_pipeline_name()
|
|
107
107
|
if ai_pipeline_name:
|
|
108
|
-
span.set_attribute(SPANDATA.
|
|
108
|
+
span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, ai_pipeline_name)
|
|
109
109
|
|
|
110
110
|
if input_tokens is not None:
|
|
111
111
|
span.set_attribute(SPANDATA.GEN_AI_USAGE_INPUT_TOKENS, input_tokens)
|
|
@@ -117,10 +117,10 @@ def record_token_usage(
|
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
if output_tokens is not None:
|
|
120
|
-
span.
|
|
120
|
+
span.set_attribute(SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
|
|
121
121
|
|
|
122
122
|
if output_tokens_reasoning is not None:
|
|
123
|
-
span.
|
|
123
|
+
span.set_attribute(
|
|
124
124
|
SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS_REASONING,
|
|
125
125
|
output_tokens_reasoning,
|
|
126
126
|
)
|
sentry_sdk/ai/utils.py
CHANGED
|
@@ -23,9 +23,13 @@ def _normalize_data(data: Any) -> Any:
|
|
|
23
23
|
return list(_normalize_data(x) for x in data)
|
|
24
24
|
if isinstance(data, dict):
|
|
25
25
|
return {k: _normalize_data(v) for (k, v) in data.items()}
|
|
26
|
+
|
|
26
27
|
return data
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def set_data_normalized(span: Span, key: str, value: Any) -> None:
|
|
30
31
|
normalized = _normalize_data(value)
|
|
31
|
-
|
|
32
|
+
if isinstance(normalized, (int, float, bool, str)):
|
|
33
|
+
span.set_attribute(key, normalized)
|
|
34
|
+
else:
|
|
35
|
+
span.set_attribute(key, str(normalized))
|
sentry_sdk/api.py
CHANGED
|
@@ -48,6 +48,7 @@ __all__ = [
|
|
|
48
48
|
"capture_exception",
|
|
49
49
|
"capture_message",
|
|
50
50
|
"continue_trace",
|
|
51
|
+
"new_trace",
|
|
51
52
|
"flush",
|
|
52
53
|
"get_baggage",
|
|
53
54
|
"get_client",
|
|
@@ -74,6 +75,7 @@ __all__ = [
|
|
|
74
75
|
"use_isolation_scope",
|
|
75
76
|
"start_session",
|
|
76
77
|
"end_session",
|
|
78
|
+
"set_transaction_name",
|
|
77
79
|
]
|
|
78
80
|
|
|
79
81
|
|
|
@@ -315,6 +317,15 @@ def continue_trace(environ_or_headers: dict[str, Any]) -> Generator[None, None,
|
|
|
315
317
|
yield
|
|
316
318
|
|
|
317
319
|
|
|
320
|
+
@contextmanager
|
|
321
|
+
def new_trace() -> Generator[None, None, None]:
|
|
322
|
+
"""
|
|
323
|
+
Force creation of a new trace.
|
|
324
|
+
"""
|
|
325
|
+
with get_isolation_scope().new_trace():
|
|
326
|
+
yield
|
|
327
|
+
|
|
328
|
+
|
|
318
329
|
@scopemethod
|
|
319
330
|
def start_session(
|
|
320
331
|
session_mode: str = "application",
|
|
@@ -325,3 +336,8 @@ def start_session(
|
|
|
325
336
|
@scopemethod
|
|
326
337
|
def end_session() -> None:
|
|
327
338
|
return get_isolation_scope().end_session()
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@scopemethod
|
|
342
|
+
def set_transaction_name(name: str, source: Optional[str] = None) -> None:
|
|
343
|
+
return get_current_scope().set_transaction_name(name, source)
|
sentry_sdk/client.py
CHANGED
|
@@ -46,7 +46,6 @@ from sentry_sdk.profiler.transaction_profiler import (
|
|
|
46
46
|
)
|
|
47
47
|
from sentry_sdk.scrubber import EventScrubber
|
|
48
48
|
from sentry_sdk.monitor import Monitor
|
|
49
|
-
from sentry_sdk.spotlight import setup_spotlight
|
|
50
49
|
|
|
51
50
|
if TYPE_CHECKING:
|
|
52
51
|
from typing import (
|
|
@@ -323,9 +322,9 @@ class _Client(BaseClient):
|
|
|
323
322
|
|
|
324
323
|
self.session_flusher = SessionFlusher(capture_func=_capture_envelope)
|
|
325
324
|
|
|
326
|
-
experiments = self.options.get("_experiments", {})
|
|
327
325
|
self.log_batcher = None
|
|
328
|
-
|
|
326
|
+
|
|
327
|
+
if self.options.get("enable_logs") is True:
|
|
329
328
|
from sentry_sdk._log_batcher import LogBatcher
|
|
330
329
|
|
|
331
330
|
self.log_batcher = LogBatcher(capture_func=_capture_envelope)
|
|
@@ -358,6 +357,10 @@ class _Client(BaseClient):
|
|
|
358
357
|
)
|
|
359
358
|
|
|
360
359
|
if self.options.get("spotlight"):
|
|
360
|
+
# This is intentionally here to prevent setting up spotlight
|
|
361
|
+
# stuff we don't need unless spotlight is explicitly enabled
|
|
362
|
+
from sentry_sdk.spotlight import setup_spotlight
|
|
363
|
+
|
|
361
364
|
self.spotlight = setup_spotlight(self.options)
|
|
362
365
|
if not self.options["dsn"]:
|
|
363
366
|
sample_all = lambda *_args, **_kwargs: 1.0
|
|
@@ -817,9 +820,8 @@ class _Client(BaseClient):
|
|
|
817
820
|
|
|
818
821
|
return return_value
|
|
819
822
|
|
|
820
|
-
def _capture_experimental_log(self, log: Log) -> None:
|
|
821
|
-
|
|
822
|
-
if not logs_enabled:
|
|
823
|
+
def _capture_experimental_log(self, log: Optional[Log]) -> None:
|
|
824
|
+
if self.options.get("enable_logs") is not True or log is None:
|
|
823
825
|
return
|
|
824
826
|
|
|
825
827
|
current_scope = sentry_sdk.get_current_scope()
|
|
@@ -874,9 +876,10 @@ class _Client(BaseClient):
|
|
|
874
876
|
f'[Sentry Logs] [{log.get("severity_text")}] {log.get("body")}'
|
|
875
877
|
)
|
|
876
878
|
|
|
877
|
-
before_send_log = self.options
|
|
879
|
+
before_send_log = self.options.get("before_send_log")
|
|
878
880
|
if before_send_log is not None:
|
|
879
881
|
log = before_send_log(log, {})
|
|
882
|
+
|
|
880
883
|
if log is None:
|
|
881
884
|
return
|
|
882
885
|
|
sentry_sdk/consts.py
CHANGED
|
@@ -17,7 +17,10 @@ if TYPE_CHECKING:
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
# up top to prevent circular import due to integration import
|
|
20
|
-
|
|
20
|
+
# This is more or less an arbitrary large-ish value for now, so that we allow
|
|
21
|
+
# pretty long strings (like LLM prompts), but still have *some* upper limit
|
|
22
|
+
# until we verify that removing the trimming completely is safe.
|
|
23
|
+
DEFAULT_MAX_VALUE_LENGTH = 100_000
|
|
21
24
|
|
|
22
25
|
DEFAULT_MAX_STACK_FRAMES = 100
|
|
23
26
|
DEFAULT_ADD_FULL_STACK = False
|
|
@@ -75,8 +78,6 @@ if TYPE_CHECKING:
|
|
|
75
78
|
"transport_compression_algo": Optional[CompressionAlgo],
|
|
76
79
|
"transport_num_pools": Optional[int],
|
|
77
80
|
"transport_http2": Optional[bool],
|
|
78
|
-
"enable_logs": Optional[bool],
|
|
79
|
-
"before_send_log": Optional[Callable[[Log, Hint], Optional[Log]]],
|
|
80
81
|
},
|
|
81
82
|
total=False,
|
|
82
83
|
)
|
|
@@ -167,6 +168,7 @@ class SPANDATA:
|
|
|
167
168
|
AI_PIPELINE_NAME = "ai.pipeline.name"
|
|
168
169
|
"""
|
|
169
170
|
Name of the AI pipeline or chain being executed.
|
|
171
|
+
DEPRECATED: Use GEN_AI_PIPELINE_NAME instead.
|
|
170
172
|
Example: "qa-pipeline"
|
|
171
173
|
"""
|
|
172
174
|
|
|
@@ -233,6 +235,7 @@ class SPANDATA:
|
|
|
233
235
|
AI_STREAMING = "ai.streaming"
|
|
234
236
|
"""
|
|
235
237
|
Whether or not the AI model call's response was streamed back asynchronously
|
|
238
|
+
DEPRECATED: Use GEN_AI_RESPONSE_STREAMING instead.
|
|
236
239
|
Example: true
|
|
237
240
|
"""
|
|
238
241
|
|
|
@@ -382,6 +385,24 @@ class SPANDATA:
|
|
|
382
385
|
Example: "chat"
|
|
383
386
|
"""
|
|
384
387
|
|
|
388
|
+
GEN_AI_PIPELINE_NAME = "gen_ai.pipeline.name"
|
|
389
|
+
"""
|
|
390
|
+
Name of the AI pipeline or chain being executed.
|
|
391
|
+
Example: "qa-pipeline"
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
GEN_AI_RESPONSE_MODEL = "gen_ai.response.model"
|
|
395
|
+
"""
|
|
396
|
+
Exact model identifier used to generate the response
|
|
397
|
+
Example: gpt-4o-mini-2024-07-18
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
GEN_AI_RESPONSE_STREAMING = "gen_ai.response.streaming"
|
|
401
|
+
"""
|
|
402
|
+
Whether or not the AI model call's response was streamed back asynchronously
|
|
403
|
+
Example: true
|
|
404
|
+
"""
|
|
405
|
+
|
|
385
406
|
GEN_AI_RESPONSE_TEXT = "gen_ai.response.text"
|
|
386
407
|
"""
|
|
387
408
|
The model's response text messages.
|
|
@@ -421,7 +442,7 @@ class SPANDATA:
|
|
|
421
442
|
GEN_AI_REQUEST_MODEL = "gen_ai.request.model"
|
|
422
443
|
"""
|
|
423
444
|
The model identifier being used for the request.
|
|
424
|
-
Example: "gpt-4-turbo
|
|
445
|
+
Example: "gpt-4-turbo"
|
|
425
446
|
"""
|
|
426
447
|
|
|
427
448
|
GEN_AI_REQUEST_PRESENCE_PENALTY = "gen_ai.request.presence_penalty"
|
|
@@ -659,9 +680,11 @@ class OP:
|
|
|
659
680
|
FUNCTION_AWS = "function.aws"
|
|
660
681
|
FUNCTION_GCP = "function.gcp"
|
|
661
682
|
GEN_AI_CHAT = "gen_ai.chat"
|
|
683
|
+
GEN_AI_EMBEDDINGS = "gen_ai.embeddings"
|
|
662
684
|
GEN_AI_EXECUTE_TOOL = "gen_ai.execute_tool"
|
|
663
685
|
GEN_AI_HANDOFF = "gen_ai.handoff"
|
|
664
686
|
GEN_AI_INVOKE_AGENT = "gen_ai.invoke_agent"
|
|
687
|
+
GEN_AI_RESPONSES = "gen_ai.responses"
|
|
665
688
|
GRAPHQL_EXECUTE = "graphql.execute"
|
|
666
689
|
GRAPHQL_MUTATION = "graphql.mutation"
|
|
667
690
|
GRAPHQL_PARSE = "graphql.parse"
|
|
@@ -686,8 +709,6 @@ class OP:
|
|
|
686
709
|
MIDDLEWARE_STARLITE = "middleware.starlite"
|
|
687
710
|
MIDDLEWARE_STARLITE_RECEIVE = "middleware.starlite.receive"
|
|
688
711
|
MIDDLEWARE_STARLITE_SEND = "middleware.starlite.send"
|
|
689
|
-
OPENAI_CHAT_COMPLETIONS_CREATE = "ai.chat_completions.create.openai"
|
|
690
|
-
OPENAI_EMBEDDINGS_CREATE = "ai.embeddings.create.openai"
|
|
691
712
|
HUGGINGFACE_HUB_CHAT_COMPLETIONS_CREATE = (
|
|
692
713
|
"ai.chat_completions.create.huggingface_hub"
|
|
693
714
|
)
|
|
@@ -831,6 +852,8 @@ class ClientConstructor:
|
|
|
831
852
|
custom_repr: Optional[Callable[..., Optional[str]]] = None,
|
|
832
853
|
add_full_stack: bool = DEFAULT_ADD_FULL_STACK,
|
|
833
854
|
max_stack_frames: Optional[int] = DEFAULT_MAX_STACK_FRAMES,
|
|
855
|
+
enable_logs: bool = False,
|
|
856
|
+
before_send_log: Optional[Callable[[Log, Hint], Optional[Log]]] = None,
|
|
834
857
|
) -> None:
|
|
835
858
|
"""Initialize the Sentry SDK with the given parameters. All parameters described here can be used in a call to `sentry_sdk.init()`.
|
|
836
859
|
|
|
@@ -1217,6 +1240,14 @@ class ClientConstructor:
|
|
|
1217
1240
|
|
|
1218
1241
|
:param instrumenter:
|
|
1219
1242
|
|
|
1243
|
+
:param enable_logs: Set `enable_logs` to True to enable the SDK to emit
|
|
1244
|
+
Sentry logs. Defaults to False.
|
|
1245
|
+
|
|
1246
|
+
:param before_send_log: An optional function to modify or filter out logs
|
|
1247
|
+
before they're sent to Sentry. Any modifications to the log in this
|
|
1248
|
+
function will be retained. If the function returns None, the log will
|
|
1249
|
+
not be sent to Sentry.
|
|
1250
|
+
|
|
1220
1251
|
:param _experiments:
|
|
1221
1252
|
"""
|
|
1222
1253
|
pass
|
|
@@ -1241,4 +1272,4 @@ DEFAULT_OPTIONS = _get_default_options()
|
|
|
1241
1272
|
del _get_default_options
|
|
1242
1273
|
|
|
1243
1274
|
|
|
1244
|
-
VERSION = "3.0.
|
|
1275
|
+
VERSION = "3.0.0a4"
|
|
@@ -161,7 +161,7 @@ def _sentry_patched_create_common(f: Any, *args: Any, **kwargs: Any) -> Any:
|
|
|
161
161
|
op=OP.ANTHROPIC_MESSAGES_CREATE,
|
|
162
162
|
description="Anthropic messages create",
|
|
163
163
|
origin=AnthropicIntegration.origin,
|
|
164
|
-
|
|
164
|
+
only_as_child_span=True,
|
|
165
165
|
)
|
|
166
166
|
span.__enter__()
|
|
167
167
|
|
sentry_sdk/integrations/arq.py
CHANGED
|
@@ -166,7 +166,7 @@ def _wrap_connect_addr(f: Callable[..., Awaitable[T]]) -> Callable[..., Awaitabl
|
|
|
166
166
|
op=OP.DB,
|
|
167
167
|
name="connect",
|
|
168
168
|
origin=AsyncPGIntegration.origin,
|
|
169
|
-
|
|
169
|
+
only_as_child_span=True,
|
|
170
170
|
) as span:
|
|
171
171
|
data = _get_db_data(
|
|
172
172
|
addr=kwargs.get("addr"),
|
sentry_sdk/integrations/boto3.py
CHANGED
|
@@ -66,7 +66,7 @@ def _sentry_request_created(
|
|
|
66
66
|
op=OP.HTTP_CLIENT,
|
|
67
67
|
name=description,
|
|
68
68
|
origin=Boto3Integration.origin,
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
187
|
+
only_as_child_span=True,
|
|
188
188
|
):
|
|
189
189
|
return await callback(request, *args, **kwargs)
|
|
190
190
|
|
|
@@ -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
|
-
|
|
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)
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
sentry_sdk/integrations/httpx.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
132
|
+
only_as_child_span=True,
|
|
133
133
|
) as span:
|
|
134
134
|
data = {
|
|
135
135
|
SPANDATA.HTTP_METHOD: request.method,
|
sentry_sdk/integrations/huey.py
CHANGED
|
@@ -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
|
-
|
|
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
|