Skip to content

Commit 0e2af07

Browse files
committed
updates
1 parent 8c951bd commit 0e2af07

7 files changed

Lines changed: 294 additions & 124 deletions

File tree

api/all/src/test/java/io/opentelemetry/api/common/AttributesTest.java

Lines changed: 255 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -359,90 +359,273 @@ void builder_arrayTypes() {
359359
}
360360

361361
@Test
362-
void builder_valueTypes() {
363-
// Test Value type attributes with various Value kinds
364-
// Note: simple Value types (string, long, double, boolean) are coerced to their
365-
// corresponding primitive AttributeTypes for consistent storage
366-
367-
// These Value types should be coerced to primitive types
368-
AttributeKey<Value<?>> stringValueKey = valueKey("stringValue");
369-
AttributeKey<Value<?>> longValueKey = valueKey("longValue");
370-
AttributeKey<Value<?>> doubleValueKey = valueKey("doubleValue");
371-
AttributeKey<Value<?>> booleanValueKey = valueKey("booleanValue");
372-
373-
// These Value types cannot be coerced and remain as VALUE type
374-
AttributeKey<Value<?>> bytesValueKey = valueKey("bytesValue");
375-
AttributeKey<Value<?>> kvListValueKey = valueKey("kvListValue");
376-
AttributeKey<Value<?>> heterogeneousArrayKey = valueKey("heterogeneousArray");
377-
AttributeKey<Value<?>> emptyValueKey = valueKey("emptyValue");
362+
void valueStoredAsString() {
363+
// When putting a VALUE attribute with a string Value, it should be stored as STRING type
364+
Attributes attributes = Attributes.builder().put(valueKey("key"), Value.of("test")).build();
378365

366+
// Should be stored as STRING type internally
367+
assertThat(attributes.get(stringKey("key"))).isEqualTo("test");
368+
assertThat(attributes.get(valueKey("key"))).isEqualTo(Value.of("test"));
369+
370+
// forEach should show STRING type
371+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
372+
attributes.forEach(entriesSeen::put);
373+
assertThat(entriesSeen).containsExactly(entry(stringKey("key"), "test"));
374+
375+
// asMap should show STRING type
376+
assertThat(attributes.asMap()).containsExactly(entry(stringKey("key"), "test"));
377+
}
378+
379+
@Test
380+
void valueStoredAsLong() {
381+
// When putting a VALUE attribute with a long Value, it should be stored as LONG type
382+
Attributes attributes = Attributes.builder().put(valueKey("key"), Value.of(123L)).build();
383+
384+
// Should be stored as LONG type internally
385+
assertThat(attributes.get(longKey("key"))).isEqualTo(123L);
386+
assertThat(attributes.get(valueKey("key"))).isEqualTo(Value.of(123L));
387+
388+
// forEach should show LONG type
389+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
390+
attributes.forEach(entriesSeen::put);
391+
assertThat(entriesSeen).containsExactly(entry(longKey("key"), 123L));
392+
393+
// asMap should show LONG type
394+
assertThat(attributes.asMap()).containsExactly(entry(longKey("key"), 123L));
395+
}
396+
397+
@Test
398+
void valueStoredAsDouble() {
399+
// When putting a VALUE attribute with a double Value, it should be stored as DOUBLE type
400+
Attributes attributes = Attributes.builder().put(valueKey("key"), Value.of(1.23)).build();
401+
402+
// Should be stored as DOUBLE type internally
403+
assertThat(attributes.get(doubleKey("key"))).isEqualTo(1.23);
404+
assertThat(attributes.get(valueKey("key"))).isEqualTo(Value.of(1.23));
405+
406+
// forEach should show DOUBLE type
407+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
408+
attributes.forEach(entriesSeen::put);
409+
assertThat(entriesSeen).containsExactly(entry(doubleKey("key"), 1.23));
410+
411+
// asMap should show DOUBLE type
412+
assertThat(attributes.asMap()).containsExactly(entry(doubleKey("key"), 1.23));
413+
}
414+
415+
@Test
416+
void valueStoredAsBoolean() {
417+
// When putting a VALUE attribute with a boolean Value, it should be stored as BOOLEAN type
418+
Attributes attributes = Attributes.builder().put(valueKey("key"), Value.of(true)).build();
419+
420+
// Should be stored as BOOLEAN type internally
421+
assertThat(attributes.get(booleanKey("key"))).isEqualTo(true);
422+
assertThat(attributes.get(valueKey("key"))).isEqualTo(Value.of(true));
423+
424+
// forEach should show BOOLEAN type
425+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
426+
attributes.forEach(entriesSeen::put);
427+
assertThat(entriesSeen).containsExactly(entry(booleanKey("key"), true));
428+
429+
// asMap should show BOOLEAN type
430+
assertThat(attributes.asMap()).containsExactly(entry(booleanKey("key"), true));
431+
}
432+
433+
@Test
434+
void valueStoredAsStringArray() {
435+
// When putting a VALUE attribute with a homogeneous string array, it should be stored as
436+
// STRING_ARRAY type
379437
Attributes attributes =
380438
Attributes.builder()
381-
.put(stringValueKey, Value.of("stringVal"))
382-
.put(longValueKey, Value.of(100L))
383-
.put(doubleValueKey, Value.of(3.14))
384-
.put(booleanValueKey, Value.of(true))
385-
.put(bytesValueKey, Value.of(new byte[] {1, 2, 3}))
386-
.put(kvListValueKey, Value.of(KeyValue.of("nested", Value.of("value"))))
387-
.put(heterogeneousArrayKey, Value.of(Value.of("elem1"), Value.of(42L)))
388-
.put(emptyValueKey, Value.empty())
439+
.put(valueKey("key"), Value.of(Arrays.asList(Value.of("a"), Value.of("b"))))
389440
.build();
390441

391-
// Verify coerced values can be retrieved with primitive keys
392-
assertThat(attributes.get(stringKey("stringValue"))).isEqualTo("stringVal");
393-
assertThat(attributes.get(longKey("longValue"))).isEqualTo(100L);
394-
assertThat(attributes.get(doubleKey("doubleValue"))).isEqualTo(3.14);
395-
assertThat(attributes.get(booleanKey("booleanValue"))).isEqualTo(true);
442+
// Should be stored as STRING_ARRAY type internally
443+
assertThat(attributes.get(stringArrayKey("key"))).containsExactly("a", "b");
444+
assertThat(attributes.get(valueKey("key")))
445+
.isEqualTo(Value.of(Arrays.asList(Value.of("a"), Value.of("b"))));
396446

397-
// Verify complex Value types that remain as VALUE type
398-
assertThat(attributes.get(bytesValueKey)).isNotNull();
399-
assertThat(attributes.get(bytesValueKey).getType()).isEqualTo(ValueType.BYTES);
447+
// forEach should show STRING_ARRAY type
448+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
449+
attributes.forEach(entriesSeen::put);
450+
assertThat(entriesSeen).containsExactly(entry(stringArrayKey("key"), Arrays.asList("a", "b")));
400451

401-
assertThat(attributes.get(kvListValueKey)).isNotNull();
402-
assertThat(attributes.get(kvListValueKey).getType()).isEqualTo(ValueType.KEY_VALUE_LIST);
452+
// asMap should show STRING_ARRAY type
453+
assertThat(attributes.asMap())
454+
.containsExactly(entry(stringArrayKey("key"), Arrays.asList("a", "b")));
455+
}
403456

404-
assertThat(attributes.get(heterogeneousArrayKey)).isNotNull();
405-
assertThat(attributes.get(heterogeneousArrayKey).getType()).isEqualTo(ValueType.ARRAY);
457+
@Test
458+
void valueStoredAsLongArray() {
459+
// When putting a VALUE attribute with a homogeneous long array, it should be stored as
460+
// LONG_ARRAY type
461+
Attributes attributes =
462+
Attributes.builder()
463+
.put(valueKey("key"), Value.of(Arrays.asList(Value.of(1L), Value.of(2L))))
464+
.build();
406465

407-
assertThat(attributes.get(emptyValueKey)).isNotNull();
408-
assertThat(attributes.get(emptyValueKey).getType()).isEqualTo(ValueType.EMPTY);
409-
assertThat(attributes.get(emptyValueKey).getValue()).isNull();
466+
// Should be stored as LONG_ARRAY type internally
467+
assertThat(attributes.get(longArrayKey("key"))).containsExactly(1L, 2L);
468+
assertThat(attributes.get(valueKey("key")))
469+
.isEqualTo(Value.of(Arrays.asList(Value.of(1L), Value.of(2L))));
410470

411-
// Verify the total size
412-
assertThat(attributes.size()).isEqualTo(8);
471+
// forEach should show LONG_ARRAY type
472+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
473+
attributes.forEach(entriesSeen::put);
474+
assertThat(entriesSeen).containsExactly(entry(longArrayKey("key"), Arrays.asList(1L, 2L)));
413475

414-
// Verify forEach sees the correct types
415-
Map<AttributeKey, Object> entriesSeen = new LinkedHashMap<>();
476+
// asMap should show LONG_ARRAY type
477+
assertThat(attributes.asMap())
478+
.containsExactly(entry(longArrayKey("key"), Arrays.asList(1L, 2L)));
479+
}
480+
481+
@Test
482+
void valueStoredAsDoubleArray() {
483+
// When putting a VALUE attribute with a homogeneous double array, it should be stored as
484+
// DOUBLE_ARRAY type
485+
Attributes attributes =
486+
Attributes.builder()
487+
.put(valueKey("key"), Value.of(Arrays.asList(Value.of(1.1), Value.of(2.2))))
488+
.build();
489+
490+
// Should be stored as DOUBLE_ARRAY type internally
491+
assertThat(attributes.get(doubleArrayKey("key"))).containsExactly(1.1, 2.2);
492+
assertThat(attributes.get(valueKey("key")))
493+
.isEqualTo(Value.of(Arrays.asList(Value.of(1.1), Value.of(2.2))));
494+
495+
// forEach should show DOUBLE_ARRAY type
496+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
497+
attributes.forEach(entriesSeen::put);
498+
assertThat(entriesSeen).containsExactly(entry(doubleArrayKey("key"), Arrays.asList(1.1, 2.2)));
499+
500+
// asMap should show DOUBLE_ARRAY type
501+
assertThat(attributes.asMap())
502+
.containsExactly(entry(doubleArrayKey("key"), Arrays.asList(1.1, 2.2)));
503+
}
504+
505+
@Test
506+
void valueStoredAsBooleanArray() {
507+
// When putting a VALUE attribute with a homogeneous boolean array, it should be stored as
508+
// BOOLEAN_ARRAY type
509+
Attributes attributes =
510+
Attributes.builder()
511+
.put(valueKey("key"), Value.of(Arrays.asList(Value.of(true), Value.of(false))))
512+
.build();
513+
514+
// Should be stored as BOOLEAN_ARRAY type internally
515+
assertThat(attributes.get(booleanArrayKey("key"))).containsExactly(true, false);
516+
assertThat(attributes.get(valueKey("key")))
517+
.isEqualTo(Value.of(Arrays.asList(Value.of(true), Value.of(false))));
518+
519+
// forEach should show BOOLEAN_ARRAY type
520+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
521+
attributes.forEach(entriesSeen::put);
522+
assertThat(entriesSeen)
523+
.containsExactly(entry(booleanArrayKey("key"), Arrays.asList(true, false)));
524+
525+
// asMap should show BOOLEAN_ARRAY type
526+
assertThat(attributes.asMap())
527+
.containsExactly(entry(booleanArrayKey("key"), Arrays.asList(true, false)));
528+
}
529+
530+
@Test
531+
void simpleAttributeRetrievedAsValue() {
532+
Attributes attributes =
533+
Attributes.builder()
534+
.put("string", "test")
535+
.put("long", 123L)
536+
.put("double", 1.23)
537+
.put("boolean", true)
538+
.put("stringArray", "a", "b")
539+
.put("longArray", 1L, 2L)
540+
.put("doubleArray", 1.1, 2.2)
541+
.put("booleanArray", true, false)
542+
.build();
543+
assertThat(attributes.get(valueKey("string"))).isEqualTo(Value.of("test"));
544+
assertThat(attributes.get(valueKey("long"))).isEqualTo(Value.of(123L));
545+
assertThat(attributes.get(valueKey("double"))).isEqualTo(Value.of(1.23));
546+
assertThat(attributes.get(valueKey("boolean"))).isEqualTo(Value.of(true));
547+
assertThat(attributes.get(valueKey("stringArray")))
548+
.isEqualTo(Value.of(Arrays.asList(Value.of("a"), Value.of("b"))));
549+
assertThat(attributes.get(valueKey("longArray")))
550+
.isEqualTo(Value.of(Arrays.asList(Value.of(1L), Value.of(2L))));
551+
assertThat(attributes.get(valueKey("doubleArray")))
552+
.isEqualTo(Value.of(Arrays.asList(Value.of(1.1), Value.of(2.2))));
553+
assertThat(attributes.get(valueKey("booleanArray")))
554+
.isEqualTo(Value.of(Arrays.asList(Value.of(true), Value.of(false))));
555+
}
556+
557+
@Test
558+
void emptyValueArrayRetrievedAsAnyArrayType() {
559+
Attributes attributes =
560+
Attributes.builder().put(valueKey("key"), Value.of(Collections.emptyList())).build();
561+
assertThat(attributes.get(stringArrayKey("key"))).isEmpty();
562+
assertThat(attributes.get(longArrayKey("key"))).isEmpty();
563+
assertThat(attributes.get(doubleArrayKey("key"))).isEmpty();
564+
assertThat(attributes.get(booleanArrayKey("key"))).isEmpty();
565+
}
566+
567+
@Test
568+
void valueWithKeyValueList() {
569+
// KEY_VALUE_LIST should be kept as VALUE type
570+
Value<?> kvListValue = Value.of(Collections.emptyMap());
571+
Attributes attributes = Attributes.builder().put(valueKey("key"), kvListValue).build();
572+
573+
// Should be stored as VALUE type
574+
assertThat(attributes.get(valueKey("key"))).isEqualTo(kvListValue);
575+
576+
// forEach should show VALUE type
577+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
578+
attributes.forEach(entriesSeen::put);
579+
assertThat(entriesSeen).containsExactly(entry(valueKey("key"), kvListValue));
580+
}
581+
582+
@Test
583+
void valueWithBytes() {
584+
// BYTES should be kept as VALUE type
585+
Value<?> bytesValue = Value.of(new byte[] {1, 2, 3});
586+
Attributes attributes = Attributes.builder().put(valueKey("key"), bytesValue).build();
587+
588+
// Should be stored as VALUE type
589+
assertThat(attributes.get(valueKey("key"))).isEqualTo(bytesValue);
590+
591+
// forEach should show VALUE type
592+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
593+
attributes.forEach(entriesSeen::put);
594+
assertThat(entriesSeen).containsExactly(entry(valueKey("key"), bytesValue));
595+
}
596+
597+
@Test
598+
void valueWithNonHomogeneousArray() {
599+
// Non-homogeneous array should be kept as VALUE type
600+
Value<?> mixedArray = Value.of(Arrays.asList(Value.of("string"), Value.of(123L)));
601+
Attributes attributes = Attributes.builder().put(valueKey("key"), mixedArray).build();
602+
603+
// Should be stored as VALUE type
604+
assertThat(attributes.get(valueKey("key"))).isEqualTo(mixedArray);
605+
606+
// forEach should show VALUE type
607+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
608+
attributes.forEach(entriesSeen::put);
609+
assertThat(entriesSeen).containsExactly(entry(valueKey("key"), mixedArray));
610+
}
611+
612+
@Test
613+
void valueWithNestedArray() {
614+
// Array containing arrays should be kept as VALUE type
615+
Value<?> nestedArray =
616+
Value.of(
617+
Arrays.asList(
618+
Value.of(Arrays.asList(Value.of("a"), Value.of("b"))),
619+
Value.of(Arrays.asList(Value.of("c"), Value.of("d")))));
620+
Attributes attributes = Attributes.builder().put(valueKey("key"), nestedArray).build();
621+
622+
// Should be stored as VALUE type
623+
assertThat(attributes.get(valueKey("key"))).isEqualTo(nestedArray);
624+
625+
// forEach should show VALUE type
626+
Map<AttributeKey, Object> entriesSeen = new HashMap<>();
416627
attributes.forEach(entriesSeen::put);
417-
assertThat(entriesSeen).hasSize(8);
418-
419-
// Verify coerced keys have primitive types
420-
assertThat(entriesSeen.keySet())
421-
.filteredOn(key -> key.getKey().equals("stringValue"))
422-
.allMatch(key -> key.getType() == AttributeType.STRING);
423-
assertThat(entriesSeen.keySet())
424-
.filteredOn(key -> key.getKey().equals("longValue"))
425-
.allMatch(key -> key.getType() == AttributeType.LONG);
426-
assertThat(entriesSeen.keySet())
427-
.filteredOn(key -> key.getKey().equals("doubleValue"))
428-
.allMatch(key -> key.getType() == AttributeType.DOUBLE);
429-
assertThat(entriesSeen.keySet())
430-
.filteredOn(key -> key.getKey().equals("booleanValue"))
431-
.allMatch(key -> key.getType() == AttributeType.BOOLEAN);
432-
433-
// Verify complex types remain as VALUE type
434-
assertThat(entriesSeen.keySet())
435-
.filteredOn(key -> key.getKey().equals("bytesValue"))
436-
.allMatch(key -> key.getType() == AttributeType.VALUE);
437-
assertThat(entriesSeen.keySet())
438-
.filteredOn(key -> key.getKey().equals("kvListValue"))
439-
.allMatch(key -> key.getType() == AttributeType.VALUE);
440-
assertThat(entriesSeen.keySet())
441-
.filteredOn(key -> key.getKey().equals("heterogeneousArray"))
442-
.allMatch(key -> key.getType() == AttributeType.VALUE);
443-
assertThat(entriesSeen.keySet())
444-
.filteredOn(key -> key.getKey().equals("emptyValue"))
445-
.allMatch(key -> key.getType() == AttributeType.VALUE);
628+
assertThat(entriesSeen).containsExactly(entry(valueKey("key"), nestedArray));
446629
}
447630

448631
@Test

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public void writeTo(Serializer output, AttributeType type, List<T> list, Marshal
5252
DoubleAnyValueStatelessMarshaler.INSTANCE,
5353
context);
5454
return;
55-
// TODO this class is named *ArrayAnyValue*, does that mean it covers List<Value<?>> as well?
5655
default:
5756
throw new IllegalArgumentException("Unsupported attribute type.");
5857
}
@@ -83,7 +82,6 @@ public int getBinarySerializedSize(AttributeType type, List<T> list, MarshalerCo
8382
(List<Double>) list,
8483
DoubleAnyValueStatelessMarshaler.INSTANCE,
8584
context);
86-
// TODO this class is named *ArrayAnyValue*, does that mean it covers List<Value<?>> as well?
8785
default:
8886
throw new IllegalArgumentException("Unsupported attribute type.");
8987
}

0 commit comments

Comments
 (0)