|
5 | 5 |
|
6 | 6 | package io.opentelemetry.api.common; |
7 | 7 |
|
| 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 | + |
8 | 17 | import java.util.ArrayList; |
9 | 18 | import java.util.Arrays; |
10 | 19 | import java.util.List; |
@@ -38,15 +47,127 @@ public <T> AttributesBuilder put(AttributeKey<Long> key, int value) { |
38 | 47 | } |
39 | 48 |
|
40 | 49 | @Override |
| 50 | + @SuppressWarnings("unchecked") |
41 | 51 | public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) { |
42 | 52 | if (key == null || key.getKey().isEmpty() || value == null) { |
43 | 53 | return this; |
44 | 54 | } |
| 55 | + if (key.getType() == AttributeType.VALUE && value instanceof Value) { |
| 56 | + putValue(key, (Value<?>) value); |
| 57 | + return this; |
| 58 | + } |
45 | 59 | data.add(key); |
46 | 60 | data.add(value); |
47 | 61 | return this; |
48 | 62 | } |
49 | 63 |
|
| 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 | + |
50 | 171 | @Override |
51 | 172 | @SuppressWarnings({"unchecked", "rawtypes"}) |
52 | 173 | public AttributesBuilder putAll(Attributes attributes) { |
|
0 commit comments