From 98993c9258fbdffe75e2bec76c10681c0bd38f28 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 7 Aug 2026 17:25:26 -0500 Subject: [PATCH] Jaeger propagator: inject only SAMPLED flag, never force DEBUG The Jaeger propagator forced the DEBUG (forced-keep) flag on inject for every sampled span, overriding downstream sampling decisions. Propagate only the SAMPLED bit instead. --- .changelog/33.fixed | 1 + .../src/opentelemetry/propagators/jaeger/__init__.py | 7 ++++--- .../tests/test_jaeger_propagator.py | 9 ++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changelog/33.fixed diff --git a/.changelog/33.fixed b/.changelog/33.fixed new file mode 100644 index 0000000000..d08c98d26b --- /dev/null +++ b/.changelog/33.fixed @@ -0,0 +1 @@ +Jaeger propagator no longer forces the DEBUG flag on inject; a normally-sampled span now propagates only the SAMPLED flag diff --git a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py index e71cc7cfeb..6efcd8a9ec 100644 --- a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py +++ b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py @@ -68,9 +68,10 @@ def inject( # Non-recording spans do not have a parent span_parent_id = span.parent.span_id if span.is_recording() and span.parent else 0 - trace_flags = span_context.trace_flags - if trace_flags.sampled: - trace_flags |= self.DEBUG_FLAG + # Only propagate the SAMPLED flag. The DEBUG flag must not be set on + # inject for a normally-sampled span, since that would force downstream + # Jaeger components into a forced-keep decision. + trace_flags = trace.TraceFlags(span_context.trace_flags & trace.TraceFlags.SAMPLED) # set span identity setter.set( diff --git a/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py b/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py index 60b010490c..25966aa0b5 100644 --- a/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py +++ b/propagator/opentelemetry-propagator-jaeger/tests/test_jaeger_propagator.py @@ -91,11 +91,14 @@ def test_sampled_flag_set(self): sample_flag_value = int(new_carrier[FORMAT.TRACE_ID_KEY].split(":")[3]) & 0x01 self.assertEqual(1, sample_flag_value) - def test_debug_flag_set(self): + def test_debug_flag_not_set_for_sampled_span(self): + # Injecting a normally-sampled span must set only the SAMPLED bit and + # must never force the Jaeger DEBUG (forced-keep) flag. old_carrier = {FORMAT.TRACE_ID_KEY: self.serialized_uber_trace_id} _, new_carrier = get_context_new_carrier(old_carrier) - debug_flag_value = int(new_carrier[FORMAT.TRACE_ID_KEY].split(":")[3]) & FORMAT.DEBUG_FLAG - self.assertEqual(FORMAT.DEBUG_FLAG, debug_flag_value) + flags = int(new_carrier[FORMAT.TRACE_ID_KEY].split(":")[3]) + self.assertEqual(1, flags & 0x01) + self.assertEqual(0, flags & FORMAT.DEBUG_FLAG) def test_sample_debug_flags_unset(self): uber_trace_id = jaeger._format_uber_trace_id( # pylint: disable=protected-access