@@ -50,31 +50,33 @@ def get_parent_sampled(parent_context, trace_id):
5050 return None
5151
5252
53+ def _update_sample_rate (sample_rate : float , trace_state : TraceState ) -> TraceState :
54+ if TRACESTATE_SAMPLE_RATE_KEY in trace_state :
55+ trace_state = trace_state .update (TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate ))
56+ else :
57+ trace_state = trace_state .add (TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate ))
58+
59+ return trace_state
60+
61+
5362def dropped_result (parent_span_context , attributes , sample_rate = None ):
5463 # type: (SpanContext, Attributes, Optional[float]) -> SamplingResult
5564 # these will only be added the first time in a root span sampling decision
65+ # if sample_rate is provided, it'll be updated in trace state
5666 trace_state = parent_span_context .trace_state
5767
5868 if TRACESTATE_SAMPLED_KEY not in trace_state :
5969 trace_state = trace_state .add (TRACESTATE_SAMPLED_KEY , "false" )
6070 elif trace_state .get (TRACESTATE_SAMPLED_KEY ) == "deferred" :
6171 trace_state = trace_state .update (TRACESTATE_SAMPLED_KEY , "false" )
6272
73+ if sample_rate is not None :
74+ trace_state = _update_sample_rate (sample_rate , trace_state )
75+
6376 is_root_span = not (
6477 parent_span_context .is_valid and not parent_span_context .is_remote
6578 )
6679 if is_root_span :
67- # Update the sample rate in the trace state
68- if sample_rate is not None :
69- if TRACESTATE_SAMPLE_RATE_KEY in trace_state :
70- trace_state = trace_state .update (
71- TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate )
72- )
73- else :
74- trace_state = trace_state .add (
75- TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate )
76- )
77-
7880 # Tell Sentry why we dropped the transaction/root-span
7981 client = sentry_sdk .get_client ()
8082 if client .monitor and client .monitor .downsample_factor > 0 :
@@ -96,19 +98,18 @@ def dropped_result(parent_span_context, attributes, sample_rate=None):
9698
9799
98100def sampled_result (span_context , attributes , sample_rate ):
99- # type: (SpanContext, Attributes, float) -> SamplingResult
101+ # type: (SpanContext, Attributes, Optional[ float] ) -> SamplingResult
100102 # these will only be added the first time in a root span sampling decision
103+ # if sample_rate is provided, it'll be updated in trace state
101104 trace_state = span_context .trace_state
102105
103106 if TRACESTATE_SAMPLED_KEY not in trace_state :
104107 trace_state = trace_state .add (TRACESTATE_SAMPLED_KEY , "true" )
105108 elif trace_state .get (TRACESTATE_SAMPLED_KEY ) == "deferred" :
106109 trace_state = trace_state .update (TRACESTATE_SAMPLED_KEY , "true" )
107110
108- if TRACESTATE_SAMPLE_RATE_KEY in trace_state :
109- trace_state = trace_state .update (TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate ))
110- else :
111- trace_state = trace_state .add (TRACESTATE_SAMPLE_RATE_KEY , str (sample_rate ))
111+ if sample_rate is not None :
112+ trace_state = _update_sample_rate (sample_rate , trace_state )
112113
113114 return SamplingResult (
114115 Decision .RECORD_AND_SAMPLE ,
@@ -152,9 +153,13 @@ def should_sample(
152153 if is_root_span :
153154 sample_rate = float (custom_sampled )
154155 if sample_rate > 0 :
155- return sampled_result (parent_span_context , attributes , sample_rate )
156+ return sampled_result (
157+ parent_span_context , attributes , sample_rate = sample_rate
158+ )
156159 else :
157- return dropped_result (parent_span_context , attributes , sample_rate )
160+ return dropped_result (
161+ parent_span_context , attributes , sample_rate = sample_rate
162+ )
158163 else :
159164 logger .debug (
160165 f"[Tracing] Ignoring sampled param for non-root span { name } "
@@ -163,6 +168,7 @@ def should_sample(
163168 # Check if there is a traces_sampler
164169 # Traces_sampler is responsible to check parent sampled to have full transactions.
165170 has_traces_sampler = callable (client .options .get ("traces_sampler" ))
171+ inherited_parent_sampled = False
166172
167173 if is_root_span and has_traces_sampler :
168174 sampling_context = create_sampling_context (
@@ -174,6 +180,7 @@ def should_sample(
174180 parent_sampled = get_parent_sampled (parent_span_context , trace_id )
175181 if parent_sampled is not None :
176182 sample_rate = parent_sampled
183+ inherited_parent_sampled = True
177184 else :
178185 # Check if there is a traces_sample_rate
179186 sample_rate = client .options .get ("traces_sample_rate" )
@@ -194,9 +201,17 @@ def should_sample(
194201 sampled = random .random () < sample_rate
195202
196203 if sampled :
197- return sampled_result (parent_span_context , attributes , sample_rate )
204+ return sampled_result (
205+ parent_span_context ,
206+ attributes ,
207+ sample_rate = sample_rate if not inherited_parent_sampled else None ,
208+ )
198209 else :
199- return dropped_result (parent_span_context , attributes , sample_rate )
210+ return dropped_result (
211+ parent_span_context ,
212+ attributes ,
213+ sample_rate = sample_rate if not inherited_parent_sampled else None ,
214+ )
200215
201216 def get_description (self ) -> str :
202217 return self .__class__ .__name__
0 commit comments