diff --git a/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/main/java/datadog/trace/instrumentation/armeria/grpc/client/GrpcInjectAdapter.java b/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/main/java/datadog/trace/instrumentation/armeria/grpc/client/GrpcInjectAdapter.java index 72799867c90..931d729c6e1 100644 --- a/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/main/java/datadog/trace/instrumentation/armeria/grpc/client/GrpcInjectAdapter.java +++ b/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/main/java/datadog/trace/instrumentation/armeria/grpc/client/GrpcInjectAdapter.java @@ -11,6 +11,11 @@ public final class GrpcInjectAdapter implements CarrierSetter { @Override public void set(final Metadata carrier, final String key, final String value) { - carrier.put(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER), value); + Metadata.Key metadataKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER); + if (carrier.containsKey(metadataKey)) { + carrier.removeAll( + metadataKey); // Remove existing to ensure identical behavior with other carriers + } + carrier.put(metadataKey, value); } } diff --git a/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/test/groovy/GrpcInjectAdapterTest.groovy b/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/test/groovy/GrpcInjectAdapterTest.groovy new file mode 100644 index 00000000000..abb6ad7db8c --- /dev/null +++ b/dd-java-agent/instrumentation/armeria/armeria-grpc-0.84/src/test/groovy/GrpcInjectAdapterTest.groovy @@ -0,0 +1,47 @@ +import datadog.trace.agent.test.naming.VersionedNamingTestBase +import io.grpc.Metadata +import static datadog.trace.instrumentation.grpc.client.GrpcInjectAdapter.SETTER + +class GrpcInjectAdapterTest extends VersionedNamingTestBase { + def "carrier overrides values for duplicate keys"() { + setup: + def carrier = new Metadata() + + def baggage = [ + ["ot-baggage-foo", "v1"], + ["ot-baggage-foo", "v2"], + ["ot-baggage-bar", "v3"] + ] + + when: + baggage.each { pair -> + def (key, value) = pair + SETTER.set(carrier, key, value) + } + + then: + carrier.headerCount() == 2 + carrier.get(getKey("ot-baggage-foo")) == "v2" // overridden value wins + carrier.get(getKey("ot-baggage-bar")) == "v3" + } + + Metadata.Key getKey(String key){ + Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER) + } + + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return null + } +} diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/client/GrpcInjectAdapter.java b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/client/GrpcInjectAdapter.java index 392e5647398..a969dcb8771 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/client/GrpcInjectAdapter.java +++ b/dd-java-agent/instrumentation/grpc-1.5/src/main/java/datadog/trace/instrumentation/grpc/client/GrpcInjectAdapter.java @@ -10,6 +10,11 @@ public final class GrpcInjectAdapter implements CarrierSetter { @Override public void set(final Metadata carrier, final String key, final String value) { - carrier.put(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER), value); + Metadata.Key metadataKey = Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER); + if (carrier.containsKey(metadataKey)) { + carrier.removeAll( + metadataKey); // Remove existing to ensure identical behavior with other carriers + } + carrier.put(metadataKey, value); } } diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcInjectAdapterTest.groovy b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcInjectAdapterTest.groovy new file mode 100644 index 00000000000..abb6ad7db8c --- /dev/null +++ b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcInjectAdapterTest.groovy @@ -0,0 +1,47 @@ +import datadog.trace.agent.test.naming.VersionedNamingTestBase +import io.grpc.Metadata +import static datadog.trace.instrumentation.grpc.client.GrpcInjectAdapter.SETTER + +class GrpcInjectAdapterTest extends VersionedNamingTestBase { + def "carrier overrides values for duplicate keys"() { + setup: + def carrier = new Metadata() + + def baggage = [ + ["ot-baggage-foo", "v1"], + ["ot-baggage-foo", "v2"], + ["ot-baggage-bar", "v3"] + ] + + when: + baggage.each { pair -> + def (key, value) = pair + SETTER.set(carrier, key, value) + } + + then: + carrier.headerCount() == 2 + carrier.get(getKey("ot-baggage-foo")) == "v2" // overridden value wins + carrier.get(getKey("ot-baggage-bar")) == "v3" + } + + Metadata.Key getKey(String key){ + Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER) + } + + + @Override + int version() { + return 0 + } + + @Override + String service() { + return null + } + + @Override + String operation() { + return null + } +}