sentry-sdk 2.26.1__py2.py3-none-any.whl → 3.0.0a1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sentry-sdk might be problematic. Click here for more details.
- sentry_sdk/__init__.py +4 -8
- sentry_sdk/_compat.py +0 -1
- sentry_sdk/_init_implementation.py +6 -44
- sentry_sdk/_log_batcher.py +47 -28
- sentry_sdk/_types.py +8 -64
- sentry_sdk/ai/monitoring.py +14 -10
- sentry_sdk/ai/utils.py +1 -1
- sentry_sdk/api.py +69 -163
- sentry_sdk/client.py +25 -72
- sentry_sdk/consts.py +42 -23
- sentry_sdk/debug.py +0 -10
- sentry_sdk/envelope.py +2 -10
- sentry_sdk/feature_flags.py +5 -1
- sentry_sdk/integrations/__init__.py +5 -2
- sentry_sdk/integrations/_asgi_common.py +3 -3
- sentry_sdk/integrations/_wsgi_common.py +11 -40
- sentry_sdk/integrations/aiohttp.py +104 -57
- sentry_sdk/integrations/anthropic.py +10 -7
- sentry_sdk/integrations/arq.py +24 -13
- sentry_sdk/integrations/asgi.py +103 -83
- sentry_sdk/integrations/asyncio.py +1 -0
- sentry_sdk/integrations/asyncpg.py +45 -30
- sentry_sdk/integrations/aws_lambda.py +109 -92
- sentry_sdk/integrations/boto3.py +38 -9
- sentry_sdk/integrations/bottle.py +1 -1
- sentry_sdk/integrations/celery/__init__.py +48 -38
- sentry_sdk/integrations/clickhouse_driver.py +59 -28
- sentry_sdk/integrations/cohere.py +2 -0
- sentry_sdk/integrations/django/__init__.py +25 -46
- sentry_sdk/integrations/django/asgi.py +6 -2
- sentry_sdk/integrations/django/caching.py +13 -22
- sentry_sdk/integrations/django/middleware.py +1 -0
- sentry_sdk/integrations/django/signals_handlers.py +3 -1
- sentry_sdk/integrations/django/templates.py +8 -12
- sentry_sdk/integrations/django/transactions.py +1 -6
- sentry_sdk/integrations/django/views.py +5 -2
- sentry_sdk/integrations/falcon.py +7 -25
- sentry_sdk/integrations/fastapi.py +3 -3
- sentry_sdk/integrations/flask.py +1 -1
- sentry_sdk/integrations/gcp.py +63 -38
- sentry_sdk/integrations/graphene.py +6 -13
- sentry_sdk/integrations/grpc/aio/client.py +14 -8
- sentry_sdk/integrations/grpc/aio/server.py +19 -21
- sentry_sdk/integrations/grpc/client.py +8 -6
- sentry_sdk/integrations/grpc/server.py +12 -14
- sentry_sdk/integrations/httpx.py +47 -12
- sentry_sdk/integrations/huey.py +26 -22
- sentry_sdk/integrations/huggingface_hub.py +1 -0
- sentry_sdk/integrations/langchain.py +22 -15
- sentry_sdk/integrations/launchdarkly.py +3 -3
- sentry_sdk/integrations/litestar.py +4 -2
- sentry_sdk/integrations/logging.py +12 -3
- sentry_sdk/integrations/openai.py +2 -0
- sentry_sdk/integrations/openfeature.py +3 -5
- sentry_sdk/integrations/pymongo.py +18 -25
- sentry_sdk/integrations/pyramid.py +1 -1
- sentry_sdk/integrations/quart.py +3 -3
- sentry_sdk/integrations/ray.py +23 -17
- sentry_sdk/integrations/redis/_async_common.py +30 -18
- sentry_sdk/integrations/redis/_sync_common.py +28 -18
- sentry_sdk/integrations/redis/modules/caches.py +13 -10
- sentry_sdk/integrations/redis/modules/queries.py +14 -11
- sentry_sdk/integrations/redis/rb.py +4 -4
- sentry_sdk/integrations/redis/redis.py +6 -6
- sentry_sdk/integrations/redis/redis_cluster.py +18 -16
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +4 -4
- sentry_sdk/integrations/redis/utils.py +63 -19
- sentry_sdk/integrations/rq.py +68 -23
- sentry_sdk/integrations/rust_tracing.py +28 -43
- sentry_sdk/integrations/sanic.py +23 -13
- sentry_sdk/integrations/socket.py +9 -5
- sentry_sdk/integrations/sqlalchemy.py +8 -8
- sentry_sdk/integrations/starlette.py +11 -31
- sentry_sdk/integrations/starlite.py +4 -2
- sentry_sdk/integrations/stdlib.py +56 -9
- sentry_sdk/integrations/strawberry.py +40 -59
- sentry_sdk/integrations/threading.py +10 -26
- sentry_sdk/integrations/tornado.py +57 -18
- sentry_sdk/integrations/trytond.py +4 -1
- sentry_sdk/integrations/unleash.py +2 -3
- sentry_sdk/integrations/wsgi.py +84 -38
- sentry_sdk/opentelemetry/__init__.py +9 -0
- sentry_sdk/opentelemetry/consts.py +33 -0
- sentry_sdk/opentelemetry/contextvars_context.py +73 -0
- sentry_sdk/{integrations/opentelemetry → opentelemetry}/propagator.py +19 -28
- sentry_sdk/opentelemetry/sampler.py +326 -0
- sentry_sdk/opentelemetry/scope.py +218 -0
- sentry_sdk/opentelemetry/span_processor.py +329 -0
- sentry_sdk/opentelemetry/tracing.py +35 -0
- sentry_sdk/opentelemetry/utils.py +476 -0
- sentry_sdk/profiler/__init__.py +0 -40
- sentry_sdk/profiler/continuous_profiler.py +1 -30
- sentry_sdk/profiler/transaction_profiler.py +5 -56
- sentry_sdk/scope.py +107 -351
- sentry_sdk/sessions.py +0 -87
- sentry_sdk/tracing.py +418 -1134
- sentry_sdk/tracing_utils.py +134 -169
- sentry_sdk/transport.py +4 -104
- sentry_sdk/types.py +26 -2
- sentry_sdk/utils.py +169 -152
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/METADATA +3 -5
- sentry_sdk-3.0.0a1.dist-info/RECORD +154 -0
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/WHEEL +1 -1
- sentry_sdk-3.0.0a1.dist-info/entry_points.txt +2 -0
- sentry_sdk/hub.py +0 -739
- sentry_sdk/integrations/opentelemetry/__init__.py +0 -7
- sentry_sdk/integrations/opentelemetry/consts.py +0 -5
- sentry_sdk/integrations/opentelemetry/integration.py +0 -58
- sentry_sdk/integrations/opentelemetry/span_processor.py +0 -391
- sentry_sdk/metrics.py +0 -965
- sentry_sdk-2.26.1.dist-info/RECORD +0 -152
- sentry_sdk-2.26.1.dist-info/entry_points.txt +0 -2
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-2.26.1.dist-info → sentry_sdk-3.0.0a1.dist-info}/top_level.txt +0 -0
sentry_sdk/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)
|
|
@@ -225,12 +194,12 @@ class Scope:
|
|
|
225
194
|
self.generate_propagation_context(incoming_data=incoming_trace_information)
|
|
226
195
|
|
|
227
196
|
def __copy__(self):
|
|
228
|
-
# type: () ->
|
|
197
|
+
# type: () -> Self
|
|
229
198
|
"""
|
|
230
199
|
Returns a copy of this scope.
|
|
231
200
|
This also creates a copy of all referenced data structures.
|
|
232
201
|
"""
|
|
233
|
-
rv = object.__new__(self.__class__) # type:
|
|
202
|
+
rv = object.__new__(self.__class__) # type: Self
|
|
234
203
|
|
|
235
204
|
rv._type = self._type
|
|
236
205
|
rv.client = self.client
|
|
@@ -273,13 +242,21 @@ class Scope:
|
|
|
273
242
|
|
|
274
243
|
Returns the current scope.
|
|
275
244
|
"""
|
|
276
|
-
current_scope =
|
|
245
|
+
current_scope = cls._get_current_scope()
|
|
277
246
|
if current_scope is None:
|
|
278
247
|
current_scope = Scope(ty=ScopeType.CURRENT)
|
|
279
248
|
_current_scope.set(current_scope)
|
|
280
249
|
|
|
281
250
|
return current_scope
|
|
282
251
|
|
|
252
|
+
@classmethod
|
|
253
|
+
def _get_current_scope(cls):
|
|
254
|
+
# type: () -> Optional[Scope]
|
|
255
|
+
"""
|
|
256
|
+
Returns the current scope without creating a new one. Internal use only.
|
|
257
|
+
"""
|
|
258
|
+
return _current_scope.get()
|
|
259
|
+
|
|
283
260
|
@classmethod
|
|
284
261
|
def set_current_scope(cls, new_current_scope):
|
|
285
262
|
# type: (Scope) -> None
|
|
@@ -299,13 +276,21 @@ class Scope:
|
|
|
299
276
|
|
|
300
277
|
Returns the isolation scope.
|
|
301
278
|
"""
|
|
302
|
-
isolation_scope =
|
|
279
|
+
isolation_scope = cls._get_isolation_scope()
|
|
303
280
|
if isolation_scope is None:
|
|
304
281
|
isolation_scope = Scope(ty=ScopeType.ISOLATION)
|
|
305
282
|
_isolation_scope.set(isolation_scope)
|
|
306
283
|
|
|
307
284
|
return isolation_scope
|
|
308
285
|
|
|
286
|
+
@classmethod
|
|
287
|
+
def _get_isolation_scope(cls):
|
|
288
|
+
# type: () -> Optional[Scope]
|
|
289
|
+
"""
|
|
290
|
+
Returns the isolation scope without creating a new one. Internal use only.
|
|
291
|
+
"""
|
|
292
|
+
return _isolation_scope.get()
|
|
293
|
+
|
|
309
294
|
@classmethod
|
|
310
295
|
def set_isolation_scope(cls, new_isolation_scope):
|
|
311
296
|
# type: (Scope) -> None
|
|
@@ -349,7 +334,7 @@ class Scope:
|
|
|
349
334
|
return cls.get_isolation_scope()._last_event_id
|
|
350
335
|
|
|
351
336
|
def _merge_scopes(self, additional_scope=None, additional_scope_kwargs=None):
|
|
352
|
-
# type: (Optional[Scope], Optional[Dict[str, Any]]) ->
|
|
337
|
+
# type: (Optional[Scope], Optional[Dict[str, Any]]) -> Self
|
|
353
338
|
"""
|
|
354
339
|
Merges global, isolation and current scope into a new scope and
|
|
355
340
|
adds the given additional scope or additional scope kwargs to it.
|
|
@@ -357,16 +342,17 @@ class Scope:
|
|
|
357
342
|
if additional_scope and additional_scope_kwargs:
|
|
358
343
|
raise TypeError("cannot provide scope and kwargs")
|
|
359
344
|
|
|
360
|
-
final_scope =
|
|
345
|
+
final_scope = self.__class__()
|
|
361
346
|
final_scope._type = ScopeType.MERGED
|
|
362
347
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
final_scope.update_from_scope(isolation_scope)
|
|
348
|
+
global_scope = self.get_global_scope()
|
|
349
|
+
final_scope.update_from_scope(global_scope)
|
|
366
350
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
351
|
+
isolation_scope = self.get_isolation_scope()
|
|
352
|
+
final_scope.update_from_scope(self.get_isolation_scope())
|
|
353
|
+
|
|
354
|
+
current_scope = self.get_current_scope()
|
|
355
|
+
final_scope.update_from_scope(current_scope)
|
|
370
356
|
|
|
371
357
|
if self != current_scope and self != isolation_scope:
|
|
372
358
|
final_scope.update_from_scope(self)
|
|
@@ -392,7 +378,7 @@ class Scope:
|
|
|
392
378
|
This checks the current scope, the isolation scope and the global scope for a client.
|
|
393
379
|
If no client is available a :py:class:`sentry_sdk.client.NonRecordingClient` is returned.
|
|
394
380
|
"""
|
|
395
|
-
current_scope =
|
|
381
|
+
current_scope = cls.get_current_scope()
|
|
396
382
|
try:
|
|
397
383
|
client = current_scope.client
|
|
398
384
|
except AttributeError:
|
|
@@ -401,7 +387,7 @@ class Scope:
|
|
|
401
387
|
if client is not None and client.is_active():
|
|
402
388
|
return client
|
|
403
389
|
|
|
404
|
-
isolation_scope =
|
|
390
|
+
isolation_scope = cls.get_isolation_scope()
|
|
405
391
|
try:
|
|
406
392
|
client = isolation_scope.client
|
|
407
393
|
except AttributeError:
|
|
@@ -434,7 +420,7 @@ class Scope:
|
|
|
434
420
|
self.client = client if client is not None else NonRecordingClient()
|
|
435
421
|
|
|
436
422
|
def fork(self):
|
|
437
|
-
# type: () ->
|
|
423
|
+
# type: () -> Self
|
|
438
424
|
"""
|
|
439
425
|
.. versionadded:: 2.0.0
|
|
440
426
|
|
|
@@ -496,19 +482,10 @@ class Scope:
|
|
|
496
482
|
def get_dynamic_sampling_context(self):
|
|
497
483
|
# type: () -> Optional[Dict[str, str]]
|
|
498
484
|
"""
|
|
499
|
-
Returns the Dynamic Sampling Context from the
|
|
500
|
-
If not existing, creates a new one.
|
|
485
|
+
Returns the Dynamic Sampling Context from the baggage or populates one.
|
|
501
486
|
"""
|
|
502
|
-
if self._propagation_context is None:
|
|
503
|
-
return None
|
|
504
|
-
|
|
505
487
|
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
|
|
488
|
+
return baggage.dynamic_sampling_context() if baggage else None
|
|
512
489
|
|
|
513
490
|
def get_traceparent(self, *args, **kwargs):
|
|
514
491
|
# type: (Any, Any) -> Optional[str]
|
|
@@ -519,16 +496,16 @@ class Scope:
|
|
|
519
496
|
client = self.get_client()
|
|
520
497
|
|
|
521
498
|
# If we have an active span, return traceparent from there
|
|
522
|
-
if
|
|
499
|
+
if (
|
|
500
|
+
has_tracing_enabled(client.options)
|
|
501
|
+
and self.span is not None
|
|
502
|
+
and self.span.is_valid
|
|
503
|
+
):
|
|
523
504
|
return self.span.to_traceparent()
|
|
524
505
|
|
|
525
506
|
# If this scope has a propagation context, return traceparent from there
|
|
526
507
|
if self._propagation_context is not None:
|
|
527
|
-
|
|
528
|
-
self._propagation_context.trace_id,
|
|
529
|
-
self._propagation_context.span_id,
|
|
530
|
-
)
|
|
531
|
-
return traceparent
|
|
508
|
+
return self._propagation_context.to_traceparent()
|
|
532
509
|
|
|
533
510
|
# Fall back to isolation scope's traceparent. It always has one
|
|
534
511
|
return self.get_isolation_scope().get_traceparent()
|
|
@@ -538,22 +515,24 @@ class Scope:
|
|
|
538
515
|
"""
|
|
539
516
|
Returns the Sentry "baggage" header containing trace information from the
|
|
540
517
|
currently active span or the scopes Propagation Context.
|
|
518
|
+
If not existing, creates a new one.
|
|
541
519
|
"""
|
|
542
520
|
client = self.get_client()
|
|
543
521
|
|
|
544
522
|
# If we have an active span, return baggage from there
|
|
545
|
-
if
|
|
523
|
+
if (
|
|
524
|
+
has_tracing_enabled(client.options)
|
|
525
|
+
and self.span is not None
|
|
526
|
+
and self.span.is_valid
|
|
527
|
+
):
|
|
546
528
|
return self.span.to_baggage()
|
|
547
529
|
|
|
548
530
|
# If this scope has a propagation context, return baggage from there
|
|
531
|
+
# populate a fresh one if it doesn't exist
|
|
549
532
|
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)
|
|
533
|
+
if self._propagation_context.baggage is None:
|
|
534
|
+
self._propagation_context.baggage = Baggage.from_options(self)
|
|
535
|
+
return self._propagation_context.baggage
|
|
557
536
|
|
|
558
537
|
# Fall back to isolation scope's baggage. It always has one
|
|
559
538
|
return self.get_isolation_scope().get_baggage()
|
|
@@ -581,12 +560,6 @@ class Scope:
|
|
|
581
560
|
Return meta tags which should be injected into HTML templates
|
|
582
561
|
to allow propagation of trace information.
|
|
583
562
|
"""
|
|
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
563
|
meta = ""
|
|
591
564
|
|
|
592
565
|
sentry_trace = self.get_traceparent()
|
|
@@ -615,10 +588,9 @@ class Scope:
|
|
|
615
588
|
if traceparent is not None:
|
|
616
589
|
yield SENTRY_TRACE_HEADER_NAME, traceparent
|
|
617
590
|
|
|
618
|
-
|
|
619
|
-
if
|
|
620
|
-
|
|
621
|
-
yield BAGGAGE_HEADER_NAME, baggage
|
|
591
|
+
baggage = self.get_baggage()
|
|
592
|
+
if baggage is not None:
|
|
593
|
+
yield BAGGAGE_HEADER_NAME, baggage.serialize()
|
|
622
594
|
|
|
623
595
|
def iter_trace_propagation_headers(self, *args, **kwargs):
|
|
624
596
|
# type: (Any, Any) -> Generator[Tuple[str, str], None, None]
|
|
@@ -629,18 +601,11 @@ class Scope:
|
|
|
629
601
|
If no span is given, the trace data is taken from the scope.
|
|
630
602
|
"""
|
|
631
603
|
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
604
|
|
|
640
605
|
span = kwargs.pop("span", None)
|
|
641
606
|
span = span or self.span
|
|
642
607
|
|
|
643
|
-
if has_tracing_enabled(client.options) and span is not None:
|
|
608
|
+
if has_tracing_enabled(client.options) and span is not None and span.is_valid:
|
|
644
609
|
for header in span.iter_headers():
|
|
645
610
|
yield header
|
|
646
611
|
else:
|
|
@@ -706,23 +671,6 @@ class Scope:
|
|
|
706
671
|
self._last_event_id = None # type: Optional[str]
|
|
707
672
|
self._flags = None # type: Optional[FlagBuffer]
|
|
708
673
|
|
|
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
674
|
def set_level(self, value):
|
|
727
675
|
# type: (LogLevelStr) -> None
|
|
728
676
|
"""
|
|
@@ -739,71 +687,36 @@ class Scope:
|
|
|
739
687
|
self._fingerprint = value
|
|
740
688
|
|
|
741
689
|
@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
|
|
690
|
+
def root_span(self):
|
|
691
|
+
# type: () -> Optional[Span]
|
|
692
|
+
"""Return the root span in the scope, if any."""
|
|
748
693
|
if self._span is None:
|
|
749
694
|
return None
|
|
750
695
|
|
|
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
|
|
696
|
+
return self._span.root_span
|
|
783
697
|
|
|
784
698
|
def set_transaction_name(self, name, source=None):
|
|
785
699
|
# type: (str, Optional[str]) -> None
|
|
786
700
|
"""Set the transaction name and optionally the transaction source."""
|
|
787
701
|
self._transaction = name
|
|
788
702
|
|
|
789
|
-
if self._span and self._span.
|
|
790
|
-
self._span.
|
|
703
|
+
if self._span and self._span.root_span:
|
|
704
|
+
self._span.root_span.name = name
|
|
791
705
|
if source:
|
|
792
|
-
self._span.
|
|
706
|
+
self._span.root_span.source = source
|
|
793
707
|
|
|
794
708
|
if source:
|
|
795
709
|
self._transaction_info["source"] = source
|
|
796
710
|
|
|
797
|
-
@
|
|
798
|
-
def
|
|
799
|
-
# type: (Optional[
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
)
|
|
806
|
-
self.set_user(value)
|
|
711
|
+
@property
|
|
712
|
+
def transaction_name(self):
|
|
713
|
+
# type: () -> Optional[str]
|
|
714
|
+
return self._transaction
|
|
715
|
+
|
|
716
|
+
@property
|
|
717
|
+
def transaction_source(self):
|
|
718
|
+
# type: () -> Optional[str]
|
|
719
|
+
return self._transaction_info.get("source")
|
|
807
720
|
|
|
808
721
|
def set_user(self, value):
|
|
809
722
|
# type: (Optional[Dict[str, Any]]) -> None
|
|
@@ -816,21 +729,14 @@ class Scope:
|
|
|
816
729
|
@property
|
|
817
730
|
def span(self):
|
|
818
731
|
# type: () -> Optional[Span]
|
|
819
|
-
"""Get
|
|
732
|
+
"""Get current tracing span."""
|
|
820
733
|
return self._span
|
|
821
734
|
|
|
822
735
|
@span.setter
|
|
823
736
|
def span(self, span):
|
|
824
737
|
# type: (Optional[Span]) -> None
|
|
738
|
+
"""Set current tracing span."""
|
|
825
739
|
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
740
|
|
|
835
741
|
@property
|
|
836
742
|
def profile(self):
|
|
@@ -990,195 +896,41 @@ class Scope:
|
|
|
990
896
|
self._breadcrumbs.popleft()
|
|
991
897
|
self._n_breadcrumbs_truncated += 1
|
|
992
898
|
|
|
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]
|
|
899
|
+
def start_transaction(self, **kwargs):
|
|
900
|
+
# type: (Any) -> Union[NoOpSpan, Span]
|
|
1001
901
|
"""
|
|
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.
|
|
902
|
+
.. deprecated:: 3.0.0
|
|
903
|
+
This function is deprecated and will be removed in a future release.
|
|
904
|
+
Use :py:meth:`sentry_sdk.start_span` instead.
|
|
1031
905
|
"""
|
|
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
|
|
906
|
+
warnings.warn(
|
|
907
|
+
"The `start_transaction` method is deprecated, please use `sentry_sdk.start_span instead.`",
|
|
908
|
+
DeprecationWarning,
|
|
909
|
+
stacklevel=2,
|
|
910
|
+
)
|
|
911
|
+
return NoOpSpan(**kwargs)
|
|
1096
912
|
|
|
1097
|
-
def start_span(self,
|
|
1098
|
-
# type: (
|
|
913
|
+
def start_span(self, **kwargs):
|
|
914
|
+
# type: (Any) -> Union[NoOpSpan, Span]
|
|
1099
915
|
"""
|
|
1100
|
-
Start a span whose parent is the currently active span
|
|
916
|
+
Start a span whose parent is the currently active span, if any.
|
|
1101
917
|
|
|
1102
918
|
The return value is a :py:class:`sentry_sdk.tracing.Span` instance,
|
|
1103
919
|
typically used as a context manager to start and stop timing in a `with`
|
|
1104
920
|
block.
|
|
1105
921
|
|
|
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
922
|
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
923
|
"""
|
|
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
|
|
924
|
+
return NoOpSpan(**kwargs)
|
|
1144
925
|
|
|
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
|
|
926
|
+
@contextmanager
|
|
927
|
+
def continue_trace(self, environ_or_headers):
|
|
928
|
+
# type: (Dict[str, Any]) -> Generator[None, None, None]
|
|
1156
929
|
"""
|
|
1157
|
-
Sets the propagation context from environment or headers
|
|
930
|
+
Sets the propagation context from environment or headers to continue an incoming trace.
|
|
1158
931
|
"""
|
|
1159
932
|
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
|
|
933
|
+
yield
|
|
1182
934
|
|
|
1183
935
|
def capture_event(self, event, hint=None, scope=None, **scope_kwargs):
|
|
1184
936
|
# type: (Event, Optional[Hint], Optional[Scope], Any) -> Optional[str]
|
|
@@ -1432,7 +1184,11 @@ class Scope:
|
|
|
1432
1184
|
|
|
1433
1185
|
# Add "trace" context
|
|
1434
1186
|
if contexts.get("trace") is None:
|
|
1435
|
-
if
|
|
1187
|
+
if (
|
|
1188
|
+
has_tracing_enabled(options)
|
|
1189
|
+
and self._span is not None
|
|
1190
|
+
and self._span.is_valid
|
|
1191
|
+
):
|
|
1436
1192
|
contexts["trace"] = self._span.get_trace_context()
|
|
1437
1193
|
else:
|
|
1438
1194
|
contexts["trace"] = self.get_trace_context()
|
|
@@ -1482,8 +1238,8 @@ class Scope:
|
|
|
1482
1238
|
|
|
1483
1239
|
if not is_check_in:
|
|
1484
1240
|
# Get scopes without creating them to prevent infinite recursion
|
|
1485
|
-
isolation_scope =
|
|
1486
|
-
current_scope =
|
|
1241
|
+
isolation_scope = self._get_isolation_scope()
|
|
1242
|
+
current_scope = self._get_current_scope()
|
|
1487
1243
|
|
|
1488
1244
|
event_processors = chain(
|
|
1489
1245
|
global_event_processors,
|
|
@@ -1493,7 +1249,7 @@ class Scope:
|
|
|
1493
1249
|
)
|
|
1494
1250
|
|
|
1495
1251
|
for event_processor in event_processors:
|
|
1496
|
-
new_event = event
|
|
1252
|
+
new_event = event # type: Optional[Event]
|
|
1497
1253
|
with capture_internal_exceptions():
|
|
1498
1254
|
new_event = event_processor(event, hint)
|
|
1499
1255
|
if new_event is None:
|