Skip to content

Commit cbdcc32

Browse files
committed
More implementation
1 parent 77c3d90 commit cbdcc32

File tree

9 files changed

+445
-16
lines changed

9 files changed

+445
-16
lines changed

api/all/src/main/java/io/opentelemetry/api/common/ArrayBackedAttributes.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.opentelemetry.api.internal.ImmutableKeyValuePairs;
99
import java.util.ArrayList;
1010
import java.util.Comparator;
11+
import java.util.List;
1112
import javax.annotation.Nullable;
1213
import javax.annotation.concurrent.Immutable;
1314

@@ -45,9 +46,74 @@ public AttributesBuilder toBuilder() {
4546
@Override
4647
@Nullable
4748
public <T> T get(AttributeKey<T> key) {
49+
if (key != null && key.getType() == AttributeType.VALUE) {
50+
return (T) getAsValue(key.getKey());
51+
}
4852
return (T) super.get(key);
4953
}
5054

55+
@Nullable
56+
private Value<?> getAsValue(String keyName) {
57+
// Find any attribute with the same key name and convert it to Value
58+
List<Object> data = data();
59+
for (int i = 0; i < data.size(); i += 2) {
60+
AttributeKey<?> currentKey = (AttributeKey<?>) data.get(i);
61+
if (currentKey.getKey().equals(keyName)) {
62+
Object value = data.get(i + 1);
63+
return asValue(currentKey.getType(), value);
64+
}
65+
}
66+
return null;
67+
}
68+
69+
@SuppressWarnings("unchecked")
70+
@Nullable
71+
private static Value<?> asValue(AttributeType type, Object value) {
72+
switch (type) {
73+
case STRING:
74+
return Value.of((String) value);
75+
case LONG:
76+
return Value.of((Long) value);
77+
case DOUBLE:
78+
return Value.of((Double) value);
79+
case BOOLEAN:
80+
return Value.of((Boolean) value);
81+
case STRING_ARRAY:
82+
List<String> stringList = (List<String>) value;
83+
Value<?>[] stringValues = new Value<?>[stringList.size()];
84+
for (int i = 0; i < stringList.size(); i++) {
85+
stringValues[i] = Value.of(stringList.get(i));
86+
}
87+
return Value.of(stringValues);
88+
case LONG_ARRAY:
89+
List<Long> longList = (List<Long>) value;
90+
Value<?>[] longValues = new Value<?>[longList.size()];
91+
for (int i = 0; i < longList.size(); i++) {
92+
longValues[i] = Value.of(longList.get(i));
93+
}
94+
return Value.of(longValues);
95+
case DOUBLE_ARRAY:
96+
List<Double> doubleList = (List<Double>) value;
97+
Value<?>[] doubleValues = new Value<?>[doubleList.size()];
98+
for (int i = 0; i < doubleList.size(); i++) {
99+
doubleValues[i] = Value.of(doubleList.get(i));
100+
}
101+
return Value.of(doubleValues);
102+
case BOOLEAN_ARRAY:
103+
List<Boolean> booleanList = (List<Boolean>) value;
104+
Value<?>[] booleanValues = new Value<?>[booleanList.size()];
105+
for (int i = 0; i < booleanList.size(); i++) {
106+
booleanValues[i] = Value.of(booleanList.get(i));
107+
}
108+
return Value.of(booleanValues);
109+
case VALUE:
110+
// Already a Value
111+
return (Value<?>) value;
112+
}
113+
// Should not reach here
114+
return null;
115+
}
116+
51117
static Attributes sortAndFilterToAttributes(Object... data) {
52118
// null out any empty keys or keys with null values
53119
// so they will then be removed by the sortAndFilter method.

api/all/src/main/java/io/opentelemetry/api/common/ArrayBackedAttributesBuilder.java

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@
55

66
package io.opentelemetry.api.common;
77

8+
import static io.opentelemetry.api.common.AttributeKey.booleanArrayKey;
9+
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
10+
import static io.opentelemetry.api.common.AttributeKey.doubleArrayKey;
11+
import static io.opentelemetry.api.common.AttributeKey.doubleKey;
12+
import static io.opentelemetry.api.common.AttributeKey.longArrayKey;
13+
import static io.opentelemetry.api.common.AttributeKey.longKey;
14+
import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
15+
import static io.opentelemetry.api.common.AttributeKey.stringKey;
16+
817
import java.util.ArrayList;
918
import java.util.Arrays;
1019
import java.util.List;
@@ -38,15 +47,127 @@ public <T> AttributesBuilder put(AttributeKey<Long> key, int value) {
3847
}
3948

4049
@Override
50+
@SuppressWarnings("unchecked")
4151
public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) {
4252
if (key == null || key.getKey().isEmpty() || value == null) {
4353
return this;
4454
}
55+
if (key.getType() == AttributeType.VALUE && value instanceof Value) {
56+
putValue(key, (Value<?>) value);
57+
return this;
58+
}
4559
data.add(key);
4660
data.add(value);
4761
return this;
4862
}
4963

64+
private void putValue(AttributeKey<?> key, Value<?> valueObj) {
65+
// Convert VALUE type to narrower type when possible
66+
String keyName = key.getKey();
67+
switch (valueObj.getType()) {
68+
case STRING:
69+
data.add(stringKey(keyName));
70+
data.add(valueObj.getValue());
71+
return;
72+
case LONG:
73+
data.add(longKey(keyName));
74+
data.add(valueObj.getValue());
75+
return;
76+
case DOUBLE:
77+
data.add(doubleKey(keyName));
78+
data.add(valueObj.getValue());
79+
return;
80+
case BOOLEAN:
81+
data.add(booleanKey(keyName));
82+
data.add(valueObj.getValue());
83+
return;
84+
case ARRAY:
85+
@SuppressWarnings("unchecked")
86+
List<Value<?>> arrayValues = (List<Value<?>>) valueObj.getValue();
87+
AttributeType attributeType = attributeType(arrayValues);
88+
switch (attributeType) {
89+
case STRING_ARRAY:
90+
List<String> strings = new ArrayList<>();
91+
for (Value<?> v : arrayValues) {
92+
strings.add((String) v.getValue());
93+
}
94+
data.add(stringArrayKey(keyName));
95+
data.add(strings);
96+
return;
97+
case LONG_ARRAY:
98+
List<Long> longs = new ArrayList<>();
99+
for (Value<?> v : arrayValues) {
100+
longs.add((Long) v.getValue());
101+
}
102+
data.add(longArrayKey(keyName));
103+
data.add(longs);
104+
return;
105+
case DOUBLE_ARRAY:
106+
List<Double> doubles = new ArrayList<>();
107+
for (Value<?> v : arrayValues) {
108+
doubles.add((Double) v.getValue());
109+
}
110+
data.add(doubleArrayKey(keyName));
111+
data.add(doubles);
112+
return;
113+
case BOOLEAN_ARRAY:
114+
List<Boolean> booleans = new ArrayList<>();
115+
for (Value<?> v : arrayValues) {
116+
booleans.add((Boolean) v.getValue());
117+
}
118+
data.add(booleanArrayKey(keyName));
119+
data.add(booleans);
120+
return;
121+
case VALUE:
122+
// Not coercible (empty, non-homogeneous, or unsupported element type)
123+
// TODO when empty, retrieve it when asked for any kind of array?
124+
data.add(key);
125+
data.add(valueObj);
126+
return;
127+
default:
128+
throw new IllegalArgumentException("Unexpected array attribute type: " + attributeType);
129+
}
130+
case KEY_VALUE_LIST:
131+
case BYTES:
132+
// Keep as VALUE type
133+
data.add(key);
134+
data.add(valueObj);
135+
return;
136+
}
137+
}
138+
139+
/**
140+
* Returns the AttributeType for a homogeneous array (STRING_ARRAY, LONG_ARRAY, DOUBLE_ARRAY, or
141+
* BOOLEAN_ARRAY), or VALUE if the array is empty, non-homogeneous, or contains unsupported
142+
* element types.
143+
*/
144+
private static AttributeType attributeType(List<Value<?>> arrayValues) {
145+
if (arrayValues.isEmpty()) {
146+
return AttributeType.VALUE;
147+
}
148+
ValueType elementType = arrayValues.get(0).getType();
149+
for (Value<?> v : arrayValues) {
150+
if (v.getType() != elementType) {
151+
return AttributeType.VALUE;
152+
}
153+
}
154+
switch (elementType) {
155+
case STRING:
156+
return AttributeType.STRING_ARRAY;
157+
case LONG:
158+
return AttributeType.LONG_ARRAY;
159+
case DOUBLE:
160+
return AttributeType.DOUBLE_ARRAY;
161+
case BOOLEAN:
162+
return AttributeType.BOOLEAN_ARRAY;
163+
case ARRAY:
164+
case KEY_VALUE_LIST:
165+
case BYTES:
166+
return AttributeType.VALUE;
167+
}
168+
throw new IllegalArgumentException("Unsupported element type: " + elementType);
169+
}
170+
50171
@Override
51172
@SuppressWarnings({"unchecked", "rawtypes"})
52173
public AttributesBuilder putAll(Attributes attributes) {

0 commit comments

Comments
 (0)