Skip to content

Commit

Permalink
Refactor Event API to reflect spec changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-berg committed Nov 20, 2023
1 parent c87852c commit 75c13bb
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 171 deletions.
1 change: 1 addition & 0 deletions api/events/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ otelJava.moduleName.set("io.opentelemetry.api.events")

dependencies {
api(project(":api:all"))
api(project(":extensions:incubator"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -20,17 +23,22 @@ 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;
}

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;
Expand All @@ -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() {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,54 @@

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;

/** The EventBuilder is used to {@link #emit()} events. */
public interface EventBuilder {

/**
* Set the epoch {@code timestamp} for the event, using the timestamp and unit.
* Set the {@code payload}.
*
* <p>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.
*
* <p>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(long timestamp, TimeUnit unit);

/**
* Set the epoch {@code timestamp} for the event, using the instant.
* Set the epoch {@code timestamp}t, using the instant.
*
* <p>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.
*
* <p>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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@

package io.opentelemetry.api.events;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.extension.incubator.logs.AnyValue;
import javax.annotation.concurrent.ThreadSafe;

/**
* A {@link EventEmitter} is the entry point into an event pipeline.
*
* <p>Example usage emitting events:
*
* <p>// TODO: rework
*
* <pre>{@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
* }
* }
Expand All @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -23,7 +23,6 @@ void noopEventEmitterProvider_doesNotThrow() {
() ->
provider
.eventEmitterBuilder("scope-name")
.setEventDomain("event-domain")
.setInstrumentationVersion("1.0")
.setSchemaUrl("http://schema.com")
.build())
Expand All @@ -34,7 +33,7 @@ void noopEventEmitterProvider_doesNotThrow() {
provider
.eventEmitterBuilder("scope-name")
.build()
.emit("event-name", Attributes.empty()))
.emit("namespace.event-name", AnyValue.of("")))
.doesNotThrowAnyException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,41 @@
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;

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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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
Expand Down Expand Up @@ -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()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<KeyValue> getFirstDataPointLabels(Metric metric) {
Expand Down
Loading

0 comments on commit 75c13bb

Please sign in to comment.