Skip to content

Commit 7b33dd6

Browse files
authored
Fix ParentBased sampler for implicit parent spans (open-telemetry#1394)
consider the sample decision of implicit parent spans (when creating a span without explicitly providing a context) instead of forwarding to the delegating sampler. * fix trace_state erasure for dropped spans * samplers did not return the trace_state in the sampling result when a span was dropped. This caused the trace_state extracted from a remote parent span to be erased and further context propagation to break. * fix also TraceIdRatioBased which erased the trace_state independent of the sampling outcome.
1 parent 2425d66 commit 7b33dd6

File tree

3 files changed

+231
-187
lines changed

3 files changed

+231
-187
lines changed

opentelemetry-sdk/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
([#1373](https://github.com/open-telemetry/opentelemetry-python/pull/1373))
1515
- Rename Meter class to Accumulator in Metrics SDK
1616
([#1372](https://github.com/open-telemetry/opentelemetry-python/pull/1372))
17-
- Rename Meter class to Accumulator in Metrics SDK
18-
([#1372](https://github.com/open-telemetry/opentelemetry-python/pull/1372))
17+
- Fix `ParentBased` sampler for implicit parent spans. Fix also `trace_state`
18+
erasure for dropped spans or spans sampled by the `TraceIdRatioBased` sampler.
19+
([#1394](https://github.com/open-telemetry/opentelemetry-python/pull/1394))
1920

2021
## Version 0.15b0
2122

opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def should_sample(
151151
trace_state: "TraceState" = None,
152152
) -> "SamplingResult":
153153
if self._decision is Decision.DROP:
154-
return SamplingResult(self._decision)
154+
attributes = None
155155
return SamplingResult(self._decision, attributes, trace_state)
156156

157157
def get_description(self) -> str:
@@ -209,8 +209,8 @@ def should_sample(
209209
if trace_id & self.TRACE_ID_LIMIT < self.bound:
210210
decision = Decision.RECORD_AND_SAMPLE
211211
if decision is Decision.DROP:
212-
return SamplingResult(decision)
213-
return SamplingResult(decision, attributes)
212+
attributes = None
213+
return SamplingResult(decision, attributes, trace_state)
214214

215215
def get_description(self) -> str:
216216
return "TraceIdRatioBased{{{}}}".format(self._rate)
@@ -238,18 +238,16 @@ def should_sample(
238238
links: Sequence["Link"] = None,
239239
trace_state: "TraceState" = None,
240240
) -> "SamplingResult":
241-
if parent_context is not None:
242-
parent_span_context = get_current_span(
243-
parent_context
244-
).get_span_context()
245-
# only drop if parent exists and is not a root span
246-
if (
247-
parent_span_context is not None
248-
and parent_span_context.is_valid
249-
and not parent_span_context.trace_flags.sampled
250-
):
251-
return SamplingResult(Decision.DROP)
252-
return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes)
241+
parent_span_context = get_current_span(
242+
parent_context
243+
).get_span_context()
244+
# respect the sampling flag of the parent if present
245+
if parent_span_context is not None and parent_span_context.is_valid:
246+
decision = Decision.RECORD_AND_SAMPLE
247+
if not parent_span_context.trace_flags.sampled:
248+
decision = Decision.DROP
249+
attributes = None
250+
return SamplingResult(decision, attributes, trace_state)
253251

254252
return self._delegate.should_sample(
255253
parent_context=parent_context,

0 commit comments

Comments
 (0)