Skip to content

Commit efa3210

Browse files
authored
Support propagating OTel API created baggage via outgoing W3C headers (#9987)
1 parent 532ee38 commit efa3210

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/baggage/OtelBaggageBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ public BaggageBuilder remove(@Nullable String key) {
3535

3636
@Override
3737
public Baggage build() {
38-
return new OtelBaggage(items);
38+
return new OtelBaggage(new HashMap<>(items));
3939
}
4040
}

dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/OtelContext.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ public <V> Context with(ContextKey<V> key, V value) {
8080
if (value instanceof OtelBaggage) {
8181
Baggage baggage = ((OtelBaggage) value).asAgentBaggage();
8282
return new OtelContext(delegate.with(baggage));
83+
} else if (value instanceof io.opentelemetry.api.baggage.Baggage) {
84+
Baggage baggage = Baggage.empty();
85+
// transfer baggage to our internal container for propagation purposes
86+
((io.opentelemetry.api.baggage.Baggage) value)
87+
.forEach((k, b) -> baggage.addItem(k, b.getValue()));
88+
return new OtelContext(delegate.with(baggage));
8389
}
8490
// fall-through and store as non-datadog baggage
8591
}

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,43 +338,90 @@ class ContextTest extends InstrumentationSpecification {
338338
otelBaggageFromContext.isEmpty()
339339
otelBaggageFromContextOrNull == null
340340

341+
when:
342+
def otelScope = Baggage.builder()
343+
.put("foo", "otel_value_to_be_replaced")
344+
.put("FOO","OTEL_UNTOUCHED")
345+
.put("remove_me_key", "otel_remove_me_value")
346+
.build()
347+
.makeCurrent()
348+
otelBaggage = Baggage.current()
349+
otelBaggageFromContext = Baggage.fromContext(Context.current())
350+
otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current())
351+
352+
then: "OTel baggage must be current"
353+
otelBaggage != null
354+
otelBaggage.size() == 3
355+
otelBaggage.getEntryValue("foo") == "otel_value_to_be_replaced"
356+
otelBaggage.getEntryValue("FOO") == "OTEL_UNTOUCHED"
357+
otelBaggage.getEntryValue("remove_me_key") == "otel_remove_me_value"
358+
otelBaggage.asMap() == otelBaggageFromContext.asMap()
359+
otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap()
360+
341361
when:
342362
def ddContext = datadog.context.Context.current()
343-
def ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.create([
344-
"foo" : "value_to_be_replaced",
345-
"FOO" : "UNTOUCHED",
346-
"remove_me_key" : "remove_me_value"
347-
])
363+
def ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.fromContext(ddContext)
364+
ddBaggage.addItem("new_foo", "dd_new_value")
365+
ddBaggage.addItem("foo", "dd_overwrite_value")
366+
ddBaggage.removeItem("remove_me_key")
348367
def ddScope = ddContext.with(ddBaggage).attach()
349368
otelBaggage = Baggage.current()
350369
otelBaggageFromContext = Baggage.fromContext(Context.current())
351370
otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current())
352371

372+
then: "baggage must contain Datadog changes"
373+
otelBaggage != null
374+
otelBaggage.size() == 3
375+
otelBaggage.getEntryValue("foo") == "dd_overwrite_value"
376+
otelBaggage.getEntryValue("FOO") == "OTEL_UNTOUCHED"
377+
otelBaggage.getEntryValue("new_foo") == "dd_new_value"
378+
otelBaggage.asMap() == otelBaggageFromContext.asMap()
379+
otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap()
380+
381+
when:
382+
ddScope.close()
383+
otelScope.close()
384+
385+
then: "current baggage must be empty or null"
386+
Baggage.current().isEmpty()
387+
388+
when:
389+
ddContext = datadog.context.Context.current()
390+
ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.create([
391+
"foo" : "dd_value_to_be_replaced",
392+
"FOO" : "DD_UNTOUCHED",
393+
"remove_me_key" : "dd_remove_me_value"
394+
])
395+
ddScope = ddContext.with(ddBaggage).attach()
396+
otelBaggage = Baggage.current()
397+
otelBaggageFromContext = Baggage.fromContext(Context.current())
398+
otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current())
399+
353400
then: "Datadog baggage must be current"
354401
otelBaggage != null
355402
otelBaggage.size() == 3
356-
otelBaggage.getEntryValue("foo") == "value_to_be_replaced"
357-
otelBaggage.getEntryValue("FOO") == "UNTOUCHED"
358-
otelBaggage.getEntryValue("remove_me_key") == "remove_me_value"
403+
otelBaggage.getEntryValue("foo") == "dd_value_to_be_replaced"
404+
otelBaggage.getEntryValue("FOO") == "DD_UNTOUCHED"
405+
otelBaggage.getEntryValue("remove_me_key") == "dd_remove_me_value"
359406
otelBaggage.asMap() == otelBaggageFromContext.asMap()
360407
otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap()
361408

362409
when:
363410
def builder = otelBaggage.toBuilder()
364-
builder.put("new_foo", "new_value")
365-
builder.put("foo", "overwrite_value")
411+
builder.put("new_foo", "otel_new_value")
412+
builder.put("foo", "otel_overwrite_value")
366413
builder.remove("remove_me_key")
367-
def otelScope = builder.build().makeCurrent()
414+
otelScope = builder.build().makeCurrent()
368415
otelBaggage = Baggage.current()
369416
otelBaggageFromContext = Baggage.fromContext(Context.current())
370417
otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current())
371418

372419
then: "baggage must contain OTel changes"
373420
otelBaggage != null
374421
otelBaggage.size() == 3
375-
otelBaggage.getEntryValue("foo") == "overwrite_value"
376-
otelBaggage.getEntryValue("FOO") == "UNTOUCHED"
377-
otelBaggage.getEntryValue("new_foo") == "new_value"
422+
otelBaggage.getEntryValue("foo") == "otel_overwrite_value"
423+
otelBaggage.getEntryValue("FOO") == "DD_UNTOUCHED"
424+
otelBaggage.getEntryValue("new_foo") == "otel_new_value"
378425
otelBaggage.asMap() == otelBaggageFromContext.asMap()
379426
otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap()
380427

0 commit comments

Comments
 (0)