diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 8e55add770..14b6fdfa4c 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -530,9 +530,7 @@ def get_dynamic_sampling_context(self): baggage = self.get_baggage() if baggage is not None: - self._propagation_context.dynamic_sampling_context = ( - baggage.dynamic_sampling_context() - ) + self._propagation_context.baggage = baggage return self._propagation_context.dynamic_sampling_context @@ -573,13 +571,7 @@ def get_baggage(self, *args, **kwargs): # If this scope has a propagation context, return baggage from there if self._propagation_context is not None: - dynamic_sampling_context = ( - self._propagation_context.dynamic_sampling_context - ) - if dynamic_sampling_context is None: - return Baggage.from_options(self) - else: - return Baggage(dynamic_sampling_context) + return self._propagation_context.baggage or Baggage.from_options(self) # Fall back to isolation scope's baggage. It always has one return self.get_isolation_scope().get_baggage() @@ -1099,9 +1091,9 @@ def start_transaction( if transaction.sample_rate is not None: propagation_context = self.get_active_propagation_context() if propagation_context: - dsc = propagation_context.dynamic_sampling_context - if dsc is not None: - dsc["sample_rate"] = str(transaction.sample_rate) + baggage = propagation_context.baggage + if baggage is not None: + baggage.sentry_items["sample_rate"] = str(transaction.sample_rate) if transaction._baggage: transaction._baggage.sentry_items["sample_rate"] = str( transaction.sample_rate diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index d044711ce1..472bd6bbdd 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -411,7 +411,7 @@ class PropagationContext: "_span_id", "parent_span_id", "parent_sampled", - "dynamic_sampling_context", + "baggage", ) def __init__( @@ -421,6 +421,7 @@ def __init__( parent_span_id=None, # type: Optional[str] parent_sampled=None, # type: Optional[bool] dynamic_sampling_context=None, # type: Optional[Dict[str, str]] + baggage=None, # type: Optional[Baggage] ): # type: (...) -> None self._trace_id = trace_id @@ -438,8 +439,12 @@ def __init__( Important when the parent span originated in an upstream service, because we want to sample the whole trace, or nothing from the trace.""" - self.dynamic_sampling_context = dynamic_sampling_context - """Data that is used for dynamic sampling decisions.""" + self.baggage = baggage + """Parsed baggage header that is used for dynamic sampling decisions.""" + + """DEPRECATED this only exists for backwards compat of constructor.""" + if baggage is None and dynamic_sampling_context is not None: + self.baggage = Baggage(dynamic_sampling_context) @classmethod def from_incoming_data(cls, incoming_data): @@ -456,9 +461,7 @@ def from_incoming_data(cls, incoming_data): baggage_header = normalized_data.get(BAGGAGE_HEADER_NAME) if baggage_header: - propagation_context.dynamic_sampling_context = Baggage.from_incoming_header( - baggage_header - ).dynamic_sampling_context() + propagation_context.baggage = Baggage.from_incoming_header(baggage_header) propagation_context._fill_sample_rand() @@ -493,6 +496,11 @@ def span_id(self, value): # type: (str) -> None self._span_id = value + @property + def dynamic_sampling_context(self): + # type: () -> Optional[Dict[str, Any]] + return self.baggage.dynamic_sampling_context() if self.baggage else None + def update(self, other_dict): # type: (Dict[str, Any]) -> None """ @@ -506,20 +514,20 @@ def update(self, other_dict): def __repr__(self): # type: (...) -> str - return "".format( + return "".format( self._trace_id, self._span_id, self.parent_span_id, self.parent_sampled, - self.dynamic_sampling_context, + self.baggage, ) def _fill_sample_rand(self): # type: () -> None """ - Ensure that there is a valid sample_rand value in the dynamic_sampling_context. + Ensure that there is a valid sample_rand value in the baggage. - If there is a valid sample_rand value in the dynamic_sampling_context, we keep it. + If there is a valid sample_rand value in the baggage, we keep it. Otherwise, we generate a sample_rand value according to the following: - If we have a parent_sampled value and a sample_rate in the DSC, we compute @@ -532,23 +540,19 @@ def _fill_sample_rand(self): The sample_rand is deterministically generated from the trace_id, if present. - This function does nothing if there is no dynamic_sampling_context. + This function does nothing if there is no baggage. """ - if self.dynamic_sampling_context is None: + if self.baggage is None: return - sample_rand = try_convert( - float, self.dynamic_sampling_context.get("sample_rand") - ) + sample_rand = try_convert(float, self.baggage.sentry_items.get("sample_rand")) if sample_rand is not None and 0 <= sample_rand < 1: # sample_rand is present and valid, so don't overwrite it return # Get the sample rate and compute the transformation that will map the random value # to the desired range: [0, 1), [0, sample_rate), or [sample_rate, 1). - sample_rate = try_convert( - float, self.dynamic_sampling_context.get("sample_rate") - ) + sample_rate = try_convert(float, self.baggage.sentry_items.get("sample_rate")) lower, upper = _sample_rand_range(self.parent_sampled, sample_rate) try: @@ -564,15 +568,15 @@ def _fill_sample_rand(self): ) return - self.dynamic_sampling_context["sample_rand"] = f"{sample_rand:.6f}" # noqa: E231 + self.baggage.sentry_items["sample_rand"] = f"{sample_rand:.6f}" # noqa: E231 def _sample_rand(self): # type: () -> Optional[str] - """Convenience method to get the sample_rand value from the dynamic_sampling_context.""" - if self.dynamic_sampling_context is None: + """Convenience method to get the sample_rand value from the baggage.""" + if self.baggage is None: return None - return self.dynamic_sampling_context.get("sample_rand") + return self.baggage.sentry_items.get("sample_rand") class Baggage: