From 27d111c7bf4ddf1307d6bee1a1f9029fe69752a7 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 15 Dec 2024 17:28:19 -0800 Subject: [PATCH 1/2] How to support complex attributes in logs/events? (Option B) --- .../api/common/AttributeKey.java | 5 +++ .../api/common/AttributeType.java | 3 +- .../api/common/AttributesBuilder.java | 16 +++++++++ .../io/opentelemetry/api/common/Value.java | 4 +++ .../api/common/ValueBuilder.java | 33 +++++++++++++++++++ .../api/common/ValueBuilderImpl.java | 20 +++++++++++ 6 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java create mode 100644 api/all/src/main/java/io/opentelemetry/api/common/ValueBuilderImpl.java diff --git a/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey.java b/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey.java index 7743c315c50..a9a5dd31772 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/AttributeKey.java @@ -65,4 +65,9 @@ static AttributeKey> longArrayKey(String key) { static AttributeKey> doubleArrayKey(String key) { return InternalAttributeKeyImpl.create(key, AttributeType.DOUBLE_ARRAY); } + + /** Returns a new AttributeKey for Value valued attributes. */ + static AttributeKey valueKey(String key) { + return InternalAttributeKeyImpl.create(key, AttributeType.VALUE); + } } diff --git a/api/all/src/main/java/io/opentelemetry/api/common/AttributeType.java b/api/all/src/main/java/io/opentelemetry/api/common/AttributeType.java index 1c51e36d644..8ed5baa94bf 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/AttributeType.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/AttributeType.java @@ -17,5 +17,6 @@ public enum AttributeType { STRING_ARRAY, BOOLEAN_ARRAY, LONG_ARRAY, - DOUBLE_ARRAY + DOUBLE_ARRAY, + VALUE } diff --git a/api/all/src/main/java/io/opentelemetry/api/common/AttributesBuilder.java b/api/all/src/main/java/io/opentelemetry/api/common/AttributesBuilder.java index a7fe1be0ee0..2553eb37b51 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/AttributesBuilder.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/AttributesBuilder.java @@ -14,6 +14,7 @@ import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringArrayKey; import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.api.common.AttributeKey.valueKey; import java.util.Arrays; import java.util.List; @@ -86,6 +87,21 @@ default AttributesBuilder put(String key, boolean value) { return put(booleanKey(key), value); } + /** + * Puts a {@link Value} attribute into this. + * + *

Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate + * your keys, if possible. + * + *

IMPORTANT: {@link Value} attributes are only supported by Logs. Spans and Metrics do not + * support {@link Value} attributes. + * + * @return this Builder + */ + default AttributesBuilder put(String key, Value value) { + return put(valueKey(key), value); + } + /** * Puts a String array attribute into this. * diff --git a/api/all/src/main/java/io/opentelemetry/api/common/Value.java b/api/all/src/main/java/io/opentelemetry/api/common/Value.java index a29be801e27..a49251fdd40 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/Value.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/Value.java @@ -115,4 +115,8 @@ static Value> of(Map> value) { */ // TODO(jack-berg): Should this be a JSON encoding? String asString(); + + static ValueBuilder builder() { + return new ValueBuilderImpl(); + } } diff --git a/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java new file mode 100644 index 00000000000..907b5c267e6 --- /dev/null +++ b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.api.common; + +public interface ValueBuilder { + + Value build(); + + ValueBuilder put(String key, Value value); + + default ValueBuilder put(String key, String value) { + put(key, Value.of(value)); + return this; + } + + default ValueBuilder put(String key, long value) { + put(key, Value.of(value)); + return this; + } + + default ValueBuilder put(String key, double value) { + put(key, Value.of(value)); + return this; + } + + default ValueBuilder put(String key, boolean value) { + put(key, Value.of(value)); + return this; + } +} diff --git a/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilderImpl.java b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilderImpl.java new file mode 100644 index 00000000000..ddc417a7539 --- /dev/null +++ b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilderImpl.java @@ -0,0 +1,20 @@ +package io.opentelemetry.api.common; + +import java.util.ArrayList; +import java.util.List; + +class ValueBuilderImpl implements ValueBuilder { + + private final List keyValues = new ArrayList<>(); + + @Override + public ValueBuilder put(String key, Value value) { + keyValues.add(KeyValue.of(key, value)); + return this; + } + + @Override + public Value build() { + return Value.of(keyValues.toArray(new KeyValue[0])); + } +} From 7ba8e32bf83e1e54cf95dd6c097341fb19516c64 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 15 Dec 2024 17:41:41 -0800 Subject: [PATCH 2/2] Some more convenience methods --- .../api/common/ValueBuilder.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java index 907b5c267e6..c0ff2c8b5f2 100644 --- a/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java +++ b/api/all/src/main/java/io/opentelemetry/api/common/ValueBuilder.java @@ -5,6 +5,12 @@ package io.opentelemetry.api.common; +import static java.util.stream.Collectors.toList; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public interface ValueBuilder { Value build(); @@ -30,4 +36,28 @@ default ValueBuilder put(String key, boolean value) { put(key, Value.of(value)); return this; } + + default ValueBuilder put(String key, String... value) { + put(key, Value.of(Arrays.stream(value).map(Value::of).collect(toList()))); + return this; + } + + default ValueBuilder put(String key, long... value) { + put(key, Value.of(Arrays.stream(value).mapToObj(Value::of).collect(toList()))); + return this; + } + + default ValueBuilder put(String key, double... value) { + put(key, Value.of(Arrays.stream(value).mapToObj(Value::of).collect(toList()))); + return this; + } + + default ValueBuilder put(String key, boolean... value) { + List> values = new ArrayList<>(value.length); + for (boolean val : value) { + values.add(Value.of(val)); + } + put(key, Value.of(values)); + return this; + } }