diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/baggage/OtelBaggageBuilder.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/baggage/OtelBaggageBuilder.java index 430f7be3b01..bc456d7f8f1 100644 --- a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/baggage/OtelBaggageBuilder.java +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/baggage/OtelBaggageBuilder.java @@ -35,6 +35,6 @@ public BaggageBuilder remove(@Nullable String key) { @Override public Baggage build() { - return new OtelBaggage(items); + return new OtelBaggage(new HashMap<>(items)); } } diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/OtelContext.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/OtelContext.java index 19e124db4f5..ba4199b0c51 100644 --- a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/OtelContext.java +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/context/OtelContext.java @@ -80,6 +80,12 @@ public Context with(ContextKey key, V value) { if (value instanceof OtelBaggage) { Baggage baggage = ((OtelBaggage) value).asAgentBaggage(); return new OtelContext(delegate.with(baggage)); + } else if (value instanceof io.opentelemetry.api.baggage.Baggage) { + Baggage baggage = Baggage.empty(); + // transfer baggage to our internal container for propagation purposes + ((io.opentelemetry.api.baggage.Baggage) value) + .forEach((k, b) -> baggage.addItem(k, b.getValue())); + return new OtelContext(delegate.with(baggage)); } // fall-through and store as non-datadog baggage } diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy index 5cfa8de0c81..0691d20c921 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy @@ -338,33 +338,80 @@ class ContextTest extends InstrumentationSpecification { otelBaggageFromContext.isEmpty() otelBaggageFromContextOrNull == null + when: + def otelScope = Baggage.builder() + .put("foo", "otel_value_to_be_replaced") + .put("FOO","OTEL_UNTOUCHED") + .put("remove_me_key", "otel_remove_me_value") + .build() + .makeCurrent() + otelBaggage = Baggage.current() + otelBaggageFromContext = Baggage.fromContext(Context.current()) + otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current()) + + then: "OTel baggage must be current" + otelBaggage != null + otelBaggage.size() == 3 + otelBaggage.getEntryValue("foo") == "otel_value_to_be_replaced" + otelBaggage.getEntryValue("FOO") == "OTEL_UNTOUCHED" + otelBaggage.getEntryValue("remove_me_key") == "otel_remove_me_value" + otelBaggage.asMap() == otelBaggageFromContext.asMap() + otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap() + when: def ddContext = datadog.context.Context.current() - def ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.create([ - "foo" : "value_to_be_replaced", - "FOO" : "UNTOUCHED", - "remove_me_key" : "remove_me_value" - ]) + def ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.fromContext(ddContext) + ddBaggage.addItem("new_foo", "dd_new_value") + ddBaggage.addItem("foo", "dd_overwrite_value") + ddBaggage.removeItem("remove_me_key") def ddScope = ddContext.with(ddBaggage).attach() otelBaggage = Baggage.current() otelBaggageFromContext = Baggage.fromContext(Context.current()) otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current()) + then: "baggage must contain Datadog changes" + otelBaggage != null + otelBaggage.size() == 3 + otelBaggage.getEntryValue("foo") == "dd_overwrite_value" + otelBaggage.getEntryValue("FOO") == "OTEL_UNTOUCHED" + otelBaggage.getEntryValue("new_foo") == "dd_new_value" + otelBaggage.asMap() == otelBaggageFromContext.asMap() + otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap() + + when: + ddScope.close() + otelScope.close() + + then: "current baggage must be empty or null" + Baggage.current().isEmpty() + + when: + ddContext = datadog.context.Context.current() + ddBaggage = datadog.trace.bootstrap.instrumentation.api.Baggage.create([ + "foo" : "dd_value_to_be_replaced", + "FOO" : "DD_UNTOUCHED", + "remove_me_key" : "dd_remove_me_value" + ]) + ddScope = ddContext.with(ddBaggage).attach() + otelBaggage = Baggage.current() + otelBaggageFromContext = Baggage.fromContext(Context.current()) + otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current()) + then: "Datadog baggage must be current" otelBaggage != null otelBaggage.size() == 3 - otelBaggage.getEntryValue("foo") == "value_to_be_replaced" - otelBaggage.getEntryValue("FOO") == "UNTOUCHED" - otelBaggage.getEntryValue("remove_me_key") == "remove_me_value" + otelBaggage.getEntryValue("foo") == "dd_value_to_be_replaced" + otelBaggage.getEntryValue("FOO") == "DD_UNTOUCHED" + otelBaggage.getEntryValue("remove_me_key") == "dd_remove_me_value" otelBaggage.asMap() == otelBaggageFromContext.asMap() otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap() when: def builder = otelBaggage.toBuilder() - builder.put("new_foo", "new_value") - builder.put("foo", "overwrite_value") + builder.put("new_foo", "otel_new_value") + builder.put("foo", "otel_overwrite_value") builder.remove("remove_me_key") - def otelScope = builder.build().makeCurrent() + otelScope = builder.build().makeCurrent() otelBaggage = Baggage.current() otelBaggageFromContext = Baggage.fromContext(Context.current()) otelBaggageFromContextOrNull = Baggage.fromContextOrNull(Context.current()) @@ -372,9 +419,9 @@ class ContextTest extends InstrumentationSpecification { then: "baggage must contain OTel changes" otelBaggage != null otelBaggage.size() == 3 - otelBaggage.getEntryValue("foo") == "overwrite_value" - otelBaggage.getEntryValue("FOO") == "UNTOUCHED" - otelBaggage.getEntryValue("new_foo") == "new_value" + otelBaggage.getEntryValue("foo") == "otel_overwrite_value" + otelBaggage.getEntryValue("FOO") == "DD_UNTOUCHED" + otelBaggage.getEntryValue("new_foo") == "otel_new_value" otelBaggage.asMap() == otelBaggageFromContext.asMap() otelBaggage.asMap() == otelBaggageFromContextOrNull.asMap()