Skip to content

Commit 64500a6

Browse files
tjquinnotvallin
authored andcommitted
Set incoming baggage from parent on Span (helidon-io#8303)
Signed-off-by: Tim Quinn <[email protected]>
1 parent aef657e commit 64500a6

File tree

4 files changed

+91
-6
lines changed

4 files changed

+91
-6
lines changed

tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpanBuilder.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 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.
@@ -20,13 +20,15 @@
2020
import io.helidon.tracing.Span;
2121
import io.helidon.tracing.SpanContext;
2222

23+
import io.opentelemetry.api.baggage.Baggage;
2324
import io.opentelemetry.api.trace.SpanBuilder;
2425
import io.opentelemetry.api.trace.SpanKind;
2526
import io.opentelemetry.context.Context;
2627

2728
class OpenTelemetrySpanBuilder implements Span.Builder<OpenTelemetrySpanBuilder> {
2829
private final SpanBuilder spanBuilder;
2930
private boolean parentSet;
31+
private Baggage parentBaggage;
3032

3133
OpenTelemetrySpanBuilder(SpanBuilder spanBuilder) {
3234
this.spanBuilder = spanBuilder;
@@ -41,6 +43,7 @@ public Span build() {
4143
public OpenTelemetrySpanBuilder parent(SpanContext spanContext) {
4244
this.parentSet = true;
4345
spanContext.asParent(this);
46+
parentBaggage = Baggage.fromContext(((OpenTelemetrySpanContext) spanContext).openTelemetry());
4447
return this;
4548
}
4649

@@ -87,7 +90,11 @@ public Span start(Instant instant) {
8790
}
8891
spanBuilder.setStartTimestamp(instant);
8992
io.opentelemetry.api.trace.Span span = spanBuilder.startSpan();
90-
return new OpenTelemetrySpan(span);
93+
Span result = new OpenTelemetrySpan(span);
94+
if (parentBaggage != null) {
95+
parentBaggage.forEach((key, baggageEntry) -> result.baggage(key, baggageEntry.getValue()));
96+
}
97+
return result;
9198
}
9299

93100
// used to set open telemetry context as parent, to be equivalent in function to
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tracing.providers.opentelemetry;
17+
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.Optional;
21+
22+
import io.helidon.tracing.HeaderProvider;
23+
24+
record MapHeaderProvider(Map<String, List<String>> values) implements HeaderProvider {
25+
26+
@Override
27+
public Iterable<String> keys() {
28+
return values.keySet();
29+
}
30+
31+
@Override
32+
public Optional<String> get(String key) {
33+
if (!values.containsKey(key)) {
34+
return Optional.empty();
35+
}
36+
List<String> matches = values.get(key);
37+
return matches.isEmpty() ? Optional.empty() : Optional.of(matches.get(0));
38+
}
39+
40+
@Override
41+
public Iterable<String> getAll(String key) {
42+
return values.get(key);
43+
}
44+
45+
@Override
46+
public boolean contains(String key) {
47+
return values.containsKey(key);
48+
}
49+
}

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

+17-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
*/
1616
package io.helidon.tracing.providers.opentelemetry;
1717

18+
import java.util.List;
19+
import java.util.Map;
1820
import java.util.Optional;
1921

2022
import io.helidon.common.testing.junit5.OptionalMatcher;
23+
import io.helidon.tracing.HeaderProvider;
2124
import io.helidon.tracing.Scope;
2225
import io.helidon.tracing.Span;
26+
import io.helidon.tracing.SpanContext;
2327
import io.helidon.tracing.Tracer;
2428

25-
import io.opentelemetry.context.Context;
2629
import org.junit.jupiter.api.AfterAll;
2730
import org.junit.jupiter.api.BeforeAll;
2831
import org.junit.jupiter.api.Test;
@@ -42,7 +45,7 @@ class TestSpanAndBaggage {
4245
@BeforeAll
4346
static void init() {
4447
originalOtelSdkAutoConfiguredSetting = System.setProperty(OTEL_AUTO_CONFIGURE_PROP, "true");
45-
originalOtelSdkDisabledSetting = System.setProperty(OTEL_SDK_DISABLED_PROP, "true");
48+
originalOtelSdkDisabledSetting = System.setProperty(OTEL_SDK_DISABLED_PROP, "false");
4649
}
4750

4851
@AfterAll
@@ -110,4 +113,16 @@ void testActiveSpanScopeWithBaggage() {
110113
currentSpanAfterTryResourcesBlock.get().context().spanId(),
111114
containsString("00000000"));
112115
}
116+
117+
@Test
118+
void testIncomingBaggage() {
119+
Tracer tracer = Tracer.global();
120+
HeaderProvider inboundHeaders = new MapHeaderProvider(Map.of("baggage", List.of("bag1=val1,bag2=val2")));
121+
Optional<SpanContext> spanContextOpt = tracer.extract(inboundHeaders);
122+
assertThat("Span context from inbound headers", spanContextOpt, OptionalMatcher.optionalPresent());
123+
Span span = tracer.spanBuilder("inbound").parent(spanContextOpt.get()).start();
124+
span.end();
125+
assertThat("Inbound baggage bag1", span.baggage("bag1"), OptionalMatcher.optionalValue(is("val1")));
126+
assertThat("Inbound baggage bag1", span.baggage("bag2"), OptionalMatcher.optionalValue(is("val2")));
127+
}
113128
}

tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpanBuilder.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 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.
@@ -16,6 +16,8 @@
1616
package io.helidon.tracing.providers.opentracing;
1717

1818
import java.time.Instant;
19+
import java.util.HashMap;
20+
import java.util.Map;
1921
import java.util.concurrent.TimeUnit;
2022

2123
import io.helidon.tracing.Span;
@@ -27,6 +29,7 @@
2729
class OpenTracingSpanBuilder implements Span.Builder<OpenTracingSpanBuilder> {
2830
private final Tracer.SpanBuilder delegate;
2931
private final Tracer tracer;
32+
private Map<String, String> baggage;
3033

3134
OpenTracingSpanBuilder(Tracer tracer, Tracer.SpanBuilder delegate) {
3235
this.tracer = tracer;
@@ -42,6 +45,13 @@ public Span build() {
4245
public OpenTracingSpanBuilder parent(SpanContext spanContext) {
4346
if (spanContext instanceof OpenTracingContext otc) {
4447
delegate.asChildOf(otc.openTracing());
48+
if (baggage == null) {
49+
baggage = new HashMap<>();
50+
} else {
51+
baggage.clear();
52+
}
53+
((OpenTracingContext) spanContext).openTracing().baggageItems().forEach(entry -> baggage.put(entry.getKey(),
54+
entry.getValue()));
4555
}
4656
return this;
4757
}
@@ -83,6 +93,10 @@ public OpenTracingSpanBuilder tag(String key, Number value) {
8393
@Override
8494
public Span start(Instant instant) {
8595
long micro = TimeUnit.MILLISECONDS.toMicros(instant.toEpochMilli());
86-
return new OpenTracingSpan(tracer, delegate.withStartTimestamp(micro).start());
96+
Span result = new OpenTracingSpan(tracer, delegate.withStartTimestamp(micro).start());
97+
if (baggage != null) {
98+
baggage.forEach(result::baggage);
99+
}
100+
return result;
87101
}
88102
}

0 commit comments

Comments
 (0)