diff --git a/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/AttributesMap.java b/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/AttributesMap.java index 0ddf9599752..729c2921d6f 100644 --- a/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/AttributesMap.java +++ b/sdk/common/src/main/java/io/opentelemetry/sdk/common/internal/AttributesMap.java @@ -63,12 +63,29 @@ public Object put(AttributeKey key, @Nullable Object value) { return null; } totalAddedValues++; + AttributeKey existingKey = null; + for (AttributeKey k : keySet()) { + if (k.getKey().equals(key.getKey())) { + existingKey = k; + break; + } + } + if (existingKey != null && !existingKey.equals(key)) { + super.remove(existingKey); + } if (size() >= capacity && !containsKey(key)) { return null; } return super.put(key, AttributeUtil.applyAttributeLengthLimit(value, lengthLimit)); } + @Override + public void putAll(Map, ?> m) { + for (Map.Entry, ?> entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + /** Generic overload of {@link #put(AttributeKey, Object)}. */ public void putIfCapacity(AttributeKey key, @Nullable T value) { put(key, value); diff --git a/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/AttributesMapTest.java b/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/AttributesMapTest.java index a7a1f8ecb2e..5ae6afd7167 100644 --- a/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/AttributesMapTest.java +++ b/sdk/common/src/test/java/io/opentelemetry/sdk/common/internal/AttributesMapTest.java @@ -5,10 +5,15 @@ package io.opentelemetry.sdk.common.internal; +import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.api.common.AttributeKey.longKey; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import io.opentelemetry.api.common.AttributeKey; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.Test; class AttributesMapTest { @@ -22,4 +27,34 @@ void asMap() { assertThat(attributesMap.asMap()) .containsOnly(entry(longKey("one"), 1L), entry(longKey("two"), 2L)); } + + @Test + void put_lastValueWins_differentTypes() { + AttributesMap attributesMap = AttributesMap.create(10, Integer.MAX_VALUE); + attributesMap.put(stringKey("key"), "value"); + attributesMap.put(booleanKey("key"), false); + + assertThat(attributesMap.asMap()).containsOnly(entry(booleanKey("key"), false)); + } + + @Test + void put_lastValueWins_sameType() { + AttributesMap attributesMap = AttributesMap.create(10, Integer.MAX_VALUE); + attributesMap.put(stringKey("key"), "value1"); + attributesMap.put(stringKey("key"), "value2"); + + assertThat(attributesMap.asMap()).containsOnly(entry(stringKey("key"), "value2")); + } + + @Test + void putAll() { + AttributesMap attributesMap = AttributesMap.create(10, Integer.MAX_VALUE); + Map, Object> newAttrs = new HashMap<>(); + newAttrs.put(stringKey("key1"), "value1"); + newAttrs.put(booleanKey("key2"), true); + attributesMap.putAll(newAttrs); + + assertThat(attributesMap.asMap()) + .containsOnly(entry(stringKey("key1"), "value1"), entry(booleanKey("key2"), true)); + } }