Skip to content

Commit 527d002

Browse files
committed
Fix OTel extract when there is no current context
Signed-off-by: Tim Quinn <tim.quinn@oracle.com>
1 parent fae450c commit 527d002

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

tracing/opentelemetry/src/main/java/io/helidon/tracing/opentelemetry/OpenTelemetryTracer.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -70,8 +70,10 @@ public Span.Builder<?> spanBuilder(String name) {
7070
public Optional<SpanContext> extract(HeaderProvider headersProvider) {
7171
Context context = propagator.extract(Context.current(), headersProvider, GETTER);
7272

73-
return Optional.ofNullable(context)
74-
.map(OpenTelemetrySpanContext::new);
73+
// OTel Span.current() returns a no-op span if there is no current one. Use fromContextOrNull instead to distinguish.
74+
io.opentelemetry.api.trace.Span otelSpan = io.opentelemetry.api.trace.Span.fromContextOrNull(context);
75+
return Optional.ofNullable(otelSpan)
76+
.map(span -> new OpenTelemetrySpanContext(context));
7577
}
7678

7779
@Override

tracing/opentelemetry/src/test/java/io/helidon/tracing/opentelemetry/TestSpanAndBaggage.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ void testActiveSpanScopeWithBaggage() {
124124
@Test
125125
void testIncomingBaggage() {
126126
Tracer tracer = Tracer.global();
127-
HeaderProvider inboundHeaders = new MapHeaderProvider(Map.of("baggage", List.of("bag1=val1,bag2=val2")));
127+
// Need to supply both the traceparent and the baggage for OTel to construct a proper span context.
128+
HeaderProvider inboundHeaders = new MapHeaderProvider(
129+
Map.of("traceparent", List.of("00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01"),
130+
"baggage", List.of("bag1=val1,bag2=val2")));
128131
Optional<SpanContext> spanContextOpt = tracer.extract(inboundHeaders);
129132
assertThat("Span context from inbound headers", spanContextOpt, OptionalMatcher.optionalPresent());
130133
Span span = tracer.spanBuilder("inbound").parent(spanContextOpt.get()).start();
@@ -172,7 +175,7 @@ void testBaggageAddedAfterActivation() {
172175
final String BAGGAGE_KEY = "mykey";
173176
final String BAGGAGE_VALUE = "myvalue";
174177
final var tracer = io.helidon.tracing.Tracer.global();
175-
final var span = tracer.spanBuilder("baggageCanaryMinimal").start();
178+
final var span = tracer.spanBuilder("baggageMinimal").start();
176179
try {
177180
// Set baggage and confirm that it's known in the span
178181
try (Scope scope = span.activate()) {
@@ -186,6 +189,19 @@ void testBaggageAddedAfterActivation() {
186189
}
187190
}
188191

192+
@Test
193+
void testExtractWithNoCurrentSpan() {
194+
final String BAGGAGE_KEY = "mykey";
195+
final String BAGGAGE_VALUE = "myvalue";
196+
final var tracer = io.helidon.tracing.Tracer.global();
197+
198+
HeaderProvider headers = HeaderProvider.create(Map.of("not-a-trace", List.of("1234567890123456"),
199+
"not-a-span", List.of("6543210987654321")));
200+
Optional<SpanContext> spanContext = tracer.extract(headers);
201+
202+
assertThat("Current span reported", spanContext, OptionalMatcher.optionalEmpty());
203+
}
204+
189205
private void checkBaggage(Tracer tracer, Span span, Supplier<SpanContext> spanContextSupplier) {
190206
String value = span.baggage(BAGGAGE_KEY).orElseThrow();
191207
assertThat("baggage value right after set", value, Matchers.is(Matchers.equalTo(BAGGAGE_VALUE)));

0 commit comments

Comments
 (0)