diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
index 3e8dce08e74..378af1c6b00 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedDefaultLogger.java
@@ -17,7 +17,8 @@
class ExtendedDefaultLogger implements ExtendedLogger {
private static final Logger INSTANCE = new ExtendedDefaultLogger();
- private static final LogRecordBuilder NOOP_LOG_RECORD_BUILDER = new NoopLogRecordBuilder();
+ private static final ExtendedLogRecordBuilder NOOP_LOG_RECORD_BUILDER =
+ new NoopExtendedLogRecordBuilder();
private ExtendedDefaultLogger() {}
@@ -26,13 +27,18 @@ static Logger getNoop() {
}
@Override
- public LogRecordBuilder logRecordBuilder() {
+ public ExtendedLogRecordBuilder logRecordBuilder() {
return NOOP_LOG_RECORD_BUILDER;
}
- private static final class NoopLogRecordBuilder implements ExtendedLogRecordBuilder {
+ private static final class NoopExtendedLogRecordBuilder implements ExtendedLogRecordBuilder {
- private NoopLogRecordBuilder() {}
+ private NoopExtendedLogRecordBuilder() {}
+
+ @Override
+ public ExtendedLogRecordBuilder setEventName(String eventName) {
+ return this;
+ }
@Override
public LogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) {
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogRecordBuilder.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogRecordBuilder.java
index 4e8af8eee70..4a18baa07ed 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogRecordBuilder.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogRecordBuilder.java
@@ -10,6 +10,13 @@
/** Extended {@link LogRecordBuilder} with experimental APIs. */
public interface ExtendedLogRecordBuilder extends LogRecordBuilder {
- // Nothing at the moment, but experimental methods may be added in the future.
+ // keep this class even if it is empty, since experimental methods may be added in the future.
+ /**
+ * Sets the event name, which identifies the class / type of the Event.
+ *
+ *
This name should uniquely identify the event structure (both attributes and body). A log
+ * record with a non-empty event name is an Event.
+ */
+ ExtendedLogRecordBuilder setEventName(String eventName);
}
diff --git a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
index db5e2a3b029..de159406c0e 100644
--- a/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
+++ b/api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogger.java
@@ -20,4 +20,7 @@ public interface ExtendedLogger extends Logger {
default boolean isEnabled() {
return true;
}
+
+ @Override
+ ExtendedLogRecordBuilder logRecordBuilder();
}
diff --git a/api/testing-internal/src/main/java/io/opentelemetry/api/testing/internal/AbstractDefaultLoggerTest.java b/api/testing-internal/src/main/java/io/opentelemetry/api/testing/internal/AbstractDefaultLoggerTest.java
index 82d9f0b1f67..4b38e6fab19 100644
--- a/api/testing-internal/src/main/java/io/opentelemetry/api/testing/internal/AbstractDefaultLoggerTest.java
+++ b/api/testing-internal/src/main/java/io/opentelemetry/api/testing/internal/AbstractDefaultLoggerTest.java
@@ -51,6 +51,8 @@ void buildAndEmit() {
() ->
getLogger()
.logRecordBuilder()
+ // TODO (trask) once event name stabilizes
+ // .setEventName("event name")
.setTimestamp(100, TimeUnit.SECONDS)
.setTimestamp(Instant.now())
.setObservedTimestamp(100, TimeUnit.SECONDS)
diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/TestDataExporter.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/TestDataExporter.java
index 54032fca3e0..63040a9beb1 100644
--- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/TestDataExporter.java
+++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/TestDataExporter.java
@@ -28,6 +28,7 @@
import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.logs.TestLogRecordData;
+import io.opentelemetry.sdk.testing.logs.internal.TestExtendedLogRecordData;
import io.opentelemetry.sdk.testing.trace.TestSpanData;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.SpanData;
@@ -47,13 +48,14 @@ abstract class TestDataExporter {
Resource.create(Attributes.builder().put("key", "value").build());
private static final LogRecordData LOG1 =
- TestLogRecordData.builder()
+ TestExtendedLogRecordData.builder()
.setResource(RESOURCE)
.setInstrumentationScopeInfo(
InstrumentationScopeInfo.builder("instrumentation")
.setVersion("1")
.setAttributes(Attributes.builder().put("key", "value").build())
.build())
+ .setEventName("event name")
.setBody("body1")
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
diff --git a/exporters/logging-otlp/src/test/resources/expected-logs-wrapper.json b/exporters/logging-otlp/src/test/resources/expected-logs-wrapper.json
index 887fdb13d4b..c298d824182 100644
--- a/exporters/logging-otlp/src/test/resources/expected-logs-wrapper.json
+++ b/exporters/logging-otlp/src/test/resources/expected-logs-wrapper.json
@@ -27,6 +27,7 @@
},
"logRecords": [
{
+ "eventName": "event name",
"timeUnixNano": "100",
"observedTimeUnixNano": "200",
"severityNumber": 9,
diff --git a/exporters/logging-otlp/src/test/resources/expected-logs.json b/exporters/logging-otlp/src/test/resources/expected-logs.json
index fe84d67c4ef..6eae7f28ad3 100644
--- a/exporters/logging-otlp/src/test/resources/expected-logs.json
+++ b/exporters/logging-otlp/src/test/resources/expected-logs.json
@@ -25,6 +25,7 @@
},
"logRecords": [
{
+ "eventName": "event name",
"timeUnixNano": "100",
"observedTimeUnixNano": "200",
"severityNumber": 9,
diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogMarshaler.java
index 530e38dbe05..0ad265e9655 100644
--- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogMarshaler.java
+++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogMarshaler.java
@@ -19,12 +19,14 @@
import io.opentelemetry.proto.logs.v1.internal.LogRecord;
import io.opentelemetry.proto.logs.v1.internal.SeverityNumber;
import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.data.internal.ExtendedLogRecordData;
import java.io.IOException;
import javax.annotation.Nullable;
final class LogMarshaler extends MarshalerWithSize {
private static final String INVALID_TRACE_ID = TraceId.getInvalid();
private static final String INVALID_SPAN_ID = SpanId.getInvalid();
+ private static final byte[] EMPTY_BYTES = new byte[0];
private final long timeUnixNano;
private final long observedTimeUnixNano;
@@ -36,6 +38,7 @@ final class LogMarshaler extends MarshalerWithSize {
private final TraceFlags traceFlags;
@Nullable private final String traceId;
@Nullable private final String spanId;
+ private final byte[] eventName;
static LogMarshaler create(LogRecordData logRecordData) {
KeyValueMarshaler[] attributeMarshalers =
@@ -57,7 +60,10 @@ static LogMarshaler create(LogRecordData logRecordData) {
logRecordData.getTotalAttributeCount() - logRecordData.getAttributes().size(),
spanContext.getTraceFlags(),
spanContext.getTraceId().equals(INVALID_TRACE_ID) ? null : spanContext.getTraceId(),
- spanContext.getSpanId().equals(INVALID_SPAN_ID) ? null : spanContext.getSpanId());
+ spanContext.getSpanId().equals(INVALID_SPAN_ID) ? null : spanContext.getSpanId(),
+ logRecordData instanceof ExtendedLogRecordData
+ ? MarshalerUtil.toBytes(((ExtendedLogRecordData) logRecordData).getEventName())
+ : EMPTY_BYTES);
}
private LogMarshaler(
@@ -70,7 +76,8 @@ private LogMarshaler(
int droppedAttributesCount,
TraceFlags traceFlags,
@Nullable String traceId,
- @Nullable String spanId) {
+ @Nullable String spanId,
+ byte[] eventName) {
super(
calculateSize(
timeUnixNano,
@@ -82,7 +89,8 @@ private LogMarshaler(
droppedAttributesCount,
traceFlags,
traceId,
- spanId));
+ spanId,
+ eventName));
this.timeUnixNano = timeUnixNano;
this.observedTimeUnixNano = observedTimeUnixNano;
this.traceId = traceId;
@@ -93,6 +101,7 @@ private LogMarshaler(
this.anyValueMarshaler = anyValueMarshaler;
this.attributeMarshalers = attributeMarshalers;
this.droppedAttributesCount = droppedAttributesCount;
+ this.eventName = eventName;
}
@Override
@@ -115,6 +124,8 @@ protected void writeTo(Serializer output) throws IOException {
output.serializeByteAsFixed32(LogRecord.FLAGS, traceFlags.asByte());
output.serializeTraceId(LogRecord.TRACE_ID, traceId);
output.serializeSpanId(LogRecord.SPAN_ID, spanId);
+
+ output.serializeString(LogRecord.EVENT_NAME, eventName);
}
private static int calculateSize(
@@ -127,7 +138,8 @@ private static int calculateSize(
int droppedAttributesCount,
TraceFlags traceFlags,
@Nullable String traceId,
- @Nullable String spanId) {
+ @Nullable String spanId,
+ byte[] eventName) {
int size = 0;
size += MarshalerUtil.sizeFixed64(LogRecord.TIME_UNIX_NANO, timeUnixNano);
@@ -147,6 +159,8 @@ private static int calculateSize(
size += MarshalerUtil.sizeByteAsFixed32(LogRecord.FLAGS, traceFlags.asByte());
size += MarshalerUtil.sizeTraceId(LogRecord.TRACE_ID, traceId);
size += MarshalerUtil.sizeSpanId(LogRecord.SPAN_ID, spanId);
+
+ size += MarshalerUtil.sizeBytes(LogRecord.EVENT_NAME, eventName);
return size;
}
diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java
index 1f16ebbe41c..1477af88ce6 100644
--- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java
+++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java
@@ -19,6 +19,7 @@
import io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler;
import io.opentelemetry.proto.logs.v1.internal.LogRecord;
import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.data.internal.ExtendedLogRecordData;
import java.io.IOException;
/** See {@link LogMarshaler}. */
@@ -55,6 +56,10 @@ public void writeTo(Serializer output, LogRecordData log, MarshalerContext conte
if (!spanContext.getSpanId().equals(INVALID_SPAN_ID)) {
output.serializeSpanId(LogRecord.SPAN_ID, spanContext.getSpanId(), context);
}
+ if (log instanceof ExtendedLogRecordData) {
+ output.serializeStringWithContext(
+ LogRecord.EVENT_NAME, ((ExtendedLogRecordData) log).getEventName(), context);
+ }
}
@Override
@@ -93,6 +98,12 @@ public int getBinarySerializedSize(LogRecordData log, MarshalerContext context)
size += MarshalerUtil.sizeSpanId(LogRecord.SPAN_ID, spanContext.getSpanId());
}
+ if (log instanceof ExtendedLogRecordData) {
+ size +=
+ StatelessMarshalerUtil.sizeStringWithContext(
+ LogRecord.EVENT_NAME, ((ExtendedLogRecordData) log).getEventName(), context);
+ }
+
return size;
}
}
diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LogsRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LogsRequestMarshalerTest.java
index 9c01ddc7aed..0e54a10f0e2 100644
--- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LogsRequestMarshalerTest.java
+++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LogsRequestMarshalerTest.java
@@ -33,7 +33,7 @@
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.resources.Resource;
-import io.opentelemetry.sdk.testing.logs.TestLogRecordData;
+import io.opentelemetry.sdk.testing.logs.internal.TestExtendedLogRecordData;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -52,6 +52,7 @@ class LogsRequestMarshalerTest {
private static final String TRACE_ID = TraceId.fromBytes(TRACE_ID_BYTES);
private static final byte[] SPAN_ID_BYTES = new byte[] {0, 0, 0, 0, 4, 3, 2, 1};
private static final String SPAN_ID = SpanId.fromBytes(SPAN_ID_BYTES);
+ private static final String EVENT_NAME = "hello";
private static final String BODY = "Hello world from this log...";
@Test
@@ -59,7 +60,7 @@ void toProtoResourceLogs() {
ResourceLogsMarshaler[] resourceLogsMarshalers =
ResourceLogsMarshaler.create(
Collections.singleton(
- TestLogRecordData.builder()
+ TestExtendedLogRecordData.builder()
.setResource(
Resource.builder().put("one", 1).setSchemaUrl("http://url").build())
.setInstrumentationScopeInfo(
@@ -68,6 +69,7 @@ void toProtoResourceLogs() {
.setSchemaUrl("http://url")
.setAttributes(Attributes.builder().put("key", "value").build())
.build())
+ .setEventName(EVENT_NAME)
.setBody(BODY)
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
@@ -108,11 +110,12 @@ void toProtoLogRecord(MarshalerSource marshalerSource) {
parse(
LogRecord.getDefaultInstance(),
marshalerSource.create(
- TestLogRecordData.builder()
+ TestExtendedLogRecordData.builder()
.setResource(
Resource.create(Attributes.builder().put("testKey", "testValue").build()))
.setInstrumentationScopeInfo(
InstrumentationScopeInfo.builder("instrumentation").setVersion("1").build())
+ .setEventName(EVENT_NAME)
.setBody(BODY)
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
@@ -128,6 +131,7 @@ void toProtoLogRecord(MarshalerSource marshalerSource) {
assertThat(logRecord.getTraceId().toByteArray()).isEqualTo(TRACE_ID_BYTES);
assertThat(logRecord.getSpanId().toByteArray()).isEqualTo(SPAN_ID_BYTES);
assertThat(logRecord.getSeverityText()).isEqualTo("INFO");
+ assertThat(logRecord.getEventName()).isEqualTo(EVENT_NAME);
assertThat(logRecord.getBody()).isEqualTo(AnyValue.newBuilder().setStringValue(BODY).build());
assertThat(logRecord.getAttributesList())
.containsExactly(
@@ -147,7 +151,7 @@ void toProtoLogRecord_MinimalFields(MarshalerSource marshalerSource) {
parse(
LogRecord.getDefaultInstance(),
marshalerSource.create(
- TestLogRecordData.builder()
+ TestExtendedLogRecordData.builder()
.setResource(
Resource.create(Attributes.builder().put("testKey", "testValue").build()))
.setInstrumentationScopeInfo(
diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LowAllocationLogRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LowAllocationLogRequestMarshalerTest.java
index 4890e02dd66..2d8d61e207d 100644
--- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LowAllocationLogRequestMarshalerTest.java
+++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LowAllocationLogRequestMarshalerTest.java
@@ -16,7 +16,7 @@
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.resources.Resource;
-import io.opentelemetry.sdk.testing.logs.TestLogRecordData;
+import io.opentelemetry.sdk.testing.logs.internal.TestExtendedLogRecordData;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -39,6 +39,7 @@ class LowAllocationLogRequestMarshalerTest {
AttributeKey.doubleArrayKey("key_double_array");
private static final AttributeKey> KEY_BOOLEAN_ARRAY =
AttributeKey.booleanArrayKey("key_boolean_array");
+ private static final String EVENT_NAME = "hello";
private static final String BODY = "Hello world from this log...";
private static final Resource RESOURCE =
@@ -72,9 +73,10 @@ private static List createLogRecordDataList() {
}
private static LogRecordData createLogRecordData() {
- return TestLogRecordData.builder()
+ return TestExtendedLogRecordData.builder()
.setResource(RESOURCE)
.setInstrumentationScopeInfo(INSTRUMENTATION_SCOPE_INFO)
+ .setEventName(EVENT_NAME)
.setBody(BODY)
.setSeverity(Severity.INFO)
.setSeverityText("INFO")
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 9a0ffec76c6..578bb57eca5 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
@@ -648,8 +648,9 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) {
TraceFlags.getDefault(),
TraceState.getDefault());
- try (Scope unused = Span.wrap(spanContext).makeCurrent()) {
+ try (Scope ignored = Span.wrap(spanContext).makeCurrent()) {
((ExtendedLogRecordBuilder) logger.logRecordBuilder())
+ .setEventName("event name")
.setBody(
of(
KeyValue.of("str_key", of("value")),
@@ -699,6 +700,7 @@ private static void testLogRecordExporter(LogRecordExporter logRecordExporter) {
// LogRecord via Logger.logRecordBuilder()...emit()
io.opentelemetry.proto.logs.v1.LogRecord protoLog1 = ilLogs.getLogRecords(0);
+ assertThat(protoLog1.getEventName()).isEqualTo("event name");
assertThat(protoLog1.getBody())
.isEqualTo(
AnyValue.newBuilder()
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogRecordBuilder.java
index ba1d0e6cfd2..9f874d1f4b3 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogRecordBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogRecordBuilder.java
@@ -23,6 +23,12 @@ final class ExtendedSdkLogRecordBuilder extends SdkLogRecordBuilder
super(loggerSharedState, instrumentationScopeInfo);
}
+ @Override
+ public ExtendedSdkLogRecordBuilder setEventName(String eventName) {
+ super.setEventName(eventName);
+ return this;
+ }
+
@Override
public ExtendedSdkLogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) {
super.setTimestamp(timestamp, unit);
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogger.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogger.java
index 67813bb933d..e3ab57a9711 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogger.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogger.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.logs;
+import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder;
import io.opentelemetry.api.incubator.logs.ExtendedLogger;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.internal.LoggerConfig;
@@ -26,4 +27,9 @@ final class ExtendedSdkLogger extends SdkLogger implements ExtendedLogger {
public boolean isEnabled() {
return loggerEnabled;
}
+
+ @Override
+ public ExtendedLogRecordBuilder logRecordBuilder() {
+ return (ExtendedLogRecordBuilder) super.logRecordBuilder();
+ }
}
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ReadWriteLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ReadWriteLogRecord.java
index 03639e31e9f..8b69483d2a8 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ReadWriteLogRecord.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ReadWriteLogRecord.java
@@ -52,6 +52,8 @@ default ReadWriteLogRecord setAllAttributes(Attributes attributes) {
/** Return an immutable {@link LogRecordData} instance representing this log record. */
LogRecordData toLogRecordData();
+ // TODO (trask) once event name stabilizes, add getEventName()
+
/**
* Returns the value of a given attribute if it exists. This is the equivalent of calling {@code
* getAttributes().get(key)}.
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
index ce43bc8d2c6..da7e1f45e7e 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilder.java
@@ -24,6 +24,7 @@ class SdkLogRecordBuilder implements LogRecordBuilder {
private final LogLimits logLimits;
private final InstrumentationScopeInfo instrumentationScopeInfo;
+ @Nullable private String eventName;
private long timestampEpochNanos;
private long observedTimestampEpochNanos;
@Nullable private Context context;
@@ -39,6 +40,12 @@ class SdkLogRecordBuilder implements LogRecordBuilder {
this.instrumentationScopeInfo = instrumentationScopeInfo;
}
+ // accessible via ExtendedSdkLogRecordBuilder
+ SdkLogRecordBuilder setEventName(String eventName) {
+ this.eventName = eventName;
+ return this;
+ }
+
@Override
public SdkLogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) {
this.timestampEpochNanos = unit.toNanos(timestamp);
@@ -126,6 +133,7 @@ public void emit() {
loggerSharedState.getLogLimits(),
loggerSharedState.getResource(),
instrumentationScopeInfo,
+ eventName,
timestampEpochNanos,
observedTimestampEpochNanos,
Span.fromContext(context).getSpanContext(),
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordData.java
index 1927a0ec572..eb8e966a7fd 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordData.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogRecordData.java
@@ -11,7 +11,7 @@
import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
-import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.data.internal.ExtendedLogRecordData;
import io.opentelemetry.sdk.resources.Resource;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -19,13 +19,14 @@
@AutoValue
@AutoValue.CopyAnnotations
@Immutable
-abstract class SdkLogRecordData implements LogRecordData {
+abstract class SdkLogRecordData implements ExtendedLogRecordData {
SdkLogRecordData() {}
static SdkLogRecordData create(
Resource resource,
InstrumentationScopeInfo instrumentationScopeInfo,
+ @Nullable String eventName,
long epochNanos,
long observedEpochNanos,
SpanContext spanContext,
@@ -44,13 +45,18 @@ static SdkLogRecordData create(
severityText,
attributes,
totalAttributeCount,
- body);
+ body,
+ eventName);
}
@Override
@Nullable
public abstract Value> getBodyValue();
+ @Override
+ @Nullable
+ public abstract String getEventName();
+
@Override
@SuppressWarnings("deprecation") // Implementation of deprecated method
public io.opentelemetry.sdk.logs.data.Body getBody() {
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkReadWriteLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkReadWriteLogRecord.java
index e6c68ce6ec4..ad6197d8cf3 100644
--- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkReadWriteLogRecord.java
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkReadWriteLogRecord.java
@@ -24,6 +24,7 @@ class SdkReadWriteLogRecord implements ReadWriteLogRecord {
private final LogLimits logLimits;
private final Resource resource;
private final InstrumentationScopeInfo instrumentationScopeInfo;
+ @Nullable private final String eventName;
private final long timestampEpochNanos;
private final long observedTimestampEpochNanos;
private final SpanContext spanContext;
@@ -40,6 +41,7 @@ private SdkReadWriteLogRecord(
LogLimits logLimits,
Resource resource,
InstrumentationScopeInfo instrumentationScopeInfo,
+ @Nullable String eventName,
long timestampEpochNanos,
long observedTimestampEpochNanos,
SpanContext spanContext,
@@ -50,6 +52,7 @@ private SdkReadWriteLogRecord(
this.logLimits = logLimits;
this.resource = resource;
this.instrumentationScopeInfo = instrumentationScopeInfo;
+ this.eventName = eventName;
this.timestampEpochNanos = timestampEpochNanos;
this.observedTimestampEpochNanos = observedTimestampEpochNanos;
this.spanContext = spanContext;
@@ -64,6 +67,7 @@ static SdkReadWriteLogRecord create(
LogLimits logLimits,
Resource resource,
InstrumentationScopeInfo instrumentationScopeInfo,
+ @Nullable String eventName,
long timestampEpochNanos,
long observedTimestampEpochNanos,
SpanContext spanContext,
@@ -75,6 +79,7 @@ static SdkReadWriteLogRecord create(
logLimits,
resource,
instrumentationScopeInfo,
+ eventName,
timestampEpochNanos,
observedTimestampEpochNanos,
spanContext,
@@ -115,6 +120,7 @@ public LogRecordData toLogRecordData() {
return SdkLogRecordData.create(
resource,
instrumentationScopeInfo,
+ eventName,
timestampEpochNanos,
observedTimestampEpochNanos,
spanContext,
diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/internal/ExtendedLogRecordData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/internal/ExtendedLogRecordData.java
new file mode 100644
index 00000000000..61e48eb7821
--- /dev/null
+++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/internal/ExtendedLogRecordData.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.logs.data.internal;
+
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import javax.annotation.Nullable;
+
+/**
+ * This class is internal and experimental. Its APIs are unstable and can change at any time. Its
+ * APIs (or a version of them) may be promoted to the public stable API in the future, but no
+ * guarantees are made.
+ */
+public interface ExtendedLogRecordData extends LogRecordData {
+
+ @Nullable
+ String getEventName();
+}
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/ReadWriteLogRecordTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/ReadWriteLogRecordTest.java
index 7a444817d40..95215ee57db 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/ReadWriteLogRecordTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/ReadWriteLogRecordTest.java
@@ -62,6 +62,7 @@ SdkReadWriteLogRecord buildLogRecord() {
limits,
resource,
scope,
+ "event name",
0L,
0L,
spanContext,
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
index 3c5743e673d..0be11e67b31 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
@@ -60,6 +60,7 @@ void emit_AllFields() {
Instant timestamp = Instant.now();
Instant observedTimestamp = Instant.now().plusNanos(100);
+ String eventName = "event name";
String bodyStr = "body";
String sevText = "sevText";
Severity severity = Severity.DEBUG3;
@@ -70,6 +71,7 @@ void emit_AllFields() {
TraceFlags.getSampled(),
TraceState.getDefault());
+ builder.setEventName(eventName);
builder.setBody(bodyStr);
builder.setTimestamp(123, TimeUnit.SECONDS);
builder.setTimestamp(timestamp);
@@ -85,6 +87,8 @@ void emit_AllFields() {
assertThat(emittedLog.get().toLogRecordData())
.hasResource(RESOURCE)
.hasInstrumentationScope(SCOPE_INFO)
+ // TODO (trask) once event name stabilizes
+ // .hasEventName(eventName)
.hasBody(bodyStr)
.hasTimestamp(TimeUnit.SECONDS.toNanos(timestamp.getEpochSecond()) + timestamp.getNano())
.hasObservedTimestamp(
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
index 05da79ee3eb..63063731ac4 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLoggerProviderTest.java
@@ -246,6 +246,8 @@ void loggerBuilder_WithLogRecordProcessor() {
sdkLoggerProvider
.get("test")
.logRecordBuilder()
+ // TODO (trask) once event name stabilizes
+ // .setEventName("event name")
.setTimestamp(100, TimeUnit.NANOSECONDS)
.setContext(Span.wrap(spanContext).storeInContext(Context.root()))
.setSeverity(Severity.DEBUG)
@@ -258,6 +260,8 @@ void loggerBuilder_WithLogRecordProcessor() {
assertThat(logRecordData.get())
.hasResource(resource)
.hasInstrumentationScope(InstrumentationScopeInfo.create("test"))
+ // TODO (trask) once event name stabilizes
+ // .hasEventName("event name")
.hasTimestamp(100)
.hasSpanContext(spanContext)
.hasSeverity(Severity.DEBUG)
diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/LogRecordDataAssert.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/LogRecordDataAssert.java
index e2256dcbbef..323e5b7813d 100644
--- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/LogRecordDataAssert.java
+++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/LogRecordDataAssert.java
@@ -84,6 +84,8 @@ public LogRecordDataAssert hasInstrumentationScope(
return this;
}
+ // TODO (trask) once event name stabilizes, add hasEventName(String)
+
/** Asserts the log has the given epoch {@code timestamp}. */
public LogRecordDataAssert hasTimestamp(long timestampEpochNanos) {
isNotNull();
diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/logs/internal/TestExtendedLogRecordData.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/logs/internal/TestExtendedLogRecordData.java
new file mode 100644
index 00000000000..750344bf748
--- /dev/null
+++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/logs/internal/TestExtendedLogRecordData.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.testing.logs.internal;
+
+import com.google.auto.value.AutoValue;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
+import io.opentelemetry.api.logs.Severity;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import io.opentelemetry.sdk.logs.data.LogRecordData;
+import io.opentelemetry.sdk.logs.data.internal.ExtendedLogRecordData;
+import io.opentelemetry.sdk.resources.Resource;
+import java.time.Instant;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Immutable representation of {@link LogRecordData}.
+ *
+ * This class is internal and experimental. Its APIs are unstable and can change at any time. Its
+ * APIs (or a version of them) may be promoted to the public stable API in the future, but no
+ * guarantees are made.
+ *
+ * @since 1.27.0
+ */
+// TODO (trask) delete this class once event name stabilizes
+@Immutable
+@AutoValue
+@AutoValue.CopyAnnotations
+// Carry suppression for Body to AutoValue implementation via @AutoValue.CopyAnnotations
+@SuppressWarnings("deprecation")
+public abstract class TestExtendedLogRecordData implements ExtendedLogRecordData {
+
+ /** Creates a new Builder for creating an {@link LogRecordData} instance. */
+ public static Builder builder() {
+ return new AutoValue_TestExtendedLogRecordData.Builder()
+ .setResource(Resource.empty())
+ .setInstrumentationScopeInfo(InstrumentationScopeInfo.empty())
+ .setTimestamp(0, TimeUnit.NANOSECONDS)
+ .setObservedTimestamp(0, TimeUnit.NANOSECONDS)
+ .setSpanContext(SpanContext.getInvalid())
+ .setSeverity(Severity.UNDEFINED_SEVERITY_NUMBER)
+ .setAttributes(Attributes.empty())
+ .setTotalAttributeCount(0);
+ }
+
+ @Deprecated
+ public io.opentelemetry.sdk.logs.data.Body getBody() {
+ Value> valueBody = getBodyValue();
+ return valueBody == null
+ ? io.opentelemetry.sdk.logs.data.Body.empty()
+ : io.opentelemetry.sdk.logs.data.Body.string(valueBody.asString());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.42.0
+ */
+ @Override
+ @Nullable
+ public abstract Value> getBodyValue();
+
+ TestExtendedLogRecordData() {}
+
+ /**
+ * A {@code Builder} class for {@link TestExtendedLogRecordData}.
+ *
+ *
This class is internal and experimental. Its APIs are unstable and can change at any time.
+ * Its APIs (or a version of them) may be promoted to the public stable API in the future, but no
+ * guarantees are made.
+ */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ abstract TestExtendedLogRecordData autoBuild();
+
+ /** Create a new {@link LogRecordData} instance from the data in this. */
+ public TestExtendedLogRecordData build() {
+ return autoBuild();
+ }
+
+ /** Set the {@link Resource}. */
+ public abstract Builder setResource(Resource resource);
+
+ /** Sets the {@link InstrumentationScopeInfo}. */
+ public abstract Builder setInstrumentationScopeInfo(
+ InstrumentationScopeInfo instrumentationScopeInfo);
+
+ public abstract Builder setEventName(String eventName);
+
+ /**
+ * Set the epoch {@code timestamp}, using the instant.
+ *
+ *
The {@code timestamp} is the time at which the log record occurred.
+ */
+ public Builder setTimestamp(Instant instant) {
+ return setTimestampEpochNanos(
+ TimeUnit.SECONDS.toNanos(instant.getEpochSecond()) + instant.getNano());
+ }
+
+ /**
+ * Set the epoch {@code timestamp}, using the timestamp and unit.
+ *
+ *
The {@code timestamp} is the time at which the log record occurred.
+ */
+ public Builder setTimestamp(long timestamp, TimeUnit unit) {
+ return setTimestampEpochNanos(unit.toNanos(timestamp));
+ }
+
+ /**
+ * Set the epoch {@code timestamp}.
+ *
+ *
The {@code timestamp} is the time at which the log record occurred.
+ */
+ abstract Builder setTimestampEpochNanos(long epochNanos);
+
+ /**
+ * Set the {@code observedTimestamp}, using the instant.
+ *
+ *
The {@code observedTimestamp} is the time at which the log record was observed.
+ */
+ public Builder setObservedTimestamp(Instant instant) {
+ return setObservedTimestampEpochNanos(
+ TimeUnit.SECONDS.toNanos(instant.getEpochSecond()) + instant.getNano());
+ }
+
+ /**
+ * Set the epoch {@code observedTimestamp}, using the timestamp and unit.
+ *
+ *
The {@code observedTimestamp} is the time at which the log record was observed.
+ */
+ public Builder setObservedTimestamp(long timestamp, TimeUnit unit) {
+ return setObservedTimestampEpochNanos(unit.toNanos(timestamp));
+ }
+
+ /**
+ * Set the epoch {@code observedTimestamp}.
+ *
+ *
The {@code observedTimestamp} is the time at which the log record was observed.
+ */
+ abstract Builder setObservedTimestampEpochNanos(long epochNanos);
+
+ /** Set the span context. */
+ public abstract Builder setSpanContext(SpanContext spanContext);
+
+ /** Set the severity. */
+ public abstract Builder setSeverity(Severity severity);
+
+ /** Set the severity text. */
+ public abstract Builder setSeverityText(String severityText);
+
+ /** Set the body string. */
+ public Builder setBody(String body) {
+ return setBodyValue(Value.of(body));
+ }
+
+ /**
+ * Set the body.
+ *
+ * @deprecated Use {@link #setBodyValue(Value)}.
+ */
+ @Deprecated
+ public Builder setBody(io.opentelemetry.sdk.logs.data.Body body) {
+ if (body.getType() == io.opentelemetry.sdk.logs.data.Body.Type.STRING) {
+ setBodyValue(Value.of(body.asString()));
+ } else if (body.getType() == io.opentelemetry.sdk.logs.data.Body.Type.EMPTY) {
+ setBodyValue(null);
+ }
+ return this;
+ }
+
+ /**
+ * Set the body.
+ *
+ * @since 1.42.0
+ */
+ public abstract Builder setBodyValue(@Nullable Value> body);
+
+ /** Set the attributes. */
+ public abstract Builder setAttributes(Attributes attributes);
+
+ /** Set the total attribute count. */
+ public abstract Builder setTotalAttributeCount(int totalAttributeCount);
+ }
+}
diff --git a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/LogAssertionsTest.java b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/LogAssertionsTest.java
index 849ba25b90f..e30210eb9d6 100644
--- a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/LogAssertionsTest.java
+++ b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/LogAssertionsTest.java
@@ -34,7 +34,7 @@
import io.opentelemetry.sdk.logs.internal.SdkEventLoggerProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
-import io.opentelemetry.sdk.testing.logs.TestLogRecordData;
+import io.opentelemetry.sdk.testing.logs.internal.TestExtendedLogRecordData;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -62,9 +62,10 @@ public class LogAssertionsTest {
.build();
private static final LogRecordData LOG_DATA =
- TestLogRecordData.builder()
+ TestExtendedLogRecordData.builder()
.setResource(RESOURCE)
.setInstrumentationScopeInfo(INSTRUMENTATION_SCOPE_INFO)
+ .setEventName("event name")
.setTimestamp(100, TimeUnit.NANOSECONDS)
.setObservedTimestamp(200, TimeUnit.NANOSECONDS)
.setSpanContext(
@@ -112,6 +113,8 @@ void passing() {
satisfies(DOG, val -> val.startsWith("bar")),
satisfies(AttributeKey.booleanKey("dog is cute"), val -> val.isTrue())))
.hasInstrumentationScope(INSTRUMENTATION_SCOPE_INFO)
+ // TODO (trask) once event name stabilizes
+ // .hasEventName("event name")
.hasTimestamp(100)
.hasObservedTimestamp(200)
.hasSpanContext(