From e19cabba981c110fb62e9734b1343dd76e452bc9 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Fri, 29 Mar 2024 17:43:47 -0500 Subject: [PATCH] Add put(AttributeKey, T) overload to EventBuilder --- .../api/incubator/events/EventBuilder.java | 45 ++++++++++++++++++- .../events/DefaultEventLoggerTest.java | 37 ++++++++++++++- .../internal/SdkEventLoggerProviderTest.java | 23 ++++++++++ 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/events/EventBuilder.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/events/EventBuilder.java index 27cd6f8c367..9aca02b3077 100644 --- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/events/EventBuilder.java +++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/events/EventBuilder.java @@ -5,6 +5,9 @@ package io.opentelemetry.api.incubator.events; +import static java.util.stream.Collectors.toList; + +import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.incubator.logs.AnyValue; import io.opentelemetry.api.logs.Severity; @@ -73,6 +76,44 @@ default EventBuilder put(String key, boolean... value) { return put(key, AnyValue.of(values)); } + /** + * Put the given key and value in the payload. + * + *

NOTE: The key value pair is NOT added to the event attributes. Setting event attributes is + * less common than adding entries to the event payload. Use {@link #setAttributes(Attributes)} if + * intending the data to be set in attributes instead of the payload. + */ + @SuppressWarnings("unchecked") + default EventBuilder put(AttributeKey key, T value) { + switch (key.getType()) { + case STRING: + return put(key.getKey(), (String) value); + case BOOLEAN: + return put(key.getKey(), (boolean) value); + case LONG: + return put(key.getKey(), (long) value); + case DOUBLE: + return put(key.getKey(), (double) value); + case STRING_ARRAY: + return put( + key.getKey(), + AnyValue.of(((List) value).stream().map(AnyValue::of).collect(toList()))); + case BOOLEAN_ARRAY: + return put( + key.getKey(), + AnyValue.of(((List) value).stream().map(AnyValue::of).collect(toList()))); + case LONG_ARRAY: + return put( + key.getKey(), + AnyValue.of(((List) value).stream().map(AnyValue::of).collect(toList()))); + case DOUBLE_ARRAY: + return put( + key.getKey(), + AnyValue.of(((List) value).stream().map(AnyValue::of).collect(toList()))); + } + return this; + } + /** Put the given {@code key} and {@code value} in the payload. */ EventBuilder put(String key, AnyValue value); @@ -102,7 +143,9 @@ default EventBuilder put(String key, boolean... value) { * Set the attributes. * *

Event {@link io.opentelemetry.api.common.Attributes} provide additional details about the - * Event which are not part of the well-defined {@link AnyValue} {@code payload}. + * Event which are not part of the well-defined {@link AnyValue} payload. Setting event attributes + * is less common than adding entries to the event payload. Most users will want to call one of + * the {@code #put(String, ?)} methods instead. */ EventBuilder setAttributes(Attributes attributes); diff --git a/api/incubator/src/test/java/io/opentelemetry/api/incubator/events/DefaultEventLoggerTest.java b/api/incubator/src/test/java/io/opentelemetry/api/incubator/events/DefaultEventLoggerTest.java index e1f1f2e7ce7..054e09d2c35 100644 --- a/api/incubator/src/test/java/io/opentelemetry/api/incubator/events/DefaultEventLoggerTest.java +++ b/api/incubator/src/test/java/io/opentelemetry/api/incubator/events/DefaultEventLoggerTest.java @@ -7,23 +7,58 @@ import static org.assertj.core.api.Assertions.assertThatCode; +import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.incubator.logs.AnyValue; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; class DefaultEventLoggerTest { @Test + @SuppressWarnings("DoubleBraceInitialization") void builder() { EventLogger eventLogger = DefaultEventLogger.getInstance(); assertThatCode( () -> eventLogger .builder("namespace.myEvent") - .put("key", "value") + // Helper methods to set primitive types + .put("stringKey", "value") + .put("longKey", 1L) + .put("doubleKey", 1.0) + .put("boolKey", true) + // Helper methods to set primitive array types + .put("stringArrKey", "value1", "value2") + .put("longArrKey", 1L, 2L) + .put("doubleArrKey", 1.0, 2.0) + .put("boolArrKey", true, false) + // Set AnyValue types to encode complex data + .put( + "anyValueKey", + AnyValue.of( + new HashMap>() { + { + put("key", AnyValue.of("value")); + } + })) + // Helper methods to set AttributeKey types + .put(AttributeKey.stringKey("attrStringKey"), "value") + .put(AttributeKey.longKey("attrLongKey"), 1L) + .put(AttributeKey.doubleKey("attrDoubleKey"), 1.0) + .put(AttributeKey.booleanKey("attrBoolKey"), true) + .put( + AttributeKey.stringArrayKey("attrStringArrKey"), + Arrays.asList("value1", "value2")) + .put(AttributeKey.longArrayKey("attrLongArrKey"), Arrays.asList(1L, 2L)) + .put(AttributeKey.doubleArrayKey("attrDoubleArrKey"), Arrays.asList(1.0, 2.0)) + .put(AttributeKey.booleanArrayKey("attrBoolArrKey"), Arrays.asList(true, false)) + // Other setters .setTimestamp(123456L, TimeUnit.NANOSECONDS) .setTimestamp(Instant.now()) .setContext(Context.current()) diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventLoggerProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventLoggerProviderTest.java index 5c30a6b305d..71f48757207 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventLoggerProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventLoggerProviderTest.java @@ -10,6 +10,7 @@ import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableMap; +import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.incubator.events.EventLogger; import io.opentelemetry.api.incubator.logs.AnyValue; @@ -97,6 +98,15 @@ void eventBuilder_FullPayload() { ImmutableMap.of( "childKey1", AnyValue.of("value"), "childKey2", AnyValue.of("value")))) + // Helper methods to set AttributeKey types + .put(AttributeKey.stringKey("attrStringKey"), "value") + .put(AttributeKey.longKey("attrLongKey"), 1L) + .put(AttributeKey.doubleKey("attrDoubleKey"), 1.0) + .put(AttributeKey.booleanKey("attrBoolKey"), true) + .put(AttributeKey.stringArrayKey("attrStringArrKey"), Arrays.asList("value1", "value2")) + .put(AttributeKey.longArrayKey("attrLongArrKey"), Arrays.asList(1L, 2L)) + .put(AttributeKey.doubleArrayKey("attrDoubleArrKey"), Arrays.asList(1.0, 2.0)) + .put(AttributeKey.booleanArrayKey("attrBoolArrKey"), Arrays.asList(true, false)) .emit(); Map> expectedPayload = new HashMap<>(); @@ -117,6 +127,19 @@ void eventBuilder_FullPayload() { ImmutableMap.of( "childKey1", AnyValue.of("value"), "childKey2", AnyValue.of("value")))); + expectedPayload.put("attrStringKey", AnyValue.of("value")); + expectedPayload.put("attrLongKey", AnyValue.of(1L)); + expectedPayload.put("attrDoubleKey", AnyValue.of(1.0)); + expectedPayload.put("attrBoolKey", AnyValue.of(true)); + expectedPayload.put( + "attrStringArrKey", + AnyValue.of(Arrays.asList(AnyValue.of("value1"), AnyValue.of("value2")))); + expectedPayload.put( + "attrLongArrKey", AnyValue.of(Arrays.asList(AnyValue.of(1L), AnyValue.of(2L)))); + expectedPayload.put( + "attrDoubleArrKey", AnyValue.of(Arrays.asList(AnyValue.of(1.0), AnyValue.of(2.0)))); + expectedPayload.put( + "attrBoolArrKey", AnyValue.of(Arrays.asList(AnyValue.of(true), AnyValue.of(false)))); assertThat(((AnyValueBody) seenLog.get().toLogRecordData().getBody()).asAnyValue()) .isEqualTo(AnyValue.of(expectedPayload)); }