3535TRANSACTION_SOURCE_COMPONENT = "component"
3636TRANSACTION_SOURCE_TASK = "task"
3737
38+ # These are typically high cardinality and the server hates them
39+ LOW_QUALITY_TRANSACTION_SOURCES = [
40+ TRANSACTION_SOURCE_URL ,
41+ ]
42+
3843SOURCE_FOR_STYLE = {
3944 "endpoint" : TRANSACTION_SOURCE_COMPONENT ,
4045 "function_name" : TRANSACTION_SOURCE_COMPONENT ,
@@ -281,6 +286,10 @@ def continue_from_headers(
281286
282287 if sentrytrace_kwargs is not None :
283288 kwargs .update (sentrytrace_kwargs )
289+
290+ # If there's an incoming sentry-trace but no incoming baggage header,
291+ # for instance in traces coming from older SDKs,
292+ # baggage will be empty and immutable and won't be populated as head SDK.
284293 baggage .freeze ()
285294
286295 kwargs .update (extract_tracestate_data (headers .get ("tracestate" )))
@@ -309,8 +318,8 @@ def iter_headers(self):
309318 if tracestate :
310319 yield "tracestate" , tracestate
311320
312- if self .containing_transaction and self . containing_transaction . _baggage :
313- baggage = self .containing_transaction ._baggage .serialize ()
321+ if self .containing_transaction :
322+ baggage = self .containing_transaction .get_baggage () .serialize ()
314323 if baggage :
315324 yield "baggage" , baggage
316325
@@ -513,11 +522,10 @@ def get_trace_context(self):
513522 if sentry_tracestate :
514523 rv ["tracestate" ] = sentry_tracestate
515524
516- # TODO-neel populate fresh if head SDK
517- if self .containing_transaction and self .containing_transaction ._baggage :
525+ if self .containing_transaction :
518526 rv [
519527 "dynamic_sampling_context"
520- ] = self .containing_transaction ._baggage .dynamic_sampling_context ()
528+ ] = self .containing_transaction .get_baggage () .dynamic_sampling_context ()
521529
522530 return rv
523531
@@ -527,6 +535,7 @@ class Transaction(Span):
527535 "name" ,
528536 "source" ,
529537 "parent_sampled" ,
538+ "sample_rate" ,
530539 # the sentry portion of the `tracestate` header used to transmit
531540 # correlation context for server-side dynamic sampling, of the form
532541 # `sentry=xxxxx`, where `xxxxx` is the base64-encoded json of the
@@ -562,6 +571,7 @@ def __init__(
562571 Span .__init__ (self , ** kwargs )
563572 self .name = name
564573 self .source = source
574+ self .sample_rate = None # type: Optional[float]
565575 self .parent_sampled = parent_sampled
566576 # if tracestate isn't inherited and set here, it will get set lazily,
567577 # either the first time an outgoing request needs it for a header or the
@@ -570,7 +580,7 @@ def __init__(
570580 self ._third_party_tracestate = third_party_tracestate
571581 self ._measurements = {} # type: Dict[str, Any]
572582 self ._profile = None # type: Optional[Sampler]
573- self ._baggage = baggage
583+ self ._baggage = baggage # type: Optional[Baggage]
574584
575585 def __repr__ (self ):
576586 # type: () -> str
@@ -708,6 +718,17 @@ def to_json(self):
708718
709719 return rv
710720
721+ def get_baggage (self ):
722+ # type: () -> Baggage
723+ """
724+ The first time a new baggage with sentry items is made,
725+ it will be frozen.
726+ """
727+ if not self ._baggage or self ._baggage .mutable :
728+ self ._baggage = Baggage .populate_from_transaction (self )
729+
730+ return self ._baggage
731+
711732 def _set_initial_sampling_decision (self , sampling_context ):
712733 # type: (SamplingContext) -> None
713734 """
@@ -773,6 +794,9 @@ def _set_initial_sampling_decision(self, sampling_context):
773794 self .sampled = False
774795 return
775796
797+ # used to create baggage value for head SDKs in dynamic sampling
798+ self .sample_rate = float (sample_rate )
799+
776800 # if the function returned 0 (or false), or if `traces_sample_rate` is
777801 # 0, it's a sign the transaction should be dropped
778802 if not sample_rate :
0 commit comments