diff --git a/CHANGELOG.md b/CHANGELOG.md index 386c20ba941..7b17371f854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ * Logging: Output event name in `SystemOutLogRecordExporter` ([#8609](https://github.com/open-telemetry/opentelemetry-java/pull/8609)) +### Shims + +* OpenTracing: Return the extracted `SpanContext` when it is sampled but invalid + ([#8634](https://github.com/open-telemetry/opentelemetry-java/pull/8634)) + ## Version 1.64.0 (2026-07-10) ### API diff --git a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java index 04f0407b4a8..e67bf4fa73d 100644 --- a/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java +++ b/opentracing-shim/src/main/java/io/opentelemetry/opentracingshim/Propagation.java @@ -46,7 +46,9 @@ SpanContextShim extractTextMap(Format format, TextMapExtract carrier) { Span span = Span.fromContext(context); Baggage baggage = Baggage.fromContext(context); - if (!span.getSpanContext().isValid() && baggage.isEmpty()) { + if (!span.getSpanContext().isValid() + && !span.getSpanContext().isSampled() + && baggage.isEmpty()) { return null; } diff --git a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java index f539e5e3bfa..199b6209e26 100644 --- a/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java +++ b/opentracing-shim/src/test/java/io/opentelemetry/opentracingshim/TracerShimTest.java @@ -14,9 +14,15 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.baggage.Baggage; import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.SpanId; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceId; +import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapPropagator; +import io.opentelemetry.context.propagation.TextMapSetter; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; @@ -32,9 +38,11 @@ import io.opentracing.tag.StringTag; import io.opentracing.tag.Tag; import io.opentracing.tag.Tags; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import javax.annotation.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -350,6 +358,21 @@ void extract_onlyBaggage() { assertThat(spanContextShim.getBaggage()).isEqualTo(baggage); } + @Test + void extract_invalidButSampledSpanContext() { + tracerShim = + new TracerShim(provider, new InvalidButSampledPropagator(), TextMapPropagator.noop()); + + SpanContext spanContext = + tracerShim.extract(Format.Builtin.TEXT_MAP, new TextMapAdapter(new HashMap<>())); + + assertThat(spanContext).isNotNull(); + SpanContextShim spanContextShim = (SpanContextShim) spanContext; + assertThat(spanContextShim.getSpanContext().isValid()).isFalse(); + assertThat(spanContextShim.getSpanContext().isSampled()).isTrue(); + assertThat(spanContextShim.getBaggage().isEmpty()).isTrue(); + } + @Test void extract_emptyCarrier_withActiveSpan_returnsNull() { Span span = tracerShim.buildSpan("one").start(); @@ -467,4 +490,26 @@ void noopDoesNotCrash() { assertThat(((SpanShim) span).getSpan().isRecording()).isFalse(); } + + /** Extracts an invalid but sampled {@code SpanContext}, as {@code jaeger-debug-id} headers do. */ + private static class InvalidButSampledPropagator implements TextMapPropagator { + @Override + public Collection fields() { + return Collections.emptyList(); + } + + @Override + public void inject(Context context, @Nullable C carrier, TextMapSetter setter) {} + + @Override + public Context extract(Context context, @Nullable C carrier, TextMapGetter getter) { + return context.with( + io.opentelemetry.api.trace.Span.wrap( + io.opentelemetry.api.trace.SpanContext.create( + TraceId.getInvalid(), + SpanId.getInvalid(), + TraceFlags.getSampled(), + TraceState.getDefault()))); + } + } }