sentry-sdk 2.30.0__py2.py3-none-any.whl → 3.0.0a2__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 +3 -8
- sentry_sdk/_compat.py +0 -1
- sentry_sdk/_init_implementation.py +6 -44
- sentry_sdk/_types.py +2 -64
- sentry_sdk/ai/monitoring.py +14 -10
- sentry_sdk/ai/utils.py +1 -1
- sentry_sdk/api.py +56 -169
- sentry_sdk/client.py +27 -72
- sentry_sdk/consts.py +60 -23
- sentry_sdk/debug.py +0 -10
- sentry_sdk/envelope.py +1 -3
- sentry_sdk/feature_flags.py +1 -1
- sentry_sdk/integrations/__init__.py +4 -2
- sentry_sdk/integrations/_asgi_common.py +5 -6
- 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 +102 -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 +51 -41
- 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/litestar.py +4 -2
- sentry_sdk/integrations/logging.py +7 -2
- sentry_sdk/integrations/openai.py +2 -0
- 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 +29 -18
- sentry_sdk/integrations/redis/_sync_common.py +28 -19
- 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 -18
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +4 -4
- sentry_sdk/integrations/redis/utils.py +64 -24
- 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/wsgi.py +84 -38
- sentry_sdk/opentelemetry/__init__.py +9 -0
- sentry_sdk/opentelemetry/consts.py +33 -0
- sentry_sdk/opentelemetry/contextvars_context.py +81 -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 +335 -0
- sentry_sdk/opentelemetry/tracing.py +59 -0
- sentry_sdk/opentelemetry/utils.py +484 -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 +108 -361
- sentry_sdk/sessions.py +0 -87
- sentry_sdk/tracing.py +415 -1161
- sentry_sdk/tracing_utils.py +130 -166
- sentry_sdk/transport.py +4 -104
- sentry_sdk/utils.py +169 -152
- {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/METADATA +3 -5
- sentry_sdk-3.0.0a2.dist-info/RECORD +154 -0
- sentry_sdk-3.0.0a2.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.30.0.dist-info/RECORD +0 -152
- sentry_sdk-2.30.0.dist-info/entry_points.txt +0 -2
- {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/WHEEL +0 -0
- {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/top_level.txt +0 -0
sentry_sdk/scope.py
CHANGED
|
@@ -11,27 +11,23 @@ from itertools import chain
|
|
|
11
11
|
|
|
12
12
|
from sentry_sdk._types import AnnotatedValue
|
|
13
13
|
from sentry_sdk.attachments import Attachment
|
|
14
|
-
from sentry_sdk.consts import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
try_profile_lifecycle_trace_start,
|
|
14
|
+
from sentry_sdk.consts import (
|
|
15
|
+
DEFAULT_MAX_BREADCRUMBS,
|
|
16
|
+
FALSE_VALUES,
|
|
17
|
+
BAGGAGE_HEADER_NAME,
|
|
18
|
+
SENTRY_TRACE_HEADER_NAME,
|
|
20
19
|
)
|
|
20
|
+
from sentry_sdk.feature_flags import FlagBuffer, DEFAULT_FLAG_CAPACITY
|
|
21
21
|
from sentry_sdk.profiler.transaction_profiler import Profile
|
|
22
22
|
from sentry_sdk.session import Session
|
|
23
23
|
from sentry_sdk.tracing_utils import (
|
|
24
24
|
Baggage,
|
|
25
25
|
has_tracing_enabled,
|
|
26
|
-
normalize_incoming_data,
|
|
27
26
|
PropagationContext,
|
|
28
27
|
)
|
|
29
28
|
from sentry_sdk.tracing import (
|
|
30
|
-
BAGGAGE_HEADER_NAME,
|
|
31
|
-
SENTRY_TRACE_HEADER_NAME,
|
|
32
29
|
NoOpSpan,
|
|
33
30
|
Span,
|
|
34
|
-
Transaction,
|
|
35
31
|
)
|
|
36
32
|
from sentry_sdk.utils import (
|
|
37
33
|
capture_internal_exception,
|
|
@@ -44,7 +40,6 @@ from sentry_sdk.utils import (
|
|
|
44
40
|
logger,
|
|
45
41
|
)
|
|
46
42
|
|
|
47
|
-
import typing
|
|
48
43
|
from typing import TYPE_CHECKING
|
|
49
44
|
|
|
50
45
|
if TYPE_CHECKING:
|
|
@@ -62,8 +57,7 @@ if TYPE_CHECKING:
|
|
|
62
57
|
from typing import Tuple
|
|
63
58
|
from typing import TypeVar
|
|
64
59
|
from typing import Union
|
|
65
|
-
|
|
66
|
-
from typing_extensions import Unpack
|
|
60
|
+
from typing import Self
|
|
67
61
|
|
|
68
62
|
from sentry_sdk._types import (
|
|
69
63
|
Breadcrumb,
|
|
@@ -74,12 +68,9 @@ if TYPE_CHECKING:
|
|
|
74
68
|
ExcInfo,
|
|
75
69
|
Hint,
|
|
76
70
|
LogLevelStr,
|
|
77
|
-
SamplingContext,
|
|
78
71
|
Type,
|
|
79
72
|
)
|
|
80
73
|
|
|
81
|
-
from sentry_sdk.tracing import TransactionKwargs
|
|
82
|
-
|
|
83
74
|
import sentry_sdk
|
|
84
75
|
|
|
85
76
|
P = ParamSpec("P")
|
|
@@ -115,28 +106,6 @@ class ScopeType(Enum):
|
|
|
115
106
|
MERGED = "merged"
|
|
116
107
|
|
|
117
108
|
|
|
118
|
-
class _ScopeManager:
|
|
119
|
-
def __init__(self, hub=None):
|
|
120
|
-
# type: (Optional[Any]) -> None
|
|
121
|
-
self._old_scopes = [] # type: List[Scope]
|
|
122
|
-
|
|
123
|
-
def __enter__(self):
|
|
124
|
-
# type: () -> Scope
|
|
125
|
-
isolation_scope = Scope.get_isolation_scope()
|
|
126
|
-
|
|
127
|
-
self._old_scopes.append(isolation_scope)
|
|
128
|
-
|
|
129
|
-
forked_scope = isolation_scope.fork()
|
|
130
|
-
_isolation_scope.set(forked_scope)
|
|
131
|
-
|
|
132
|
-
return forked_scope
|
|
133
|
-
|
|
134
|
-
def __exit__(self, exc_type, exc_value, tb):
|
|
135
|
-
# type: (Any, Any, Any) -> None
|
|
136
|
-
old_scope = self._old_scopes.pop()
|
|
137
|
-
_isolation_scope.set(old_scope)
|
|
138
|
-
|
|
139
|
-
|
|
140
109
|
def add_global_event_processor(processor):
|
|
141
110
|
# type: (EventProcessor) -> None
|
|
142
111
|
global_event_processors.append(processor)
|
|
@@ -203,8 +172,8 @@ class Scope:
|
|
|
203
172
|
"_flags",
|
|
204
173
|
)
|
|
205
174
|
|
|
206
|
-
def __init__(self, ty=None
|
|
207
|
-
# type: (Optional[ScopeType]
|
|
175
|
+
def __init__(self, ty=None):
|
|
176
|
+
# type: (Optional[ScopeType]) -> None
|
|
208
177
|
self._type = ty
|
|
209
178
|
|
|
210
179
|
self._event_processors = [] # type: List[EventProcessor]
|
|
@@ -216,21 +185,18 @@ class Scope:
|
|
|
216
185
|
|
|
217
186
|
self.client = NonRecordingClient() # type: sentry_sdk.client.BaseClient
|
|
218
187
|
|
|
219
|
-
if client is not None:
|
|
220
|
-
self.set_client(client)
|
|
221
|
-
|
|
222
188
|
self.clear()
|
|
223
189
|
|
|
224
190
|
incoming_trace_information = self._load_trace_data_from_env()
|
|
225
191
|
self.generate_propagation_context(incoming_data=incoming_trace_information)
|
|
226
192
|
|
|
227
193
|
def __copy__(self):
|
|
228
|
-
# type: () ->
|
|
194
|
+
# type: () -> Self
|
|
229
195
|
"""
|
|
230
196
|
Returns a copy of this scope.
|
|
231
197
|
This also creates a copy of all referenced data structures.
|
|
232
198
|
"""
|
|
233
|
-
rv = object.__new__(self.__class__) # type:
|
|
199
|
+
rv = object.__new__(self.__class__) # type: Self
|
|
234
200
|
|
|
235
201
|
rv._type = self._type
|
|
236
202
|
rv.client = self.client
|
|
@@ -273,13 +239,21 @@ class Scope:
|
|
|
273
239
|
|
|
274
240
|
Returns the current scope.
|
|
275
241
|
"""
|
|
276
|
-
current_scope =
|
|
242
|
+
current_scope = cls._get_current_scope()
|
|
277
243
|
if current_scope is None:
|
|
278
244
|
current_scope = Scope(ty=ScopeType.CURRENT)
|
|
279
245
|
_current_scope.set(current_scope)
|
|
280
246
|
|
|
281
247
|
return current_scope
|
|
282
248
|
|
|
249
|
+
@classmethod
|
|
250
|
+
def _get_current_scope(cls):
|
|
251
|
+
# type: () -> Optional[Scope]
|
|
252
|
+
"""
|
|
253
|
+
Returns the current scope without creating a new one. Internal use only.
|
|
254
|
+
"""
|
|
255
|
+
return _current_scope.get()
|
|
256
|
+
|
|
283
257
|
@classmethod
|
|
284
258
|
def set_current_scope(cls, new_current_scope):
|
|
285
259
|
# type: (Scope) -> None
|
|
@@ -299,13 +273,21 @@ class Scope:
|
|
|
299
273
|
|
|
300
274
|
Returns the isolation scope.
|
|
301
275
|
"""
|
|
302
|
-
isolation_scope =
|
|
276
|
+
isolation_scope = cls._get_isolation_scope()
|
|
303
277
|
if isolation_scope is None:
|
|
304
278
|
isolation_scope = Scope(ty=ScopeType.ISOLATION)
|
|
305
279
|
_isolation_scope.set(isolation_scope)
|
|
306
280
|
|
|
307
281
|
return isolation_scope
|
|
308
282
|
|
|
283
|
+
@classmethod
|
|
284
|
+
def _get_isolation_scope(cls):
|
|
285
|
+
# type: () -> Optional[Scope]
|
|
286
|
+
"""
|
|
287
|
+
Returns the isolation scope without creating a new one. Internal use only.
|
|
288
|
+
"""
|
|
289
|
+
return _isolation_scope.get()
|
|
290
|
+
|
|
309
291
|
@classmethod
|
|
310
292
|
def set_isolation_scope(cls, new_isolation_scope):
|
|
311
293
|
# type: (Scope) -> None
|
|
@@ -349,7 +331,7 @@ class Scope:
|
|
|
349
331
|
return cls.get_isolation_scope()._last_event_id
|
|
350
332
|
|
|
351
333
|
def _merge_scopes(self, additional_scope=None, additional_scope_kwargs=None):
|
|
352
|
-
# type: (Optional[Scope], Optional[Dict[str, Any]]) ->
|
|
334
|
+
# type: (Optional[Scope], Optional[Dict[str, Any]]) -> Self
|
|
353
335
|
"""
|
|
354
336
|
Merges global, isolation and current scope into a new scope and
|
|
355
337
|
adds the given additional scope or additional scope kwargs to it.
|
|
@@ -357,16 +339,17 @@ class Scope:
|
|
|
357
339
|
if additional_scope and additional_scope_kwargs:
|
|
358
340
|
raise TypeError("cannot provide scope and kwargs")
|
|
359
341
|
|
|
360
|
-
final_scope =
|
|
342
|
+
final_scope = self.__class__()
|
|
361
343
|
final_scope._type = ScopeType.MERGED
|
|
362
344
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
final_scope.update_from_scope(isolation_scope)
|
|
345
|
+
global_scope = self.get_global_scope()
|
|
346
|
+
final_scope.update_from_scope(global_scope)
|
|
366
347
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
348
|
+
isolation_scope = self.get_isolation_scope()
|
|
349
|
+
final_scope.update_from_scope(self.get_isolation_scope())
|
|
350
|
+
|
|
351
|
+
current_scope = self.get_current_scope()
|
|
352
|
+
final_scope.update_from_scope(current_scope)
|
|
370
353
|
|
|
371
354
|
if self != current_scope and self != isolation_scope:
|
|
372
355
|
final_scope.update_from_scope(self)
|
|
@@ -392,7 +375,7 @@ class Scope:
|
|
|
392
375
|
This checks the current scope, the isolation scope and the global scope for a client.
|
|
393
376
|
If no client is available a :py:class:`sentry_sdk.client.NonRecordingClient` is returned.
|
|
394
377
|
"""
|
|
395
|
-
current_scope =
|
|
378
|
+
current_scope = cls.get_current_scope()
|
|
396
379
|
try:
|
|
397
380
|
client = current_scope.client
|
|
398
381
|
except AttributeError:
|
|
@@ -401,7 +384,7 @@ class Scope:
|
|
|
401
384
|
if client is not None and client.is_active():
|
|
402
385
|
return client
|
|
403
386
|
|
|
404
|
-
isolation_scope =
|
|
387
|
+
isolation_scope = cls.get_isolation_scope()
|
|
405
388
|
try:
|
|
406
389
|
client = isolation_scope.client
|
|
407
390
|
except AttributeError:
|
|
@@ -434,7 +417,7 @@ class Scope:
|
|
|
434
417
|
self.client = client if client is not None else NonRecordingClient()
|
|
435
418
|
|
|
436
419
|
def fork(self):
|
|
437
|
-
# type: () ->
|
|
420
|
+
# type: () -> Self
|
|
438
421
|
"""
|
|
439
422
|
.. versionadded:: 2.0.0
|
|
440
423
|
|
|
@@ -496,19 +479,10 @@ class Scope:
|
|
|
496
479
|
def get_dynamic_sampling_context(self):
|
|
497
480
|
# type: () -> Optional[Dict[str, str]]
|
|
498
481
|
"""
|
|
499
|
-
Returns the Dynamic Sampling Context from the
|
|
500
|
-
If not existing, creates a new one.
|
|
482
|
+
Returns the Dynamic Sampling Context from the baggage or populates one.
|
|
501
483
|
"""
|
|
502
|
-
if self._propagation_context is None:
|
|
503
|
-
return None
|
|
504
|
-
|
|
505
484
|
baggage = self.get_baggage()
|
|
506
|
-
if baggage
|
|
507
|
-
self._propagation_context.dynamic_sampling_context = (
|
|
508
|
-
baggage.dynamic_sampling_context()
|
|
509
|
-
)
|
|
510
|
-
|
|
511
|
-
return self._propagation_context.dynamic_sampling_context
|
|
485
|
+
return baggage.dynamic_sampling_context() if baggage else None
|
|
512
486
|
|
|
513
487
|
def get_traceparent(self, *args, **kwargs):
|
|
514
488
|
# type: (Any, Any) -> Optional[str]
|
|
@@ -519,16 +493,16 @@ class Scope:
|
|
|
519
493
|
client = self.get_client()
|
|
520
494
|
|
|
521
495
|
# If we have an active span, return traceparent from there
|
|
522
|
-
if
|
|
496
|
+
if (
|
|
497
|
+
has_tracing_enabled(client.options)
|
|
498
|
+
and self.span is not None
|
|
499
|
+
and self.span.is_valid
|
|
500
|
+
):
|
|
523
501
|
return self.span.to_traceparent()
|
|
524
502
|
|
|
525
503
|
# If this scope has a propagation context, return traceparent from there
|
|
526
504
|
if self._propagation_context is not None:
|
|
527
|
-
|
|
528
|
-
self._propagation_context.trace_id,
|
|
529
|
-
self._propagation_context.span_id,
|
|
530
|
-
)
|
|
531
|
-
return traceparent
|
|
505
|
+
return self._propagation_context.to_traceparent()
|
|
532
506
|
|
|
533
507
|
# Fall back to isolation scope's traceparent. It always has one
|
|
534
508
|
return self.get_isolation_scope().get_traceparent()
|
|
@@ -538,22 +512,24 @@ class Scope:
|
|
|
538
512
|
"""
|
|
539
513
|
Returns the Sentry "baggage" header containing trace information from the
|
|
540
514
|
currently active span or the scopes Propagation Context.
|
|
515
|
+
If not existing, creates a new one.
|
|
541
516
|
"""
|
|
542
517
|
client = self.get_client()
|
|
543
518
|
|
|
544
519
|
# If we have an active span, return baggage from there
|
|
545
|
-
if
|
|
520
|
+
if (
|
|
521
|
+
has_tracing_enabled(client.options)
|
|
522
|
+
and self.span is not None
|
|
523
|
+
and self.span.is_valid
|
|
524
|
+
):
|
|
546
525
|
return self.span.to_baggage()
|
|
547
526
|
|
|
548
527
|
# If this scope has a propagation context, return baggage from there
|
|
528
|
+
# populate a fresh one if it doesn't exist
|
|
549
529
|
if self._propagation_context is not None:
|
|
550
|
-
|
|
551
|
-
self._propagation_context.
|
|
552
|
-
|
|
553
|
-
if dynamic_sampling_context is None:
|
|
554
|
-
return Baggage.from_options(self)
|
|
555
|
-
else:
|
|
556
|
-
return Baggage(dynamic_sampling_context)
|
|
530
|
+
if self._propagation_context.baggage is None:
|
|
531
|
+
self._propagation_context.baggage = Baggage.from_options(self)
|
|
532
|
+
return self._propagation_context.baggage
|
|
557
533
|
|
|
558
534
|
# Fall back to isolation scope's baggage. It always has one
|
|
559
535
|
return self.get_isolation_scope().get_baggage()
|
|
@@ -581,12 +557,6 @@ class Scope:
|
|
|
581
557
|
Return meta tags which should be injected into HTML templates
|
|
582
558
|
to allow propagation of trace information.
|
|
583
559
|
"""
|
|
584
|
-
span = kwargs.pop("span", None)
|
|
585
|
-
if span is not None:
|
|
586
|
-
logger.warning(
|
|
587
|
-
"The parameter `span` in trace_propagation_meta() is deprecated and will be removed in the future."
|
|
588
|
-
)
|
|
589
|
-
|
|
590
560
|
meta = ""
|
|
591
561
|
|
|
592
562
|
sentry_trace = self.get_traceparent()
|
|
@@ -615,10 +585,9 @@ class Scope:
|
|
|
615
585
|
if traceparent is not None:
|
|
616
586
|
yield SENTRY_TRACE_HEADER_NAME, traceparent
|
|
617
587
|
|
|
618
|
-
|
|
619
|
-
if
|
|
620
|
-
|
|
621
|
-
yield BAGGAGE_HEADER_NAME, baggage
|
|
588
|
+
baggage = self.get_baggage()
|
|
589
|
+
if baggage is not None:
|
|
590
|
+
yield BAGGAGE_HEADER_NAME, baggage.serialize()
|
|
622
591
|
|
|
623
592
|
def iter_trace_propagation_headers(self, *args, **kwargs):
|
|
624
593
|
# type: (Any, Any) -> Generator[Tuple[str, str], None, None]
|
|
@@ -629,18 +598,11 @@ class Scope:
|
|
|
629
598
|
If no span is given, the trace data is taken from the scope.
|
|
630
599
|
"""
|
|
631
600
|
client = self.get_client()
|
|
632
|
-
if not client.options.get("propagate_traces"):
|
|
633
|
-
warnings.warn(
|
|
634
|
-
"The `propagate_traces` parameter is deprecated. Please use `trace_propagation_targets` instead.",
|
|
635
|
-
DeprecationWarning,
|
|
636
|
-
stacklevel=2,
|
|
637
|
-
)
|
|
638
|
-
return
|
|
639
601
|
|
|
640
602
|
span = kwargs.pop("span", None)
|
|
641
603
|
span = span or self.span
|
|
642
604
|
|
|
643
|
-
if has_tracing_enabled(client.options) and span is not None:
|
|
605
|
+
if has_tracing_enabled(client.options) and span is not None and span.is_valid:
|
|
644
606
|
for header in span.iter_headers():
|
|
645
607
|
yield header
|
|
646
608
|
else:
|
|
@@ -706,23 +668,6 @@ class Scope:
|
|
|
706
668
|
self._last_event_id = None # type: Optional[str]
|
|
707
669
|
self._flags = None # type: Optional[FlagBuffer]
|
|
708
670
|
|
|
709
|
-
@_attr_setter
|
|
710
|
-
def level(self, value):
|
|
711
|
-
# type: (LogLevelStr) -> None
|
|
712
|
-
"""
|
|
713
|
-
When set this overrides the level.
|
|
714
|
-
|
|
715
|
-
.. deprecated:: 1.0.0
|
|
716
|
-
Use :func:`set_level` instead.
|
|
717
|
-
|
|
718
|
-
:param value: The level to set.
|
|
719
|
-
"""
|
|
720
|
-
logger.warning(
|
|
721
|
-
"Deprecated: use .set_level() instead. This will be removed in the future."
|
|
722
|
-
)
|
|
723
|
-
|
|
724
|
-
self._level = value
|
|
725
|
-
|
|
726
671
|
def set_level(self, value):
|
|
727
672
|
# type: (LogLevelStr) -> None
|
|
728
673
|
"""
|
|
@@ -739,71 +684,36 @@ class Scope:
|
|
|
739
684
|
self._fingerprint = value
|
|
740
685
|
|
|
741
686
|
@property
|
|
742
|
-
def
|
|
743
|
-
# type: () ->
|
|
744
|
-
|
|
745
|
-
"""Return the transaction (root span) in the scope, if any."""
|
|
746
|
-
|
|
747
|
-
# there is no span/transaction on the scope
|
|
687
|
+
def root_span(self):
|
|
688
|
+
# type: () -> Optional[Span]
|
|
689
|
+
"""Return the root span in the scope, if any."""
|
|
748
690
|
if self._span is None:
|
|
749
691
|
return None
|
|
750
692
|
|
|
751
|
-
|
|
752
|
-
if self._span.containing_transaction is None:
|
|
753
|
-
return None
|
|
754
|
-
|
|
755
|
-
# there is either a transaction (which is its own containing
|
|
756
|
-
# transaction) or a non-orphan span on the scope
|
|
757
|
-
return self._span.containing_transaction
|
|
758
|
-
|
|
759
|
-
@transaction.setter
|
|
760
|
-
def transaction(self, value):
|
|
761
|
-
# type: (Any) -> None
|
|
762
|
-
# would be type: (Optional[str]) -> None, see https://github.com/python/mypy/issues/3004
|
|
763
|
-
"""When set this forces a specific transaction name to be set.
|
|
764
|
-
|
|
765
|
-
Deprecated: use set_transaction_name instead."""
|
|
766
|
-
|
|
767
|
-
# XXX: the docstring above is misleading. The implementation of
|
|
768
|
-
# apply_to_event prefers an existing value of event.transaction over
|
|
769
|
-
# anything set in the scope.
|
|
770
|
-
# XXX: note that with the introduction of the Scope.transaction getter,
|
|
771
|
-
# there is a semantic and type mismatch between getter and setter. The
|
|
772
|
-
# getter returns a Transaction, the setter sets a transaction name.
|
|
773
|
-
# Without breaking version compatibility, we could make the setter set a
|
|
774
|
-
# transaction name or transaction (self._span) depending on the type of
|
|
775
|
-
# the value argument.
|
|
776
|
-
|
|
777
|
-
logger.warning(
|
|
778
|
-
"Assigning to scope.transaction directly is deprecated: use scope.set_transaction_name() instead."
|
|
779
|
-
)
|
|
780
|
-
self._transaction = value
|
|
781
|
-
if self._span and self._span.containing_transaction:
|
|
782
|
-
self._span.containing_transaction.name = value
|
|
693
|
+
return self._span.root_span
|
|
783
694
|
|
|
784
695
|
def set_transaction_name(self, name, source=None):
|
|
785
696
|
# type: (str, Optional[str]) -> None
|
|
786
697
|
"""Set the transaction name and optionally the transaction source."""
|
|
787
698
|
self._transaction = name
|
|
788
699
|
|
|
789
|
-
if self._span and self._span.
|
|
790
|
-
self._span.
|
|
700
|
+
if self._span and self._span.root_span:
|
|
701
|
+
self._span.root_span.name = name
|
|
791
702
|
if source:
|
|
792
|
-
self._span.
|
|
703
|
+
self._span.root_span.source = source
|
|
793
704
|
|
|
794
705
|
if source:
|
|
795
706
|
self._transaction_info["source"] = source
|
|
796
707
|
|
|
797
|
-
@
|
|
798
|
-
def
|
|
799
|
-
# type: (Optional[
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
)
|
|
806
|
-
self.set_user(value)
|
|
708
|
+
@property
|
|
709
|
+
def transaction_name(self):
|
|
710
|
+
# type: () -> Optional[str]
|
|
711
|
+
return self._transaction
|
|
712
|
+
|
|
713
|
+
@property
|
|
714
|
+
def transaction_source(self):
|
|
715
|
+
# type: () -> Optional[str]
|
|
716
|
+
return self._transaction_info.get("source")
|
|
807
717
|
|
|
808
718
|
def set_user(self, value):
|
|
809
719
|
# type: (Optional[Dict[str, Any]]) -> None
|
|
@@ -816,22 +726,9 @@ class Scope:
|
|
|
816
726
|
@property
|
|
817
727
|
def span(self):
|
|
818
728
|
# type: () -> Optional[Span]
|
|
819
|
-
"""Get
|
|
729
|
+
"""Get current tracing span."""
|
|
820
730
|
return self._span
|
|
821
731
|
|
|
822
|
-
@span.setter
|
|
823
|
-
def span(self, span):
|
|
824
|
-
# type: (Optional[Span]) -> None
|
|
825
|
-
self._span = span
|
|
826
|
-
# XXX: this differs from the implementation in JS, there Scope.setSpan
|
|
827
|
-
# does not set Scope._transactionName.
|
|
828
|
-
if isinstance(span, Transaction):
|
|
829
|
-
transaction = span
|
|
830
|
-
if transaction.name:
|
|
831
|
-
self._transaction = transaction.name
|
|
832
|
-
if transaction.source:
|
|
833
|
-
self._transaction_info["source"] = transaction.source
|
|
834
|
-
|
|
835
732
|
@property
|
|
836
733
|
def profile(self):
|
|
837
734
|
# type: () -> Optional[Profile]
|
|
@@ -990,195 +887,41 @@ class Scope:
|
|
|
990
887
|
self._breadcrumbs.popleft()
|
|
991
888
|
self._n_breadcrumbs_truncated += 1
|
|
992
889
|
|
|
993
|
-
def start_transaction(
|
|
994
|
-
|
|
995
|
-
transaction=None,
|
|
996
|
-
instrumenter=INSTRUMENTER.SENTRY,
|
|
997
|
-
custom_sampling_context=None,
|
|
998
|
-
**kwargs,
|
|
999
|
-
):
|
|
1000
|
-
# type: (Optional[Transaction], str, Optional[SamplingContext], Unpack[TransactionKwargs]) -> Union[Transaction, NoOpSpan]
|
|
890
|
+
def start_transaction(self, **kwargs):
|
|
891
|
+
# type: (Any) -> Union[NoOpSpan, Span]
|
|
1001
892
|
"""
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
transaction with kwargs.
|
|
1006
|
-
|
|
1007
|
-
This is the entry point to manual tracing instrumentation.
|
|
1008
|
-
|
|
1009
|
-
A tree structure can be built by adding child spans to the transaction,
|
|
1010
|
-
and child spans to other spans. To start a new child span within the
|
|
1011
|
-
transaction or any span, call the respective `.start_child()` method.
|
|
1012
|
-
|
|
1013
|
-
Every child span must be finished before the transaction is finished,
|
|
1014
|
-
otherwise the unfinished spans are discarded.
|
|
1015
|
-
|
|
1016
|
-
When used as context managers, spans and transactions are automatically
|
|
1017
|
-
finished at the end of the `with` block. If not using context managers,
|
|
1018
|
-
call the `.finish()` method.
|
|
1019
|
-
|
|
1020
|
-
When the transaction is finished, it will be sent to Sentry with all its
|
|
1021
|
-
finished child spans.
|
|
1022
|
-
|
|
1023
|
-
:param transaction: The transaction to start. If omitted, we create and
|
|
1024
|
-
start a new transaction.
|
|
1025
|
-
:param instrumenter: This parameter is meant for internal use only. It
|
|
1026
|
-
will be removed in the next major version.
|
|
1027
|
-
:param custom_sampling_context: The transaction's custom sampling context.
|
|
1028
|
-
:param kwargs: Optional keyword arguments to be passed to the Transaction
|
|
1029
|
-
constructor. See :py:class:`sentry_sdk.tracing.Transaction` for
|
|
1030
|
-
available arguments.
|
|
893
|
+
.. deprecated:: 3.0.0
|
|
894
|
+
This function is deprecated and will be removed in a future release.
|
|
895
|
+
Use :py:meth:`sentry_sdk.start_span` instead.
|
|
1031
896
|
"""
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
if instrumenter != configuration_instrumenter:
|
|
1039
|
-
return NoOpSpan()
|
|
1040
|
-
|
|
1041
|
-
try_autostart_continuous_profiler()
|
|
1042
|
-
|
|
1043
|
-
custom_sampling_context = custom_sampling_context or {}
|
|
1044
|
-
|
|
1045
|
-
# kwargs at this point has type TransactionKwargs, since we have removed
|
|
1046
|
-
# the client and custom_sampling_context from it.
|
|
1047
|
-
transaction_kwargs = kwargs # type: TransactionKwargs
|
|
1048
|
-
|
|
1049
|
-
# if we haven't been given a transaction, make one
|
|
1050
|
-
if transaction is None:
|
|
1051
|
-
transaction = Transaction(**transaction_kwargs)
|
|
1052
|
-
|
|
1053
|
-
# use traces_sample_rate, traces_sampler, and/or inheritance to make a
|
|
1054
|
-
# sampling decision
|
|
1055
|
-
sampling_context = {
|
|
1056
|
-
"transaction_context": transaction.to_json(),
|
|
1057
|
-
"parent_sampled": transaction.parent_sampled,
|
|
1058
|
-
}
|
|
1059
|
-
sampling_context.update(custom_sampling_context)
|
|
1060
|
-
transaction._set_initial_sampling_decision(sampling_context=sampling_context)
|
|
1061
|
-
|
|
1062
|
-
# update the sample rate in the dsc
|
|
1063
|
-
if transaction.sample_rate is not None:
|
|
1064
|
-
propagation_context = self.get_active_propagation_context()
|
|
1065
|
-
if propagation_context:
|
|
1066
|
-
dsc = propagation_context.dynamic_sampling_context
|
|
1067
|
-
if dsc is not None:
|
|
1068
|
-
dsc["sample_rate"] = str(transaction.sample_rate)
|
|
1069
|
-
if transaction._baggage:
|
|
1070
|
-
transaction._baggage.sentry_items["sample_rate"] = str(
|
|
1071
|
-
transaction.sample_rate
|
|
1072
|
-
)
|
|
1073
|
-
|
|
1074
|
-
if transaction.sampled:
|
|
1075
|
-
profile = Profile(
|
|
1076
|
-
transaction.sampled, transaction._start_timestamp_monotonic_ns
|
|
1077
|
-
)
|
|
1078
|
-
profile._set_initial_sampling_decision(sampling_context=sampling_context)
|
|
1079
|
-
|
|
1080
|
-
transaction._profile = profile
|
|
1081
|
-
|
|
1082
|
-
transaction._continuous_profile = try_profile_lifecycle_trace_start()
|
|
1083
|
-
|
|
1084
|
-
# Typically, the profiler is set when the transaction is created. But when
|
|
1085
|
-
# using the auto lifecycle, the profiler isn't running when the first
|
|
1086
|
-
# transaction is started. So make sure we update the profiler id on it.
|
|
1087
|
-
if transaction._continuous_profile is not None:
|
|
1088
|
-
transaction.set_profiler_id(get_profiler_id())
|
|
1089
|
-
|
|
1090
|
-
# we don't bother to keep spans if we already know we're not going to
|
|
1091
|
-
# send the transaction
|
|
1092
|
-
max_spans = (client.options["_experiments"].get("max_spans")) or 1000
|
|
1093
|
-
transaction.init_span_recorder(maxlen=max_spans)
|
|
1094
|
-
|
|
1095
|
-
return transaction
|
|
897
|
+
warnings.warn(
|
|
898
|
+
"The `start_transaction` method is deprecated, please use `sentry_sdk.start_span instead.`",
|
|
899
|
+
DeprecationWarning,
|
|
900
|
+
stacklevel=2,
|
|
901
|
+
)
|
|
902
|
+
return NoOpSpan(**kwargs)
|
|
1096
903
|
|
|
1097
|
-
def start_span(self,
|
|
1098
|
-
# type: (
|
|
904
|
+
def start_span(self, **kwargs):
|
|
905
|
+
# type: (Any) -> Union[NoOpSpan, Span]
|
|
1099
906
|
"""
|
|
1100
|
-
Start a span whose parent is the currently active span
|
|
907
|
+
Start a span whose parent is the currently active span, if any.
|
|
1101
908
|
|
|
1102
909
|
The return value is a :py:class:`sentry_sdk.tracing.Span` instance,
|
|
1103
910
|
typically used as a context manager to start and stop timing in a `with`
|
|
1104
911
|
block.
|
|
1105
912
|
|
|
1106
|
-
Only spans contained in a transaction are sent to Sentry. Most
|
|
1107
|
-
integrations start a transaction at the appropriate time, for example
|
|
1108
|
-
for every incoming HTTP request. Use
|
|
1109
|
-
:py:meth:`sentry_sdk.start_transaction` to start a new transaction when
|
|
1110
|
-
one is not already in progress.
|
|
1111
|
-
|
|
1112
913
|
For supported `**kwargs` see :py:class:`sentry_sdk.tracing.Span`.
|
|
1113
|
-
|
|
1114
|
-
The instrumenter parameter is deprecated for user code, and it will
|
|
1115
|
-
be removed in the next major version. Going forward, it should only
|
|
1116
|
-
be used by the SDK itself.
|
|
1117
914
|
"""
|
|
1118
|
-
|
|
1119
|
-
warnings.warn(
|
|
1120
|
-
"The `description` parameter is deprecated. Please use `name` instead.",
|
|
1121
|
-
DeprecationWarning,
|
|
1122
|
-
stacklevel=2,
|
|
1123
|
-
)
|
|
1124
|
-
|
|
1125
|
-
with new_scope():
|
|
1126
|
-
kwargs.setdefault("scope", self)
|
|
1127
|
-
|
|
1128
|
-
client = self.get_client()
|
|
1129
|
-
|
|
1130
|
-
configuration_instrumenter = client.options["instrumenter"]
|
|
1131
|
-
|
|
1132
|
-
if instrumenter != configuration_instrumenter:
|
|
1133
|
-
return NoOpSpan()
|
|
1134
|
-
|
|
1135
|
-
# get current span or transaction
|
|
1136
|
-
span = self.span or self.get_isolation_scope().span
|
|
1137
|
-
|
|
1138
|
-
if span is None:
|
|
1139
|
-
# New spans get the `trace_id` from the scope
|
|
1140
|
-
if "trace_id" not in kwargs:
|
|
1141
|
-
propagation_context = self.get_active_propagation_context()
|
|
1142
|
-
if propagation_context is not None:
|
|
1143
|
-
kwargs["trace_id"] = propagation_context.trace_id
|
|
915
|
+
return NoOpSpan(**kwargs)
|
|
1144
916
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
span = span.start_child(**kwargs)
|
|
1149
|
-
|
|
1150
|
-
return span
|
|
1151
|
-
|
|
1152
|
-
def continue_trace(
|
|
1153
|
-
self, environ_or_headers, op=None, name=None, source=None, origin="manual"
|
|
1154
|
-
):
|
|
1155
|
-
# type: (Dict[str, Any], Optional[str], Optional[str], Optional[str], str) -> Transaction
|
|
917
|
+
@contextmanager
|
|
918
|
+
def continue_trace(self, environ_or_headers):
|
|
919
|
+
# type: (Dict[str, Any]) -> Generator[None, None, None]
|
|
1156
920
|
"""
|
|
1157
|
-
Sets the propagation context from environment or headers
|
|
921
|
+
Sets the propagation context from environment or headers to continue an incoming trace.
|
|
1158
922
|
"""
|
|
1159
923
|
self.generate_propagation_context(environ_or_headers)
|
|
1160
|
-
|
|
1161
|
-
# When we generate the propagation context, the sample_rand value is set
|
|
1162
|
-
# if missing or invalid (we use the original value if it's valid).
|
|
1163
|
-
# We want the transaction to use the same sample_rand value. Due to duplicated
|
|
1164
|
-
# propagation logic in the transaction, we pass it in to avoid recomputing it
|
|
1165
|
-
# in the transaction.
|
|
1166
|
-
# TYPE SAFETY: self.generate_propagation_context() ensures that self._propagation_context
|
|
1167
|
-
# is not None.
|
|
1168
|
-
sample_rand = typing.cast(
|
|
1169
|
-
PropagationContext, self._propagation_context
|
|
1170
|
-
)._sample_rand()
|
|
1171
|
-
|
|
1172
|
-
transaction = Transaction.continue_from_headers(
|
|
1173
|
-
normalize_incoming_data(environ_or_headers),
|
|
1174
|
-
_sample_rand=sample_rand,
|
|
1175
|
-
op=op,
|
|
1176
|
-
origin=origin,
|
|
1177
|
-
name=name,
|
|
1178
|
-
source=source,
|
|
1179
|
-
)
|
|
1180
|
-
|
|
1181
|
-
return transaction
|
|
924
|
+
yield
|
|
1182
925
|
|
|
1183
926
|
def capture_event(self, event, hint=None, scope=None, **scope_kwargs):
|
|
1184
927
|
# type: (Event, Optional[Hint], Optional[Scope], Any) -> Optional[str]
|
|
@@ -1432,7 +1175,11 @@ class Scope:
|
|
|
1432
1175
|
|
|
1433
1176
|
# Add "trace" context
|
|
1434
1177
|
if contexts.get("trace") is None:
|
|
1435
|
-
if
|
|
1178
|
+
if (
|
|
1179
|
+
has_tracing_enabled(options)
|
|
1180
|
+
and self._span is not None
|
|
1181
|
+
and self._span.is_valid
|
|
1182
|
+
):
|
|
1436
1183
|
contexts["trace"] = self._span.get_trace_context()
|
|
1437
1184
|
else:
|
|
1438
1185
|
contexts["trace"] = self.get_trace_context()
|
|
@@ -1482,8 +1229,8 @@ class Scope:
|
|
|
1482
1229
|
|
|
1483
1230
|
if not is_check_in:
|
|
1484
1231
|
# Get scopes without creating them to prevent infinite recursion
|
|
1485
|
-
isolation_scope =
|
|
1486
|
-
current_scope =
|
|
1232
|
+
isolation_scope = self._get_isolation_scope()
|
|
1233
|
+
current_scope = self._get_current_scope()
|
|
1487
1234
|
|
|
1488
1235
|
event_processors = chain(
|
|
1489
1236
|
global_event_processors,
|
|
@@ -1493,7 +1240,7 @@ class Scope:
|
|
|
1493
1240
|
)
|
|
1494
1241
|
|
|
1495
1242
|
for event_processor in event_processors:
|
|
1496
|
-
new_event = event
|
|
1243
|
+
new_event = event # type: Optional[Event]
|
|
1497
1244
|
with capture_internal_exceptions():
|
|
1498
1245
|
new_event = event_processor(event, hint)
|
|
1499
1246
|
if new_event is None:
|