From 75c13bb12444186fbb25b64ef43c88397ddb1fc7 Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Fri, 17 Nov 2023 17:13:29 -0600 Subject: [PATCH 1/3] Refactor Event API to reflect spec changes --- api/events/build.gradle.kts | 1 + .../api/events/DefaultEventEmitter.java | 27 +++++- .../events/DefaultEventEmitterProvider.java | 5 -- .../api/events/EventBuilder.java | 30 ++++++- .../api/events/EventEmitter.java | 28 +++--- .../api/events/EventEmitterBuilder.java | 9 -- .../DefaultEventEmitterProviderTest.java | 5 +- .../api/events/DefaultEventEmitterTest.java | 18 ++-- .../OtlpExporterIntegrationTest.java | 25 +++--- .../sdk/autoconfigure/FullConfigTest.java | 42 ++++----- .../sdk/logs/internal/SdkEventBuilder.java | 46 +++++++++- .../internal/SdkEventEmitterProvider.java | 56 +++++------- .../logs/internal/SdkEventBuilderTest.java | 21 ++++- .../internal/SdkEventEmitterProviderTest.java | 85 +++++++------------ 14 files changed, 227 insertions(+), 171 deletions(-) diff --git a/api/events/build.gradle.kts b/api/events/build.gradle.kts index 9a0262cded0..d0aa3006cc4 100644 --- a/api/events/build.gradle.kts +++ b/api/events/build.gradle.kts @@ -10,4 +10,5 @@ otelJava.moduleName.set("io.opentelemetry.api.events") dependencies { api(project(":api:all")) + api(project(":extensions:incubator")) } diff --git a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java index 8d9a81f8e7f..6525e6bb8f8 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java @@ -6,6 +6,9 @@ package io.opentelemetry.api.events; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import io.opentelemetry.extension.incubator.logs.AnyValue; import java.time.Instant; import java.util.concurrent.TimeUnit; @@ -20,10 +23,10 @@ static EventEmitter getInstance() { } @Override - public void emit(String eventName, Attributes attributes) {} + public void emit(String eventName, AnyValue payload) {} @Override - public EventBuilder builder(String eventName, Attributes attributes) { + public EventBuilder builder(String eventName) { return NoOpEventBuilder.INSTANCE; } @@ -31,6 +34,11 @@ private static class NoOpEventBuilder implements EventBuilder { public static final EventBuilder INSTANCE = new NoOpEventBuilder(); + @Override + public EventBuilder setPayload(AnyValue payload) { + return this; + } + @Override public EventBuilder setTimestamp(long timestamp, TimeUnit unit) { return this; @@ -41,6 +49,21 @@ public EventBuilder setTimestamp(Instant instant) { return this; } + @Override + public EventBuilder setContext(Context context) { + return this; + } + + @Override + public EventBuilder setSeverity(Severity severity) { + return this; + } + + @Override + public EventBuilder setAttributes(Attributes attributes) { + return this; + } + @Override public void emit() {} } diff --git a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitterProvider.java b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitterProvider.java index 2f5b69826fd..59f75872fa1 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitterProvider.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitterProvider.java @@ -34,11 +34,6 @@ public EventEmitterBuilder setInstrumentationVersion(String instrumentationVersi return this; } - @Override - public EventEmitterBuilder setEventDomain(String eventDomain) { - return this; - } - @Override public EventEmitter build() { return DefaultEventEmitter.getInstance(); diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java b/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java index a9acabbca6c..be79729f8ce 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java @@ -5,6 +5,10 @@ package io.opentelemetry.api.events; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import io.opentelemetry.extension.incubator.logs.AnyValue; import java.time.Instant; import java.util.concurrent.TimeUnit; @@ -12,7 +16,15 @@ public interface EventBuilder { /** - * Set the epoch {@code timestamp} for the event, using the timestamp and unit. + * Set the {@code payload}. + * + *

The {@code payload} is expected to match the schema of other events with the same {@code + * eventName}. + */ + EventBuilder setPayload(AnyValue payload); + + /** + * Set the epoch {@code timestamp}, using the timestamp and unit. * *

The {@code timestamp} is the time at which the event occurred. If unset, it will be set to * the current time when {@link #emit()} is called. @@ -20,13 +32,27 @@ public interface EventBuilder { EventBuilder setTimestamp(long timestamp, TimeUnit unit); /** - * Set the epoch {@code timestamp} for the event, using the instant. + * Set the epoch {@code timestamp}t, using the instant. * *

The {@code timestamp} is the time at which the event occurred. If unset, it will be set to * the current time when {@link #emit()} is called. */ EventBuilder setTimestamp(Instant instant); + /** Set the context. */ + EventBuilder setContext(Context context); + + /** Set the severity. */ + EventBuilder setSeverity(Severity severity); + + /** + * 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}. + */ + EventBuilder setAttributes(Attributes attributes); + /** Emit an event. */ void emit(); } diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java index a8dc47c83d7..e7bddeda41f 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java @@ -5,7 +5,7 @@ package io.opentelemetry.api.events; -import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.extension.incubator.logs.AnyValue; import javax.annotation.concurrent.ThreadSafe; /** @@ -13,17 +13,17 @@ * *

Example usage emitting events: * + *

// TODO: rework + * *

{@code
  * class MyClass {
  *   private final EventEmitter eventEmitter = openTelemetryEventEmitterProvider.eventEmitterBuilder("scope-name")
- *         .setEventDomain("acme.observability")
  *         .build();
  *
  *   void doWork() {
- *     eventEmitter.emit("my-event", Attributes.builder()
- *         .put("key1", "value1")
- *         .put("key2", "value2")
- *         .build())
+ *     eventEmitter.emit("namespace.my-event", AnyValue.of(Map.of(
+ *        "key1", AnyValue.of("value1"),
+ *        "key2", AnyValue.of("value2"))));
  *     // do work
  *   }
  * }
@@ -35,18 +35,18 @@ public interface EventEmitter {
   /**
    * Emit an event.
    *
-   * @param eventName the event name, which acts as a classifier for events. Within a particular
-   *     event domain, event name defines a particular class or type of event.
-   * @param attributes attributes associated with the event
+   * @param eventName the event name, which defines the class or type of event. Events names SHOULD
+   *     include a namespace to avoid collisions with other event names.
+   * @param payload the eventPayload, which is expected to match the schema of other events with the
+   *     same {@code eventName}.
    */
-  void emit(String eventName, Attributes attributes);
+  void emit(String eventName, AnyValue payload);
 
   /**
    * Return a {@link EventBuilder} to emit an event.
    *
-   * @param eventName the event name, which acts as a classifier for events. Within a particular
-   *     event domain, event name defines a particular class or type of event.
-   * @param attributes attributes associated with the event
+   * @param eventName the event name, which defines the class or type of event. Events names SHOULD
+   *     include a namespace to avoid collisions with other event names.
    */
-  EventBuilder builder(String eventName, Attributes attributes);
+  EventBuilder builder(String eventName);
 }
diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitterBuilder.java b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitterBuilder.java
index 0aa67a25b08..0bdb9e2f57e 100644
--- a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitterBuilder.java
+++ b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitterBuilder.java
@@ -14,15 +14,6 @@
  */
 public interface EventEmitterBuilder {
 
-  /**
-   * Sets the event domain. Event domain is not part of {@link EventEmitter} identity.
-   *
-   * @param eventDomain The event domain, which acts as a namespace for event names. Within a
-   *     particular event domain, event name defines a particular class or type of event.
-   * @return this
-   */
-  EventEmitterBuilder setEventDomain(String eventDomain);
-
   /**
    * Set the scope schema URL of the resulting {@link EventEmitter}. Schema URL is part of {@link
    * EventEmitter} identity.
diff --git a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java
index 33651e89c6e..6f0a83f49cb 100644
--- a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java
+++ b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java
@@ -8,7 +8,7 @@
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
 
-import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.extension.incubator.logs.AnyValue;
 import org.junit.jupiter.api.Test;
 
 class DefaultEventEmitterProviderTest {
@@ -23,7 +23,6 @@ void noopEventEmitterProvider_doesNotThrow() {
             () ->
                 provider
                     .eventEmitterBuilder("scope-name")
-                    .setEventDomain("event-domain")
                     .setInstrumentationVersion("1.0")
                     .setSchemaUrl("http://schema.com")
                     .build())
@@ -34,7 +33,7 @@ void noopEventEmitterProvider_doesNotThrow() {
                 provider
                     .eventEmitterBuilder("scope-name")
                     .build()
-                    .emit("event-name", Attributes.empty()))
+                    .emit("namespace.event-name", AnyValue.of("")))
         .doesNotThrowAnyException();
   }
 }
diff --git a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java
index 460cb1583ac..429c26b031f 100644
--- a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java
+++ b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java
@@ -8,7 +8,11 @@
 import static org.assertj.core.api.Assertions.assertThatCode;
 
 import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.extension.incubator.logs.AnyValue;
 import java.time.Instant;
+import java.util.Collections;
 import java.util.concurrent.TimeUnit;
 import org.junit.jupiter.api.Test;
 
@@ -16,25 +20,29 @@ class DefaultEventEmitterTest {
 
   @Test
   void emit() {
-    assertThatCode(() -> DefaultEventEmitter.getInstance().emit("event-name", Attributes.empty()))
-        .doesNotThrowAnyException();
     assertThatCode(
             () ->
                 DefaultEventEmitter.getInstance()
-                    .emit("event-name", Attributes.builder().put("key1", "value1").build()))
+                    .emit(
+                        "namespace.event-name",
+                        AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1")))))
         .doesNotThrowAnyException();
   }
 
   @Test
   void builder() {
-    Attributes attributes = Attributes.builder().put("key1", "value1").build();
     EventEmitter emitter = DefaultEventEmitter.getInstance();
     assertThatCode(
             () ->
                 emitter
-                    .builder("myEvent", attributes)
+                    .builder("namespace.myEvent")
+                    .setPayload(
+                        AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1"))))
                     .setTimestamp(123456L, TimeUnit.NANOSECONDS)
                     .setTimestamp(Instant.now())
+                    .setContext(Context.current())
+                    .setSeverity(Severity.DEBUG)
+                    .setAttributes(Attributes.empty())
                     .emit())
         .doesNotThrowAnyException();
   }
diff --git a/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java
index 7bfa82a3876..05d2e0c2a2d 100644
--- a/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java
+++ b/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java
@@ -528,7 +528,6 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) {
     EventEmitter eventEmitter =
         SdkEventEmitterProvider.create(loggerProvider)
             .eventEmitterBuilder(OtlpExporterIntegrationTest.class.getName())
-            .setEventDomain("event-domain")
             .build();
 
     SpanContext spanContext =
@@ -548,7 +547,11 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) {
           .setSeverityText("DEBUG")
           .setContext(Context.current())
           .emit();
-      eventEmitter.emit("event-name", Attributes.builder().put("key", "value").build());
+      eventEmitter.emit(
+          "namespace.event-name",
+          io.opentelemetry.extension.incubator.logs.AnyValue.of(
+              Collections.singletonMap(
+                  "key", io.opentelemetry.extension.incubator.logs.AnyValue.of("value"))));
     }
 
     // Closing triggers flush of processor
@@ -597,20 +600,18 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) {
 
     // LogRecord via EventEmitter.emit(String, Attributes)
     io.opentelemetry.proto.logs.v1.LogRecord protoLog2 = ilLogs.getLogRecords(1);
-    assertThat(protoLog2.getBody().getStringValue()).isEmpty();
+    assertThat(protoLog2.getBody())
+        .isEqualTo(
+            AnyValue.newBuilder()
+                // TODO: update after merging
+                // https://github.com/open-telemetry/opentelemetry-java/pull/5938
+                .setStringValue("[key=value]")
+                .build());
     assertThat(protoLog2.getAttributesList())
         .containsExactlyInAnyOrder(
-            KeyValue.newBuilder()
-                .setKey("event.domain")
-                .setValue(AnyValue.newBuilder().setStringValue("event-domain").build())
-                .build(),
             KeyValue.newBuilder()
                 .setKey("event.name")
-                .setValue(AnyValue.newBuilder().setStringValue("event-name").build())
-                .build(),
-            KeyValue.newBuilder()
-                .setKey("key")
-                .setValue(AnyValue.newBuilder().setStringValue("value").build())
+                .setValue(AnyValue.newBuilder().setStringValue("namespace.event-name").build())
                 .build());
     assertThat(protoLog2.getSeverityText()).isEmpty();
     assertThat(TraceId.fromBytes(protoLog2.getTraceId().toByteArray()))
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java
index affe5d4fd63..4490c7d4f42 100644
--- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FullConfigTest.java
@@ -38,10 +38,12 @@
 import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
 import io.opentelemetry.proto.common.v1.AnyValue;
 import io.opentelemetry.proto.common.v1.KeyValue;
+import io.opentelemetry.proto.logs.v1.SeverityNumber;
 import io.opentelemetry.proto.metrics.v1.Metric;
 import io.opentelemetry.sdk.OpenTelemetrySdk;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingDeque;
@@ -207,11 +209,12 @@ void configures() throws Exception {
     logger.logRecordBuilder().setBody("info log message").setSeverity(Severity.INFO).emit();
 
     EventEmitter eventEmitter =
-        GlobalEventEmitterProvider.get()
-            .eventEmitterBuilder("test")
-            .setEventDomain("test-domain")
-            .build();
-    eventEmitter.emit("test-name", Attributes.builder().put("cow", "moo").build());
+        GlobalEventEmitterProvider.get().eventEmitterBuilder("test").build();
+    eventEmitter.emit(
+        "namespace.test-name",
+        io.opentelemetry.extension.incubator.logs.AnyValue.of(
+            Collections.singletonMap(
+                "cow", io.opentelemetry.extension.incubator.logs.AnyValue.of("moo"))));
 
     openTelemetrySdk.getSdkTracerProvider().forceFlush().join(10, TimeUnit.SECONDS);
     openTelemetrySdk.getSdkLoggerProvider().forceFlush().join(10, TimeUnit.SECONDS);
@@ -333,21 +336,20 @@ void configures() throws Exception {
               assertThat(logRecord.getSeverityNumberValue())
                   .isEqualTo(Severity.INFO.getSeverityNumber());
             },
-            logRecord ->
-                assertThat(logRecord.getAttributesList())
-                    .containsExactlyInAnyOrder(
-                        KeyValue.newBuilder()
-                            .setKey("event.domain")
-                            .setValue(AnyValue.newBuilder().setStringValue("test-domain").build())
-                            .build(),
-                        KeyValue.newBuilder()
-                            .setKey("event.name")
-                            .setValue(AnyValue.newBuilder().setStringValue("test-name").build())
-                            .build(),
-                        KeyValue.newBuilder()
-                            .setKey("cow")
-                            .setValue(AnyValue.newBuilder().setStringValue("moo").build())
-                            .build()));
+            logRecord -> {
+              // TODO: update after merging
+              // https://github.com/open-telemetry/opentelemetry-java/pull/5938
+              assertThat(logRecord.getBody().getStringValue()).isEqualTo("[cow=moo]");
+              assertThat(logRecord.getSeverityNumber())
+                  .isEqualTo(SeverityNumber.SEVERITY_NUMBER_INFO);
+              assertThat(logRecord.getAttributesList())
+                  .containsExactlyInAnyOrder(
+                      KeyValue.newBuilder()
+                          .setKey("event.name")
+                          .setValue(
+                              AnyValue.newBuilder().setStringValue("namespace.test-name").build())
+                          .build());
+            });
   }
 
   private static List getFirstDataPointLabels(Metric metric) {
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilder.java
index a79b09babc3..d52cf6a39d0 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilder.java
@@ -5,37 +5,75 @@
 
 package io.opentelemetry.sdk.logs.internal;
 
+import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.events.EventBuilder;
 import io.opentelemetry.api.logs.LogRecordBuilder;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.extension.incubator.logs.AnyValue;
+import io.opentelemetry.extension.incubator.logs.ExtendedLogRecordBuilder;
+import io.opentelemetry.sdk.common.Clock;
 import java.time.Instant;
 import java.util.concurrent.TimeUnit;
 
 class SdkEventBuilder implements EventBuilder {
+  private final Clock clock;
   private final LogRecordBuilder logRecordBuilder;
-  private final String eventDomain;
   private final String eventName;
+  private boolean hasTimestamp = false;
 
-  SdkEventBuilder(LogRecordBuilder logRecordBuilder, String eventDomain, String eventName) {
+  SdkEventBuilder(Clock clock, LogRecordBuilder logRecordBuilder, String eventName) {
+    this.clock = clock;
     this.logRecordBuilder = logRecordBuilder;
-    this.eventDomain = eventDomain;
     this.eventName = eventName;
   }
 
+  @Override
+  public EventBuilder setPayload(AnyValue payload) {
+    ((ExtendedLogRecordBuilder) logRecordBuilder).setBody(payload);
+    return this;
+  }
+
   @Override
   public EventBuilder setTimestamp(long timestamp, TimeUnit unit) {
     this.logRecordBuilder.setTimestamp(timestamp, unit);
+    this.hasTimestamp = true;
     return this;
   }
 
   @Override
   public EventBuilder setTimestamp(Instant instant) {
     this.logRecordBuilder.setTimestamp(instant);
+    this.hasTimestamp = true;
+    return this;
+  }
+
+  @Override
+  public EventBuilder setContext(Context context) {
+    logRecordBuilder.setContext(context);
+    return this;
+  }
+
+  @Override
+  public EventBuilder setSeverity(Severity severity) {
+    logRecordBuilder.setSeverity(severity);
+    return this;
+  }
+
+  @Override
+  public EventBuilder setAttributes(Attributes attributes) {
+    logRecordBuilder.setAllAttributes(attributes);
     return this;
   }
 
   @Override
   public void emit() {
-    SdkEventEmitterProvider.addEventNameAndDomain(logRecordBuilder, eventDomain, eventName);
+    long now = clock.now();
+    logRecordBuilder.setObservedTimestamp(now, TimeUnit.NANOSECONDS);
+    if (!hasTimestamp) {
+      logRecordBuilder.setTimestamp(now, TimeUnit.NANOSECONDS);
+    }
+    SdkEventEmitterProvider.addEventName(logRecordBuilder, eventName);
     logRecordBuilder.emit();
   }
 }
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java
index 1cc6768667e..925e5951933 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java
@@ -6,7 +6,6 @@
 package io.opentelemetry.sdk.logs.internal;
 
 import io.opentelemetry.api.common.AttributeKey;
-import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.events.EventBuilder;
 import io.opentelemetry.api.events.EventEmitter;
 import io.opentelemetry.api.events.EventEmitterBuilder;
@@ -15,6 +14,10 @@
 import io.opentelemetry.api.logs.Logger;
 import io.opentelemetry.api.logs.LoggerBuilder;
 import io.opentelemetry.api.logs.LoggerProvider;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.extension.incubator.logs.AnyValue;
+import io.opentelemetry.extension.incubator.logs.ExtendedLogRecordBuilder;
 import io.opentelemetry.sdk.common.Clock;
 import java.util.concurrent.TimeUnit;
 
@@ -26,11 +29,8 @@
  */
 public final class SdkEventEmitterProvider implements EventEmitterProvider {
 
-  static final AttributeKey EVENT_DOMAIN = AttributeKey.stringKey("event.domain");
   static final AttributeKey EVENT_NAME = AttributeKey.stringKey("event.name");
 
-  static final String DEFAULT_EVENT_DOMAIN = "unknown";
-
   private final LoggerProvider delegateLoggerProvider;
   private final Clock clock;
 
@@ -53,13 +53,6 @@ public static SdkEventEmitterProvider create(LoggerProvider delegateLoggerProvid
     return new SdkEventEmitterProvider(delegateLoggerProvider, clock);
   }
 
-  @Override
-  public EventEmitter get(String instrumentationScopeName) {
-    return eventEmitterBuilder(instrumentationScopeName)
-        .setEventDomain(DEFAULT_EVENT_DOMAIN)
-        .build();
-  }
-
   @Override
   public EventEmitterBuilder eventEmitterBuilder(String instrumentationScopeName) {
     return new SdkEventEmitterBuilder(
@@ -70,19 +63,12 @@ private static class SdkEventEmitterBuilder implements EventEmitterBuilder {
 
     private final Clock clock;
     private final LoggerBuilder delegateLoggerBuilder;
-    private String eventDomain = DEFAULT_EVENT_DOMAIN;
 
     private SdkEventEmitterBuilder(Clock clock, LoggerBuilder delegateLoggerBuilder) {
       this.clock = clock;
       this.delegateLoggerBuilder = delegateLoggerBuilder;
     }
 
-    @Override
-    public EventEmitterBuilder setEventDomain(String eventDomain) {
-      this.eventDomain = eventDomain;
-      return this;
-    }
-
     @Override
     public EventEmitterBuilder setSchemaUrl(String schemaUrl) {
       delegateLoggerBuilder.setSchemaUrl(schemaUrl);
@@ -97,7 +83,7 @@ public EventEmitterBuilder setInstrumentationVersion(String instrumentationScope
 
     @Override
     public EventEmitter build() {
-      return new SdkEventEmitter(clock, delegateLoggerBuilder.build(), eventDomain);
+      return new SdkEventEmitter(clock, delegateLoggerBuilder.build());
     }
   }
 
@@ -105,39 +91,39 @@ private static class SdkEventEmitter implements EventEmitter {
 
     private final Clock clock;
     private final Logger delegateLogger;
-    private final String eventDomain;
 
-    private SdkEventEmitter(Clock clock, Logger delegateLogger, String eventDomain) {
+    private SdkEventEmitter(Clock clock, Logger delegateLogger) {
       this.clock = clock;
       this.delegateLogger = delegateLogger;
-      this.eventDomain = eventDomain;
     }
 
     @Override
-    public EventBuilder builder(String eventName, Attributes attributes) {
+    public EventBuilder builder(String eventName) {
       return new SdkEventBuilder(
+          clock,
           delegateLogger
               .logRecordBuilder()
-              .setTimestamp(clock.now(), TimeUnit.NANOSECONDS)
-              .setAllAttributes(attributes),
-          eventDomain,
+              .setSeverity(Severity.INFO)
+              .setContext(Context.current()),
           eventName);
     }
 
     @Override
-    public void emit(String eventName, Attributes attributes) {
+    public void emit(String eventName, AnyValue payload) {
+      long now = clock.now();
       LogRecordBuilder logRecordBuilder =
-          delegateLogger
-              .logRecordBuilder()
-              .setTimestamp(clock.now(), TimeUnit.NANOSECONDS)
-              .setAllAttributes(attributes);
-      addEventNameAndDomain(logRecordBuilder, eventDomain, eventName);
+          ((ExtendedLogRecordBuilder) delegateLogger.logRecordBuilder())
+              .setBody(payload)
+              .setSeverity(Severity.INFO)
+              .setContext(Context.current())
+              .setTimestamp(now, TimeUnit.NANOSECONDS)
+              .setObservedTimestamp(now, TimeUnit.NANOSECONDS);
+      addEventName(logRecordBuilder, eventName);
       logRecordBuilder.emit();
     }
   }
 
-  static void addEventNameAndDomain(
-      LogRecordBuilder logRecordBuilder, String eventDomain, String eventName) {
-    logRecordBuilder.setAttribute(EVENT_DOMAIN, eventDomain).setAttribute(EVENT_NAME, eventName);
+  static void addEventName(LogRecordBuilder logRecordBuilder, String eventName) {
+    logRecordBuilder.setAttribute(EVENT_NAME, eventName);
   }
 }
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilderTest.java
index 2115463a771..a3a76d094d5 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventBuilderTest.java
@@ -12,7 +12,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.logs.LogRecordBuilder;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.sdk.common.Clock;
 import java.time.Instant;
 import java.util.concurrent.TimeUnit;
 import org.junit.jupiter.api.Test;
@@ -21,22 +25,31 @@ class SdkEventBuilderTest {
 
   @Test
   void emit() {
-    String eventDomain = "mydomain";
-    String eventName = "banana";
+    String eventName = "namespace.banana";
 
     LogRecordBuilder logRecordBuilder = mock(LogRecordBuilder.class);
     when(logRecordBuilder.setTimestamp(anyLong(), any())).thenReturn(logRecordBuilder);
     when(logRecordBuilder.setAttribute(any(), any())).thenReturn(logRecordBuilder);
+    when(logRecordBuilder.setContext(any())).thenReturn(logRecordBuilder);
+    when(logRecordBuilder.setSeverity(any())).thenReturn(logRecordBuilder);
+    when(logRecordBuilder.setAllAttributes(any())).thenReturn(logRecordBuilder);
 
     Instant instant = Instant.now();
-    new SdkEventBuilder(logRecordBuilder, eventDomain, eventName)
+    Context context = Context.root();
+    Attributes attributes = Attributes.builder().put("extra-attribute", "value").build();
+    new SdkEventBuilder(Clock.getDefault(), logRecordBuilder, eventName)
         .setTimestamp(123456L, TimeUnit.NANOSECONDS)
         .setTimestamp(instant)
+        .setContext(context)
+        .setSeverity(Severity.DEBUG)
+        .setAttributes(attributes)
         .emit();
-    verify(logRecordBuilder).setAttribute(stringKey("event.domain"), eventDomain);
     verify(logRecordBuilder).setAttribute(stringKey("event.name"), eventName);
     verify(logRecordBuilder).setTimestamp(123456L, TimeUnit.NANOSECONDS);
     verify(logRecordBuilder).setTimestamp(instant);
+    verify(logRecordBuilder).setContext(context);
+    verify(logRecordBuilder).setSeverity(Severity.DEBUG);
+    verify(logRecordBuilder).setAllAttributes(attributes);
     verify(logRecordBuilder).emit();
   }
 }
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java
index 7f22b1376a8..ec1dfbd03a8 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java
@@ -5,18 +5,20 @@
 
 package io.opentelemetry.sdk.logs.internal;
 
-import static io.opentelemetry.api.common.AttributeKey.stringKey;
 import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.events.EventEmitter;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.extension.incubator.logs.AnyValue;
 import io.opentelemetry.sdk.common.Clock;
 import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
 import io.opentelemetry.sdk.logs.ReadWriteLogRecord;
 import io.opentelemetry.sdk.logs.SdkLoggerProvider;
 import io.opentelemetry.sdk.resources.Resource;
+import java.util.Collections;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import org.junit.jupiter.api.Test;
@@ -37,84 +39,55 @@ class SdkEventEmitterProviderTest {
           clock);
 
   @Test
-  void emit_WithDomain() {
+  void emit() {
     when(clock.now()).thenReturn(10L);
 
-    eventEmitterProvider
-        .eventEmitterBuilder("test-scope")
-        .setEventDomain("event-domain")
-        .build()
-        .emit(
-            "event-name",
-            Attributes.builder()
-                .put("key1", "value1")
-                // should be overridden by the eventName argument passed to emit
-                .put("event.name", "foo")
-                // should be overridden by the eventDomain
-                .put("event.domain", "foo")
-                .build());
-
-    assertThat(seenLog.get().toLogRecordData())
-        .hasResource(RESOURCE)
-        .hasInstrumentationScope(InstrumentationScopeInfo.create("test-scope"))
-        .hasTimestamp(10L)
-        .hasAttributes(
-            Attributes.builder()
-                .put("key1", "value1")
-                .put("event.domain", "event-domain")
-                .put("event.name", "event-name")
-                .build());
-  }
-
-  @Test
-  void emit_NoDomain() {
-    when(clock.now()).thenReturn(10L);
+    AnyValue payload = AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1")));
 
     eventEmitterProvider
         .eventEmitterBuilder("test-scope")
         .build()
-        .emit(
-            "event-name",
-            Attributes.builder()
-                .put("key1", "value1")
-                // should be overridden by the eventName argument passed to emit
-                .put("event.name", "foo")
-                // should be overridden by the default eventDomain
-                .put("event.domain", "foo")
-                .build());
+        .emit("namespace.event-name", payload);
 
     assertThat(seenLog.get().toLogRecordData())
         .hasResource(RESOURCE)
         .hasInstrumentationScope(InstrumentationScopeInfo.create("test-scope"))
         .hasTimestamp(10L)
-        .hasAttributes(
-            Attributes.builder()
-                .put("key1", "value1")
-                .put("event.domain", "unknown")
-                .put("event.name", "event-name")
-                .build());
+        .hasObservedTimestamp(10L)
+        .hasSeverity(Severity.INFO)
+        .hasAttributes(Attributes.builder().put("event.name", "namespace.event-name").build());
+    assertThat(((AnyValueBody) seenLog.get().toLogRecordData().getBody()).asAnyValue())
+        .isEqualTo(payload);
   }
 
   @Test
   void builder() {
-    long yesterday = System.nanoTime() - TimeUnit.DAYS.toNanos(1);
-    Attributes attributes = Attributes.of(stringKey("foo"), "bar");
+    when(clock.now()).thenReturn(10L);
 
+    long yesterday = System.nanoTime() - TimeUnit.DAYS.toNanos(1);
     EventEmitter emitter = eventEmitterProvider.eventEmitterBuilder("test-scope").build();
 
-    emitter.builder("testing", attributes).setTimestamp(yesterday, TimeUnit.NANOSECONDS).emit();
-    verifySeen(yesterday, attributes);
-  }
+    AnyValue payload = AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1")));
+    emitter
+        .builder("namespace.event-name")
+        .setPayload(payload)
+        .setTimestamp(yesterday, TimeUnit.NANOSECONDS)
+        .setSeverity(Severity.DEBUG)
+        .setAttributes(Attributes.builder().put("extra-attribute", "value").build())
+        .emit();
 
-  private void verifySeen(long timestamp, Attributes attributes) {
     assertThat(seenLog.get().toLogRecordData())
         .hasResource(RESOURCE)
         .hasInstrumentationScope(InstrumentationScopeInfo.create("test-scope"))
-        .hasTimestamp(timestamp)
+        .hasTimestamp(yesterday)
+        .hasObservedTimestamp(10L)
+        .hasSeverity(Severity.DEBUG)
         .hasAttributes(
-            attributes.toBuilder()
-                .put("event.domain", "unknown")
-                .put("event.name", "testing")
+            Attributes.builder()
+                .put("event.name", "namespace.event-name")
+                .put("extra-attribute", "value")
                 .build());
+    assertThat(((AnyValueBody) seenLog.get().toLogRecordData().getBody()).asAnyValue())
+        .isEqualTo(payload);
   }
 }

From e1459c6e6df177632665dfaa9fab55e69b86aa6a Mon Sep 17 00:00:00 2001
From: Jack Berg 
Date: Fri, 1 Dec 2023 15:28:11 -0600
Subject: [PATCH 2/3] Add Map> payload helper overload

---
 .../io/opentelemetry/api/events/EventBuilder.java   | 11 +++++++++++
 .../io/opentelemetry/api/events/EventEmitter.java   | 13 +++++++++++++
 .../api/events/DefaultEventEmitterProviderTest.java |  2 +-
 .../api/events/DefaultEventEmitterTest.java         | 12 ++++++++++--
 .../OtlpExporterIntegrationTest.java                |  5 ++---
 5 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java b/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java
index be79729f8ce..ba7cddd9ce9 100644
--- a/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java
+++ b/api/events/src/main/java/io/opentelemetry/api/events/EventBuilder.java
@@ -10,6 +10,7 @@
 import io.opentelemetry.context.Context;
 import io.opentelemetry.extension.incubator.logs.AnyValue;
 import java.time.Instant;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 /** The EventBuilder is used to {@link #emit()} events. */
@@ -23,6 +24,16 @@ public interface EventBuilder {
    */
   EventBuilder setPayload(AnyValue payload);
 
+  /**
+   * Set the {@code payload}.
+   *
+   * 

The {@code payload} is expected to match the schema of other events with the same {@code + * eventName}. + */ + default EventBuilder setPayload(Map> payload) { + return setPayload(AnyValue.of(payload)); + } + /** * Set the epoch {@code timestamp}, using the timestamp and unit. * diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java index e7bddeda41f..4d56c0dbb72 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java @@ -6,6 +6,7 @@ package io.opentelemetry.api.events; import io.opentelemetry.extension.incubator.logs.AnyValue; +import java.util.Map; import javax.annotation.concurrent.ThreadSafe; /** @@ -42,6 +43,18 @@ public interface EventEmitter { */ void emit(String eventName, AnyValue payload); + /** + * Emit an event. + * + * @param eventName the event name, which defines the class or type of event. Events names SHOULD + * include a namespace to avoid collisions with other event names. + * @param payload the eventPayload, which is expected to match the schema of other events with the + * same {@code eventName}. + */ + default void emit(String eventName, Map> payload) { + emit(eventName, AnyValue.of(payload)); + } + /** * Return a {@link EventBuilder} to emit an event. * diff --git a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java index 6f0a83f49cb..ea0d51daaef 100644 --- a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java +++ b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterProviderTest.java @@ -33,7 +33,7 @@ void noopEventEmitterProvider_doesNotThrow() { provider .eventEmitterBuilder("scope-name") .build() - .emit("namespace.event-name", AnyValue.of(""))) + .emit("namespace.event-name", AnyValue.of("payload"))) .doesNotThrowAnyException(); } } diff --git a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java index 429c26b031f..82fe2fe18dd 100644 --- a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java +++ b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java @@ -27,6 +27,14 @@ void emit() { "namespace.event-name", AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1"))))) .doesNotThrowAnyException(); + + assertThatCode( + () -> + DefaultEventEmitter.getInstance() + .emit( + "namespace.event-name", + Collections.singletonMap("key1", AnyValue.of("value1")))) + .doesNotThrowAnyException(); } @Test @@ -36,8 +44,8 @@ void builder() { () -> emitter .builder("namespace.myEvent") - .setPayload( - AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1")))) + .setPayload(AnyValue.of("payload")) + .setPayload(Collections.singletonMap("key1", AnyValue.of("value1"))) .setTimestamp(123456L, TimeUnit.NANOSECONDS) .setTimestamp(Instant.now()) .setContext(Context.current()) diff --git a/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java index 05d2e0c2a2d..b07c4242bf0 100644 --- a/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java +++ b/integration-tests/otlp/src/main/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java @@ -549,9 +549,8 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) { .emit(); eventEmitter.emit( "namespace.event-name", - io.opentelemetry.extension.incubator.logs.AnyValue.of( - Collections.singletonMap( - "key", io.opentelemetry.extension.incubator.logs.AnyValue.of("value")))); + Collections.singletonMap( + "key", io.opentelemetry.extension.incubator.logs.AnyValue.of("value"))); } // Closing triggers flush of processor From ed9376381eb426f504fb31a01e5f45976dbc245d Mon Sep 17 00:00:00 2001 From: Jack Berg Date: Mon, 4 Dec 2023 09:46:47 -0600 Subject: [PATCH 3/3] Add emit overload with no payload --- .../api/events/DefaultEventEmitter.java | 3 ++ .../api/events/EventEmitter.java | 11 +++++++ .../api/events/DefaultEventEmitterTest.java | 3 ++ .../internal/SdkEventEmitterProvider.java | 31 ++++++++++++++----- .../internal/SdkEventEmitterProviderTest.java | 19 +++++++++++- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java index 6525e6bb8f8..1cadacda8f7 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/DefaultEventEmitter.java @@ -22,6 +22,9 @@ static EventEmitter getInstance() { return INSTANCE; } + @Override + public void emit(String eventName) {} + @Override public void emit(String eventName, AnyValue payload) {} diff --git a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java index 4d56c0dbb72..292aebdde4d 100644 --- a/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java +++ b/api/events/src/main/java/io/opentelemetry/api/events/EventEmitter.java @@ -33,6 +33,14 @@ @ThreadSafe public interface EventEmitter { + /** + * Emit an event. + * + * @param eventName the event name, which defines the class or type of event. Events names SHOULD + * include a namespace to avoid collisions with other event names. + */ + void emit(String eventName); + /** * Emit an event. * @@ -46,6 +54,9 @@ public interface EventEmitter { /** * Emit an event. * + *

This is equivalent to calling {@link #emit(String, AnyValue)} with a {@link + * AnyValue#of(Map)} payload. + * * @param eventName the event name, which defines the class or type of event. Events names SHOULD * include a namespace to avoid collisions with other event names. * @param payload the eventPayload, which is expected to match the schema of other events with the diff --git a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java index 82fe2fe18dd..f7c8e041e74 100644 --- a/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java +++ b/api/events/src/test/java/io/opentelemetry/api/events/DefaultEventEmitterTest.java @@ -20,6 +20,9 @@ class DefaultEventEmitterTest { @Test void emit() { + assertThatCode(() -> DefaultEventEmitter.getInstance().emit("namespace.event-name")) + .doesNotThrowAnyException(); + assertThatCode( () -> DefaultEventEmitter.getInstance() diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java index 925e5951933..d095f2397aa 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProvider.java @@ -20,6 +20,7 @@ import io.opentelemetry.extension.incubator.logs.ExtendedLogRecordBuilder; import io.opentelemetry.sdk.common.Clock; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; /** * SDK implementation for {@link EventEmitterProvider}. @@ -89,6 +90,8 @@ public EventEmitter build() { private static class SdkEventEmitter implements EventEmitter { + private static final Severity DEFAULT_SEVERITY = Severity.INFO; + private final Clock clock; private final Logger delegateLogger; @@ -103,21 +106,33 @@ public EventBuilder builder(String eventName) { clock, delegateLogger .logRecordBuilder() - .setSeverity(Severity.INFO) + .setSeverity(DEFAULT_SEVERITY) .setContext(Context.current()), eventName); } + @Override + public void emit(String eventName) { + emitInternal(eventName, null); + } + @Override public void emit(String eventName, AnyValue payload) { + emitInternal(eventName, payload); + } + + private void emitInternal(String eventName, @Nullable AnyValue payload) { long now = clock.now(); - LogRecordBuilder logRecordBuilder = - ((ExtendedLogRecordBuilder) delegateLogger.logRecordBuilder()) - .setBody(payload) - .setSeverity(Severity.INFO) - .setContext(Context.current()) - .setTimestamp(now, TimeUnit.NANOSECONDS) - .setObservedTimestamp(now, TimeUnit.NANOSECONDS); + ExtendedLogRecordBuilder logRecordBuilder = + ((ExtendedLogRecordBuilder) delegateLogger.logRecordBuilder()); + if (payload != null) { + logRecordBuilder.setBody(payload); + } + logRecordBuilder + .setSeverity(DEFAULT_SEVERITY) + .setContext(Context.current()) + .setTimestamp(now, TimeUnit.NANOSECONDS) + .setObservedTimestamp(now, TimeUnit.NANOSECONDS); addEventName(logRecordBuilder, eventName); logRecordBuilder.emit(); } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java index ec1dfbd03a8..53ba2cbbedd 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/internal/SdkEventEmitterProviderTest.java @@ -17,6 +17,7 @@ import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.logs.ReadWriteLogRecord; import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.resources.Resource; import java.util.Collections; import java.util.concurrent.TimeUnit; @@ -39,7 +40,23 @@ class SdkEventEmitterProviderTest { clock); @Test - void emit() { + void emit_NoPayload() { + when(clock.now()).thenReturn(10L); + + eventEmitterProvider.eventEmitterBuilder("test-scope").build().emit("namespace.event-name"); + + assertThat(seenLog.get().toLogRecordData()) + .hasResource(RESOURCE) + .hasInstrumentationScope(InstrumentationScopeInfo.create("test-scope")) + .hasTimestamp(10L) + .hasObservedTimestamp(10L) + .hasSeverity(Severity.INFO) + .hasAttributes(Attributes.builder().put("event.name", "namespace.event-name").build()); + assertThat(seenLog.get().toLogRecordData().getBody()).isEqualTo(Body.empty()); + } + + @Test + void emit_WithPayload() { when(clock.now()).thenReturn(10L); AnyValue payload = AnyValue.of(Collections.singletonMap("key1", AnyValue.of("value1")));