Skip to content

Commit 2fb3eba

Browse files
authored
Add AttributeKeyValue abstraction to common otlp exporters (#7026)
1 parent c8da020 commit 2fb3eba

File tree

5 files changed

+143
-0
lines changed

5 files changed

+143
-0
lines changed

exporters/otlp/common/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ val versions: Map<String, String> by project
1515
dependencies {
1616
protoSource("io.opentelemetry.proto:opentelemetry-proto:${versions["io.opentelemetry.proto"]}")
1717

18+
annotationProcessor("com.google.auto.value:auto-value")
19+
1820
api(project(":exporters:common"))
1921

2022
compileOnly(project(":sdk:metrics"))
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.otlp;
7+
8+
import io.opentelemetry.api.common.AttributeKey;
9+
import io.opentelemetry.api.common.Attributes;
10+
import io.opentelemetry.api.common.KeyValue;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
/**
15+
* Key-value pair of {@link AttributeKey} key and its corresponding value.
16+
*
17+
* <p>Conceptually if {@link Attributes} is a Map, then this is a Map.Entry. Note that whilst {@link
18+
* KeyValue} is similar, this class holds type information on the Key rather than the value.
19+
*
20+
* <p>NOTE: This class is only used in the profiling signal, and exists in this module and package
21+
* because its a common dependency of the modules that use it. Long term, it probably makes more
22+
* sense to live in {@code opentelemetry-sdk-profiles} once such a module exists.
23+
*
24+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
25+
* at any time.
26+
*/
27+
public interface AttributeKeyValue<T> {
28+
29+
/** Returns a {@link AttributeKeyValue} for the given {@link AttributeKey} and {@code value}. */
30+
static <T> AttributeKeyValue<T> of(AttributeKey<T> attributeKey, T value) {
31+
return AttributeKeyValueImpl.create(attributeKey, value);
32+
}
33+
34+
/** Returns a List corresponding to the provided Map. This is a copy, not a view. */
35+
@SuppressWarnings("unchecked")
36+
static <T> List<AttributeKeyValue<?>> of(Attributes attributes) {
37+
List<AttributeKeyValue<?>> result = new ArrayList<>(attributes.size());
38+
attributes.forEach(
39+
(key, value) -> {
40+
result.add(of((AttributeKey<T>) key, (T) value));
41+
});
42+
return result;
43+
}
44+
45+
/** Returns the key. */
46+
AttributeKey<T> getAttributeKey();
47+
48+
/** Returns the value. */
49+
T getValue();
50+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.otlp;
7+
8+
import com.google.auto.value.AutoValue;
9+
import io.opentelemetry.api.common.AttributeKey;
10+
11+
@AutoValue
12+
abstract class AttributeKeyValueImpl<T> implements AttributeKeyValue<T> {
13+
14+
AttributeKeyValueImpl() {}
15+
16+
static <T> AttributeKeyValueImpl<T> create(AttributeKey<T> attributeKey, T value) {
17+
return new AutoValue_AttributeKeyValueImpl<T>(attributeKey, value);
18+
}
19+
}

exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/KeyValueMarshaler.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.nio.charset.StandardCharsets;
1818
import java.util.List;
1919
import java.util.function.BiConsumer;
20+
import java.util.function.Consumer;
2021

2122
/**
2223
* A Marshaler of key value pairs.
@@ -65,6 +66,28 @@ public void accept(AttributeKey<?> attributeKey, Object o) {
6566
return marshalers;
6667
}
6768

69+
@SuppressWarnings("AvoidObjectArrays")
70+
public static KeyValueMarshaler[] createRepeated(List<AttributeKeyValue<?>> items) {
71+
if (items.isEmpty()) {
72+
return EMPTY_REPEATED;
73+
}
74+
75+
KeyValueMarshaler[] keyValueMarshalers = new KeyValueMarshaler[items.size()];
76+
items.forEach(
77+
item ->
78+
new Consumer<AttributeKeyValue<?>>() {
79+
int index = 0;
80+
81+
@Override
82+
public void accept(AttributeKeyValue<?> attributeKeyValue) {
83+
keyValueMarshalers[index++] =
84+
KeyValueMarshaler.create(
85+
attributeKeyValue.getAttributeKey(), attributeKeyValue.getValue());
86+
}
87+
});
88+
return keyValueMarshalers;
89+
}
90+
6891
@SuppressWarnings("unchecked")
6992
private static KeyValueMarshaler create(AttributeKey<?> attributeKey, Object value) {
7093
byte[] keyUtf8;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.otlp;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.api.common.AttributeKey;
11+
import io.opentelemetry.api.common.AttributeType;
12+
import io.opentelemetry.api.common.Attributes;
13+
import java.util.Collections;
14+
import java.util.List;
15+
import nl.jqno.equalsverifier.EqualsVerifier;
16+
import org.assertj.core.api.Assertions;
17+
import org.junit.jupiter.api.Test;
18+
19+
class AttributeKeyValueTest {
20+
21+
@Test
22+
void equalsVerifier() {
23+
EqualsVerifier.forClass(AttributeKeyValue.class).verify();
24+
}
25+
26+
@Test
27+
void ofEmpty() {
28+
assertThat(AttributeKeyValue.of(Attributes.empty())).isEmpty();
29+
}
30+
31+
@Test
32+
void ofOne() {
33+
AttributeKeyValue<String> input = AttributeKeyValue.of(AttributeKey.stringKey("foo"), "bar");
34+
Attributes attributes = Attributes.of(input.getAttributeKey(), input.getValue());
35+
List<AttributeKeyValue<?>> list = AttributeKeyValue.of(attributes);
36+
Assertions.assertThat(list).hasSize(1);
37+
assertThat(list.get(0)).isEqualTo(input);
38+
}
39+
40+
@Test
41+
void ofList() {
42+
AttributeKeyValue<List<Long>> input =
43+
AttributeKeyValue.of(AttributeKey.longArrayKey("foo"), Collections.emptyList());
44+
Attributes attributes = Attributes.of(input.getAttributeKey(), input.getValue());
45+
List<AttributeKeyValue<?>> list = AttributeKeyValue.of(attributes);
46+
Assertions.assertThat(list).hasSize(1);
47+
assertThat(list.get(0).getAttributeKey().getType()).isEqualTo(AttributeType.LONG_ARRAY);
48+
}
49+
}

0 commit comments

Comments
 (0)