From 41ee190821a1a094c1fd1a2169aec2182cb8083b Mon Sep 17 00:00:00 2001 From: jack-berg Date: Thu, 14 Oct 2021 16:56:02 -0500 Subject: [PATCH 01/13] Add log processors to the builder so LogSinkSdkProvider is immutable --- .../sdk/logs/LogSinkSdkProvider.java | 11 ++++----- .../sdk/logs/LogSinkSdkProviderBuilder.java | 24 ++++++++++++++++++- .../sdk/logs/LogSinkSdkProviderTest.java | 17 +++++++------ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java index 7aaa81cd31e..b405fb7f43d 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java @@ -10,11 +10,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Objects; public final class LogSinkSdkProvider { private final LogSink logSink = new SdkLogSink(); - private final List processors = new ArrayList<>(); + private final List processors; /** * Returns a new {@link LogSinkSdkProviderBuilder} for this class. @@ -25,17 +24,15 @@ public static LogSinkSdkProviderBuilder builder() { return new LogSinkSdkProviderBuilder(); } - LogSinkSdkProvider() {} + LogSinkSdkProvider(List processors) { + this.processors = processors; + } public LogSink get(String instrumentationName, String instrumentationVersion) { // Currently there is no differentiation by instrumentation library return logSink; } - public void addLogProcessor(LogProcessor processor) { - processors.add(Objects.requireNonNull(processor, "Processor can not be null")); - } - /** * Flushes all attached processors. * diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java index e51d93cb20b..9e8161c5585 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java @@ -5,10 +5,32 @@ package io.opentelemetry.sdk.logs; +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.sdk.logs.data.LogRecord; +import java.util.ArrayList; +import java.util.List; + public final class LogSinkSdkProviderBuilder { + + private final List logProcessors = new ArrayList<>(); + LogSinkSdkProviderBuilder() {} + /** + * Add a LogProcessor to the log pipeline that will be built. {@link LogProcessor} will be called + * each time a {@link LogRecord} is offered to a {@link LogSink}. + * + * @param processor the processor to be added to the processing pipeline. + * @return this + */ + public LogSinkSdkProviderBuilder addLogProcessor(LogProcessor processor) { + requireNonNull(processor, "processor can not be null"); + logProcessors.add(processor); + return this; + } + public LogSinkSdkProvider build() { - return new LogSinkSdkProvider(); + return new LogSinkSdkProvider(logProcessors); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java index 9753cbb8a47..94890879443 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java @@ -49,8 +49,7 @@ private static LogRecord createLog(Severity severity, String message) { void testLogSinkSdkProvider() { TestLogExporter exporter = new TestLogExporter(); LogProcessor processor = BatchLogProcessor.builder(exporter).build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().build(); - provider.addLogProcessor(processor); + LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); LogRecord log = createLog(Severity.ERROR, "test"); sink.offer(log); @@ -69,8 +68,7 @@ void testBatchSize() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().build(); - provider.addLogProcessor(processor); + LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); for (int i = 0; i < 7; i++) { @@ -101,8 +99,7 @@ void testNoBlocking() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().build(); - provider.addLogProcessor(processor); + LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); long start = System.currentTimeMillis(); @@ -120,9 +117,11 @@ void testNoBlocking() { void testMultipleProcessors() { TestLogProcessor processorOne = new TestLogProcessor(); TestLogProcessor processorTwo = new TestLogProcessor(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().build(); - provider.addLogProcessor(processorOne); - provider.addLogProcessor(processorTwo); + LogSinkSdkProvider provider = + LogSinkSdkProvider.builder() + .addLogProcessor(processorOne) + .addLogProcessor(processorTwo) + .build(); LogSink sink = provider.get("test", "0.1"); LogRecord record = createLog(Severity.INFO, "test"); sink.offer(record); From b4950f60d8eacf19dfb09e4cace5ed628e96ad7c Mon Sep 17 00:00:00 2001 From: jack-berg Date: Thu, 14 Oct 2021 17:08:37 -0500 Subject: [PATCH 02/13] Add api diff --- .../opentelemetry-exporter-logging-otlp.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt index df26146497b..dc1c80f64c4 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt @@ -1,2 +1,7 @@ Comparing source compatibility of against -No changes. \ No newline at end of file ++++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingLogExporter (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.logs.export.LogExporter create() + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode export(java.util.Collection) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown() From 8f66d078719f7f2be310e4d20015fed7037c7350 Mon Sep 17 00:00:00 2001 From: jack-berg Date: Fri, 15 Oct 2021 15:43:50 -0500 Subject: [PATCH 03/13] Rename to SdkLogSinkProvider --- .../sdk/logs/LogSinkSdkProviderBuilder.java | 4 ++-- ...gSinkSdkProvider.java => SdkLogSinkProvider.java} | 4 ++-- .../java/io/opentelemetry/sdk/logs/package-info.java | 2 +- ...ProviderTest.java => SdkLogSinkProviderTest.java} | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/{LogSinkSdkProvider.java => SdkLogSinkProvider.java} (95%) rename sdk/logs/src/test/java/io/opentelemetry/sdk/logs/{LogSinkSdkProviderTest.java => SdkLogSinkProviderTest.java} (94%) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java index 9e8161c5585..3768dfe6929 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java @@ -30,7 +30,7 @@ public LogSinkSdkProviderBuilder addLogProcessor(LogProcessor processor) { return this; } - public LogSinkSdkProvider build() { - return new LogSinkSdkProvider(logProcessors); + public SdkLogSinkProvider build() { + return new SdkLogSinkProvider(logProcessors); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java similarity index 95% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java index b405fb7f43d..d8755287466 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java @@ -11,7 +11,7 @@ import java.util.Collection; import java.util.List; -public final class LogSinkSdkProvider { +public final class SdkLogSinkProvider { private final LogSink logSink = new SdkLogSink(); private final List processors; @@ -24,7 +24,7 @@ public static LogSinkSdkProviderBuilder builder() { return new LogSinkSdkProviderBuilder(); } - LogSinkSdkProvider(List processors) { + SdkLogSinkProvider(List processors) { this.processors = processors; } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java index 4adcab4a99b..7607958fb84 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java @@ -6,7 +6,7 @@ /** * The OpenTelemetry SDK implementation of logging. * - * @see io.opentelemetry.sdk.logs.LogSinkSdkProvider + * @see io.opentelemetry.sdk.logs.SdkLogSinkProvider */ @ParametersAreNonnullByDefault package io.opentelemetry.sdk.logs; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java similarity index 94% rename from sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java rename to sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java index 94890879443..13d35b390a0 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java @@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; -class LogSinkSdkProviderTest { +class SdkLogSinkProviderTest { private static LogRecord createLog(Severity severity, String message) { return LogRecord.builder( @@ -49,7 +49,7 @@ private static LogRecord createLog(Severity severity, String message) { void testLogSinkSdkProvider() { TestLogExporter exporter = new TestLogExporter(); LogProcessor processor = BatchLogProcessor.builder(exporter).build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); + SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); LogRecord log = createLog(Severity.ERROR, "test"); sink.offer(log); @@ -68,7 +68,7 @@ void testBatchSize() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); + SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); for (int i = 0; i < 7; i++) { @@ -99,7 +99,7 @@ void testNoBlocking() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogSinkSdkProvider provider = LogSinkSdkProvider.builder().addLogProcessor(processor).build(); + SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); LogSink sink = provider.get("test", "0.1a"); long start = System.currentTimeMillis(); @@ -117,8 +117,8 @@ void testNoBlocking() { void testMultipleProcessors() { TestLogProcessor processorOne = new TestLogProcessor(); TestLogProcessor processorTwo = new TestLogProcessor(); - LogSinkSdkProvider provider = - LogSinkSdkProvider.builder() + SdkLogSinkProvider provider = + SdkLogSinkProvider.builder() .addLogProcessor(processorOne) .addLogProcessor(processorTwo) .build(); From baa80138f21400a4c1d61e038930b36419f07f3f Mon Sep 17 00:00:00 2001 From: jack-berg Date: Fri, 15 Oct 2021 17:21:01 -0500 Subject: [PATCH 04/13] Rework log sdk --- .../opentelemetry/sdk/logs/LogProcessor.java | 60 ++++++++++-- .../io/opentelemetry/sdk/logs/LogSink.java | 17 +++- .../sdk/logs/LogSinkSdkProviderBuilder.java | 29 ++++-- .../sdk/logs/LogSinkSharedState.java | 45 +++++++++ .../sdk/logs/MultiLogProcessor.java | 56 +++++++++++ .../sdk/logs/NoopLogProcessor.java | 21 +++++ .../io/opentelemetry/sdk/logs/SdkLogSink.java | 34 +++++++ .../sdk/logs/SdkLogSinkBuilder.java | 36 +++++++ .../sdk/logs/SdkLogSinkProvider.java | 94 ++++++++++++------- .../sdk/logs/data/LogBuilder.java | 35 +++++++ .../sdk/logs/data/LogRecordBuilder.java | 14 ++- .../sdk/logs/export/BatchLogProcessor.java | 9 +- .../io/opentelemetry/sdk/logs/DemoTest.java | 70 ++++++++++++++ .../sdk/logs/sdk/BatchLogProcessorTest.java | 2 +- .../sdk/logs/util/TestLogProcessor.java | 10 +- 15 files changed, 467 insertions(+), 65 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java create mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java index 0837e7806d2..da889dbec1e 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java @@ -6,24 +6,68 @@ package io.opentelemetry.sdk.logs; import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.logs.data.LogData; +import java.io.Closeable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; -public interface LogProcessor { +public interface LogProcessor extends Closeable { - void addLogRecord(LogRecord record); + /** + * Process a log. + * + * @param logData the log + */ + void process(LogData logData); /** - * Called when {@link SdkTracerProvider#shutdown()} is called. + * Shutdown the log processor. * * @return result */ - CompletableResultCode shutdown(); + default CompletableResultCode shutdown() { + return forceFlush(); + } /** - * Processes all span events that have not yet been processed. + * Process all logs that have not yet been processed. * * @return result */ - CompletableResultCode forceFlush(); + default CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } + + @Override + default void close() { + shutdown().join(10, TimeUnit.SECONDS); + } + + /** + * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code + * processors} in order. + */ + static LogProcessor composite(LogProcessor... processors) { + return composite(Arrays.asList(processors)); + } + + /** + * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code + * processors} in order. + */ + static LogProcessor composite(Iterable processors) { + List processorList = new ArrayList<>(); + for (LogProcessor processor : processors) { + processorList.add(processor); + } + if (processorList.isEmpty()) { + return NoopLogProcessor.getInstance(); + } + if (processorList.size() == 1) { + return processorList.get(0); + } + return MultiLogProcessor.create(processorList); + } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java index b5e852308a1..6a17a6bae39 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java @@ -5,14 +5,23 @@ package io.opentelemetry.sdk.logs; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.LogBuilder; +import io.opentelemetry.sdk.logs.data.LogData; /** A LogSink accepts logging records for transmission to an aggregator or log processing system. */ public interface LogSink { + + /** + * Create a log builder. {@link LogBuilder#build()} can be passed to {@link #offer(LogData)}. + * + * @return the builder + */ + LogBuilder builder(); + /** - * Pass a record to the SDK for transmission to a logging exporter. + * Pass the {@link LogData} to the sink. * - * @param record record to transmit + * @param logData the log */ - void offer(LogRecord record); + void offer(LogData logData); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java index 3768dfe6929..816ce8fe21c 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java @@ -7,30 +7,47 @@ import static java.util.Objects.requireNonNull; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.resources.Resource; import java.util.ArrayList; import java.util.List; public final class LogSinkSdkProviderBuilder { private final List logProcessors = new ArrayList<>(); + private Resource resource = Resource.getDefault(); LogSinkSdkProviderBuilder() {} /** - * Add a LogProcessor to the log pipeline that will be built. {@link LogProcessor} will be called - * each time a {@link LogRecord} is offered to a {@link LogSink}. + * Set the resource. * - * @param processor the processor to be added to the processing pipeline. + * @param resource the resource + * @return this + */ + public LogSinkSdkProviderBuilder setResource(Resource resource) { + requireNonNull(resource, "resource"); + this.resource = resource; + return this; + } + + /** + * Add a log processor. + * + * @param processor the log processor * @return this */ public LogSinkSdkProviderBuilder addLogProcessor(LogProcessor processor) { - requireNonNull(processor, "processor can not be null"); + requireNonNull(processor, "processor"); logProcessors.add(processor); return this; } + /** + * Create a {@link SdkLogSinkProvider} instance. + * + * @return an instance configured with the provided options + */ public SdkLogSinkProvider build() { - return new SdkLogSinkProvider(logProcessors); + return new SdkLogSinkProvider(resource, logProcessors); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java new file mode 100644 index 00000000000..e227bd22354 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.resources.Resource; +import java.util.List; +import javax.annotation.Nullable; + +final class LogSinkSharedState { + private final Object lock = new Object(); + private final Resource resource; + private final LogProcessor activeLogProcessor; + @Nullable private volatile CompletableResultCode shutdownResult = null; + + LogSinkSharedState(Resource resource, List logProcessors) { + this.resource = resource; + this.activeLogProcessor = LogProcessor.composite(logProcessors); + } + + Resource getResource() { + return resource; + } + + LogProcessor getActiveLogProcessor() { + return activeLogProcessor; + } + + boolean hasBeenShutdown() { + return shutdownResult != null; + } + + CompletableResultCode shutdown() { + synchronized (lock) { + if (shutdownResult != null) { + return shutdownResult; + } + shutdownResult = activeLogProcessor.shutdown(); + return shutdownResult; + } + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java new file mode 100644 index 00000000000..985c45f7260 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java @@ -0,0 +1,56 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.data.LogData; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; + +final class MultiLogProcessor implements LogProcessor { + + private final List logProcessors; + private final AtomicBoolean isShutdown = new AtomicBoolean(false); + + static LogProcessor create(List logProcessorsList) { + return new MultiLogProcessor( + new ArrayList<>(Objects.requireNonNull(logProcessorsList, "logProcessorsList"))); + } + + @Override + public void process(LogData logData) { + for (LogProcessor logProcessor : logProcessors) { + logProcessor.process(logData); + } + } + + @Override + public CompletableResultCode shutdown() { + if (isShutdown.getAndSet(true)) { + return CompletableResultCode.ofSuccess(); + } + List results = new ArrayList<>(logProcessors.size()); + for (LogProcessor logProcessor : logProcessors) { + results.add(logProcessor.shutdown()); + } + return CompletableResultCode.ofAll(results); + } + + @Override + public CompletableResultCode forceFlush() { + List results = new ArrayList<>(logProcessors.size()); + for (LogProcessor logProcessor : logProcessors) { + results.add(logProcessor.forceFlush()); + } + return CompletableResultCode.ofAll(results); + } + + private MultiLogProcessor(List logProcessorsList) { + this.logProcessors = logProcessorsList; + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java new file mode 100644 index 00000000000..52b06182e9e --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.logs.data.LogData; + +final class NoopLogProcessor implements LogProcessor { + private static final NoopLogProcessor INSTANCE = new NoopLogProcessor(); + + static LogProcessor getInstance() { + return INSTANCE; + } + + private NoopLogProcessor() {} + + @Override + public void process(LogData logData) {} +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java new file mode 100644 index 00000000000..5b4b106f93b --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.LogBuilder; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.LogRecord; + +class SdkLogSink implements LogSink { + + private final LogSinkSharedState logSinkSharedState; + private final InstrumentationLibraryInfo instrumentationLibraryInfo; + + SdkLogSink( + LogSinkSharedState logSinkSharedState, + InstrumentationLibraryInfo instrumentationLibraryInfo) { + this.logSinkSharedState = logSinkSharedState; + this.instrumentationLibraryInfo = instrumentationLibraryInfo; + } + + @Override + public void offer(LogData logData) { + logSinkSharedState.getActiveLogProcessor().process(logData); + } + + @Override + public LogBuilder builder() { + return LogRecord.builder(logSinkSharedState.getResource(), instrumentationLibraryInfo); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java new file mode 100644 index 00000000000..2ef7a9f1a89 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.internal.ComponentRegistry; +import javax.annotation.Nullable; + +public final class SdkLogSinkBuilder { + + private final ComponentRegistry registry; + private final String instrumentationName; + @Nullable private String getInstrumentationVersion; + @Nullable private String schemaUrl; + + SdkLogSinkBuilder(ComponentRegistry registry, String instrumentationName) { + this.registry = registry; + this.instrumentationName = instrumentationName; + } + + public SdkLogSinkBuilder setSchemaUrl(String schemaUrl) { + this.schemaUrl = schemaUrl; + return this; + } + + public SdkLogSinkBuilder setInstrumentationVersion(String instrumentationVersion) { + this.getInstrumentationVersion = instrumentationVersion; + return this; + } + + public LogSink build() { + return registry.get(instrumentationName, getInstrumentationVersion, schemaUrl); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java index d8755287466..5477f9bc47a 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java @@ -6,65 +6,89 @@ package io.opentelemetry.sdk.logs; import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.logs.data.LogRecord; -import java.util.ArrayList; -import java.util.Collection; +import io.opentelemetry.sdk.internal.ComponentRegistry; +import io.opentelemetry.sdk.resources.Resource; +import java.io.Closeable; import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; -public final class SdkLogSinkProvider { - private final LogSink logSink = new SdkLogSink(); - private final List processors; +public final class SdkLogSinkProvider implements Closeable { + private static final Logger logger = Logger.getLogger(SdkLogSinkProvider.class.getName()); + private final LogSinkSharedState sharedState; + private final ComponentRegistry logSinkSdkComponentRegistry; - /** - * Returns a new {@link LogSinkSdkProviderBuilder} for this class. - * - * @return a new {@link LogSinkSdkProviderBuilder} for this class. - */ public static LogSinkSdkProviderBuilder builder() { return new LogSinkSdkProviderBuilder(); } - SdkLogSinkProvider(List processors) { - this.processors = processors; + SdkLogSinkProvider(Resource resource, List processors) { + this.sharedState = new LogSinkSharedState(resource, processors); + this.logSinkSdkComponentRegistry = + new ComponentRegistry<>( + instrumentationLibraryInfo -> new SdkLogSink(sharedState, instrumentationLibraryInfo)); } + /** + * Create a log sink instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log sink instance + */ + public LogSink get(String instrumentationName) { + return logSinkBuilder(instrumentationName).build(); + } + + /** + * Create a log sink instance. + * + * @param instrumentationName the name of the instrumentation library + * @param instrumentationVersion the version of the instrumentation library + * @return a log sink instance + */ public LogSink get(String instrumentationName, String instrumentationVersion) { - // Currently there is no differentiation by instrumentation library - return logSink; + return logSinkBuilder(instrumentationName) + .setInstrumentationVersion(instrumentationVersion) + .build(); } /** - * Flushes all attached processors. + * Create a log sink builder. * - * @return result + * @param instrumentationName the name of the instrumentation library + * @return a log sink builder instance + */ + public SdkLogSinkBuilder logSinkBuilder(String instrumentationName) { + // TODO: should instrumentationName be nullable + return new SdkLogSinkBuilder(logSinkSdkComponentRegistry, instrumentationName); + } + + /** + * Request the active log processor to process all logs that have not yet been processed. + * + * @return a {@link CompletableResultCode} which is completed when the flush is finished */ public CompletableResultCode forceFlush() { - final List processorResults = new ArrayList<>(processors.size()); - for (LogProcessor processor : processors) { - processorResults.add(processor.forceFlush()); - } - return CompletableResultCode.ofAll(processorResults); + return sharedState.getActiveLogProcessor().forceFlush(); } /** - * Shut down of provider and associated processors. + * Attempt to shut down the active log processor. * - * @return result + * @return a {@link CompletableResultCode} which is completed when the active log process has been + * shut down. */ public CompletableResultCode shutdown() { - Collection processorResults = new ArrayList<>(processors.size()); - for (LogProcessor processor : processors) { - processorResults.add(processor.shutdown()); + if (sharedState.hasBeenShutdown()) { + logger.log(Level.WARNING, "Calling shutdown() multiple times."); + return CompletableResultCode.ofSuccess(); } - return CompletableResultCode.ofAll(processorResults); + return sharedState.shutdown(); } - private class SdkLogSink implements LogSink { - @Override - public void offer(LogRecord record) { - for (LogProcessor processor : processors) { - processor.addLogRecord(record); - } - } + @Override + public void close() { + shutdown().join(10, TimeUnit.SECONDS); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java new file mode 100644 index 00000000000..5062f48e064 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs.data; + +import io.opentelemetry.api.common.Attributes; + +public interface LogBuilder { + + LogBuilder setEpochNanos(long timestamp); + + LogBuilder setEpochMillis(long timestamp); + + LogBuilder setTraceId(String traceId); + + LogBuilder setSpanId(String spanId); + + LogBuilder setFlags(int flags); + + LogBuilder setSeverity(Severity severity); + + LogBuilder setSeverityText(String severityText); + + LogBuilder setName(String name); + + LogBuilder setBody(Body body); + + LogBuilder setBody(String body); + + LogBuilder setAttributes(Attributes attributes); + + LogData build(); +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java index 310cd76e328..1d050ee6d0d 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java @@ -13,7 +13,7 @@ import javax.annotation.Nullable; /** Builder for {@link LogRecord}. */ -public final class LogRecordBuilder { +public final class LogRecordBuilder implements LogBuilder { private final Resource resource; private final InstrumentationLibraryInfo instrumentationLibraryInfo; @@ -32,54 +32,65 @@ public final class LogRecordBuilder { this.instrumentationLibraryInfo = instrumentationLibraryInfo; } + @Override public LogRecordBuilder setEpochNanos(long timestamp) { this.epochNanos = timestamp; return this; } + @Override public LogRecordBuilder setEpochMillis(long timestamp) { return setEpochNanos(TimeUnit.MILLISECONDS.toNanos(timestamp)); } + @Override public LogRecordBuilder setTraceId(String traceId) { this.traceId = traceId; return this; } + @Override public LogRecordBuilder setSpanId(String spanId) { this.spanId = spanId; return this; } + @Override public LogRecordBuilder setFlags(int flags) { this.flags = flags; return this; } + @Override public LogRecordBuilder setSeverity(Severity severity) { this.severity = severity; return this; } + @Override public LogRecordBuilder setSeverityText(String severityText) { this.severityText = severityText; return this; } + @Override public LogRecordBuilder setName(String name) { this.name = name; return this; } + @Override public LogRecordBuilder setBody(Body body) { this.body = body; return this; } + @Override public LogRecordBuilder setBody(String body) { return setBody(Body.stringBody(body)); } + @Override public LogRecordBuilder setAttributes(Attributes attributes) { this.attributeBuilder.putAll(attributes); return this; @@ -90,6 +101,7 @@ public LogRecordBuilder setAttributes(Attributes attributes) { * * @return value object being built */ + @Override public LogRecord build() { if (epochNanos == 0) { epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java index c51aab11612..f53ff773c60 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java @@ -15,7 +15,6 @@ import io.opentelemetry.sdk.internal.DaemonThreadFactory; import io.opentelemetry.sdk.logs.LogProcessor; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -51,8 +50,8 @@ public static BatchLogProcessorBuilder builder(LogExporter logExporter) { } @Override - public void addLogRecord(LogRecord record) { - worker.addLogRecord(record); + public void process(LogData logData) { + worker.addLog(logData); } @Override @@ -221,8 +220,8 @@ private CompletableResultCode forceFlush() { return flushResult; } - public void addLogRecord(LogRecord record) { - if (!queue.offer(record)) { + public void addLog(LogData logData) { + if (!queue.offer(logData)) { queueFullRecordCounter.add(1); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java new file mode 100644 index 00000000000..34e39927928 --- /dev/null +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.export.BatchLogProcessor; +import io.opentelemetry.sdk.logs.util.TestLogExporter; +import io.opentelemetry.sdk.resources.Resource; +import java.time.Duration; +import java.util.List; +import java.util.function.Consumer; +import org.junit.jupiter.api.Test; + +class DemoTest { + + @Test + @SuppressWarnings("SystemOut") + void usageTest() { + TestLogExporter testLogExporter = new TestLogExporter(); + + SdkLogSinkProvider sdkLogSinkProvider = + SdkLogSinkProvider.builder() + .setResource(Resource.builder().put("key", "value").build()) + .addLogProcessor(System.out::println) + .addLogProcessor( + BatchLogProcessor.builder(testLogExporter).setExporterTimeoutMillis(1000).build()) + .build(); + + LogSink logSink = sdkLogSinkProvider.get("my-library"); + + for (int i = 0; i < 10; i++) { + logSink.offer( + logSink + .builder() + .setEpochMillis(System.currentTimeMillis()) + .setBody("my message " + i) + .setAttributes(Attributes.builder().put("foo", "bar").build()) + .build()); + } + + await() + .atMost(Duration.ofSeconds(30)) + .untilAsserted( + () -> { + List logs = testLogExporter.getRecords(); + + assertThat(logs.size()).isEqualTo(10); + assertThat(logs) + .allSatisfy( + (Consumer) + logData -> { + assertThat(logData.getResource()) + .isEqualTo(Resource.builder().put("key", "value").build()); + assertThat(logData.getInstrumentationLibraryInfo()) + .isEqualTo(InstrumentationLibraryInfo.create("my-library", null)); + assertThat(logData.getBody().asString()).startsWith("my message"); + assertThat(logData.getAttributes()) + .isEqualTo(Attributes.builder().put("foo", "bar").build()); + }); + }); + } +} diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java index 6a3093776fc..18bb41c75b1 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java @@ -52,7 +52,7 @@ void testForceExport() { .build(); for (int i = 0; i < 17; i++) { LogRecord record = createLog(Severity.INFO, Integer.toString(i)); - processor.addLogRecord(record); + processor.process(record); } await().until(() -> exporter.getCallCount() > 0); assertThat(exporter.getRecords().size()).isEqualTo(batchSize); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java index e92a5635e7b..0535c57b222 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java @@ -7,18 +7,18 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.LogProcessor; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.LogData; import java.util.ArrayList; import java.util.List; public class TestLogProcessor implements LogProcessor { - private final List records = new ArrayList<>(); + private final List records = new ArrayList<>(); private boolean shutdownCalled = false; private int flushes = 0; @Override - public void addLogRecord(LogRecord record) { - records.add(record); + public void process(LogData logData) { + records.add(logData); } @Override @@ -33,7 +33,7 @@ public CompletableResultCode forceFlush() { return CompletableResultCode.ofSuccess(); } - public List getRecords() { + public List getRecords() { return records; } From 7c60e38f7131c2f05c26be61f5e5a7e9ecc2f1a0 Mon Sep 17 00:00:00 2001 From: jack-berg Date: Mon, 18 Oct 2021 13:33:58 -0500 Subject: [PATCH 05/13] Refactor logging sdk to implement OTEP-0150 --- .../otlp/OtlpJsonLoggingLogExporterTest.java | 53 ++++---- .../http/logs/OtlpHttpLogExporterTest.java | 30 ++--- .../internal/logs/LogsRequestMarshaler.java | 5 +- .../logs/LogsRequestMarshalerTest.java | 69 ++++++----- .../otlp/logs/OtlpGrpcLogsExporterTest.java | 30 ++--- .../exporter/otlp/logs/ExportTest.java | 30 ++--- .../exporter/otlp/logs/ExportTest.java | 30 ++--- .../exporter/otlp/logs/ExportTest.java | 30 ++--- .../otlp/logs/OkHttpOnlyExportTest.java | 30 ++--- .../OtlpExporterIntegrationTest.java | 47 +++---- .../io/opentelemetry/sdk/logs/LogEmitter.java | 45 +++++++ .../sdk/logs/LogEmitterBuilder.java | 54 ++++++++ .../sdk/logs/LogEmitterProvider.java | 107 ++++++++++++++++ .../sdk/logs/LogEmitterProviderBuilder.java | 59 +++++++++ ...dState.java => LogEmitterSharedState.java} | 8 +- .../opentelemetry/sdk/logs/LogProcessor.java | 14 ++- .../io/opentelemetry/sdk/logs/LogSink.java | 27 ---- .../sdk/logs/LogSinkSdkProviderBuilder.java | 53 -------- .../sdk/logs/MultiLogProcessor.java | 13 +- .../sdk/logs/NoopLogProcessor.java | 2 +- .../io/opentelemetry/sdk/logs/SdkLogSink.java | 34 ------ .../sdk/logs/SdkLogSinkBuilder.java | 36 ------ .../sdk/logs/SdkLogSinkProvider.java | 94 -------------- .../sdk/logs/data/LogBuilder.java | 35 ------ .../opentelemetry/sdk/logs/data/LogData.java | 75 +----------- .../sdk/logs/data/LogRecord.java | 115 +++++++++++------- .../sdk/logs/data/ReadableLogData.java | 44 +++++++ .../sdk/logs/data/ReadableLogRecord.java | 41 +++++++ ...der.java => ReadableLogRecordBuilder.java} | 57 +++------ .../sdk/logs/export/BatchLogProcessor.java | 4 +- .../sdk/logs/export/LogExporter.java | 6 +- .../opentelemetry/sdk/logs/package-info.java | 2 +- .../io/opentelemetry/sdk/logs/DemoTest.java | 12 +- ...rTest.java => LogEmitterProviderTest.java} | 64 ++++++---- .../sdk/logs/sdk/BatchLogProcessorTest.java | 37 +++--- .../sdk/logs/util/TestLogProcessor.java | 2 +- 36 files changed, 736 insertions(+), 658 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/{LogSinkSharedState.java => LogEmitterSharedState.java} (80%) delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{LogRecordBuilder.java => ReadableLogRecordBuilder.java} (52%) rename sdk/logs/src/test/java/io/opentelemetry/sdk/logs/{SdkLogSinkProviderTest.java => LogEmitterProviderTest.java} (66%) diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java index d03972a14f2..c7ffcfa37e6 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java @@ -14,7 +14,8 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.resources.Resource; @@ -31,30 +32,36 @@ class OtlpJsonLoggingLogExporterTest { Resource.create(Attributes.builder().put("key", "value").build()); private static final LogData LOG1 = - LogRecord.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation", "1")) - .setName("testLog1") - .setBody("body1") - .setFlags(0) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setSpanId("8765432112345876") - .setTraceId("12345678876543211234567887654322") - .setEpochMillis(1631533710L) - .setAttributes(Attributes.of(stringKey("animal"), "cat", longKey("lives"), 9L)) - .build(); + ReadableLogData.create( + RESOURCE, + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setName("testLog1") + .setBody("body1") + .setFlags(0) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setSpanId("8765432112345876") + .setTraceId("12345678876543211234567887654322") + .setEpochMillis(1631533710L) + .setAttributes(Attributes.of(stringKey("animal"), "cat", longKey("lives"), 9L)) + .build()); private static final LogData LOG2 = - LogRecord.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation2", "2")) - .setName("testLog2") - .setBody("body2") - .setFlags(0) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setSpanId("8765432112345875") - .setTraceId("12345678876543211234567887654322") - .setEpochMillis(1631533710L) - .setAttributes(Attributes.of(booleanKey("important"), true)) - .build(); + ReadableLogData.create( + RESOURCE, + InstrumentationLibraryInfo.create("instrumentation2", "2"), + ReadableLogRecord.builder() + .setName("testLog2") + .setBody("body2") + .setFlags(0) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setSpanId("8765432112345875") + .setTraceId("12345678876543211234567887654322") + .setEpochMillis(1631533710L) + .setAttributes(Attributes.of(booleanKey("important"), true)) + .build()); @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(OtlpJsonLoggingLogExporter.class); diff --git a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java index 33f1681b327..8ba9e4a2627 100644 --- a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java +++ b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java @@ -30,7 +30,8 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.IdGenerator; @@ -304,18 +305,19 @@ private static HttpResponse buildResponse(HttpStatus httpSta } private static LogData generateFakeLog() { - return LogRecord.builder( - Resource.getDefault(), - InstrumentationLibraryInfo.create("testLib", "1.0", "http://url")) - .setName("log-name") - .setBody(Body.stringBody("log body")) - .setAttributes(Attributes.builder().put("key", "value").build()) - .setSeverity(Severity.INFO) - .setSeverityText(Severity.INFO.name()) - .setTraceId(IdGenerator.random().generateTraceId()) - .setSpanId(IdGenerator.random().generateSpanId()) - .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) - .setFlags(0) - .build(); + return ReadableLogData.create( + Resource.getDefault(), + InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), + ReadableLogRecord.builder() + .setName("log-name") + .setBody(Body.stringBody("log body")) + .setAttributes(Attributes.builder().put("key", "value").build()) + .setSeverity(Severity.INFO) + .setSeverityText(Severity.INFO.name()) + .setTraceId(IdGenerator.random().generateTraceId()) + .setSpanId(IdGenerator.random().generateSpanId()) + .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) + .setFlags(0) + .build()); } } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java index 2781399df9d..a0d9b04223a 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java @@ -11,13 +11,14 @@ import io.opentelemetry.exporter.otlp.internal.Serializer; import io.opentelemetry.proto.collector.logs.v1.internal.ExportLogsServiceRequest; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; import io.opentelemetry.sdk.trace.data.SpanData; import java.io.IOException; import java.util.Collection; /** - * {@link Marshaler} to convert SDK {@link LogRecord} to OTLP ExportLogsServiceRequest. + * {@link Marshaler} to convert SDK {@link ReadableLogRecordBuilder} to OTLP + * ExportLogsServiceRequest. * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java index 810c45efd71..165722e7cee 100644 --- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java +++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java @@ -24,6 +24,8 @@ import io.opentelemetry.proto.logs.v1.LogRecord; import io.opentelemetry.proto.logs.v1.ResourceLogs; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.io.ByteArrayOutputStream; @@ -49,18 +51,19 @@ void toProtoResourceLogs() { ResourceLogsMarshaler[] resourceLogsMarshalers = ResourceLogsMarshaler.create( Collections.singleton( - io.opentelemetry.sdk.logs.data.LogRecord.builder( - Resource.builder().put("one", 1).setSchemaUrl("http://url").build(), - InstrumentationLibraryInfo.create("testLib", "1.0", "http://url")) - .setName(NAME) - .setBody(BODY) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setTraceId(TRACE_ID) - .setSpanId(SPAN_ID) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) - .build())); + ReadableLogData.create( + Resource.builder().put("one", 1).setSchemaUrl("http://url").build(), + InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), + ReadableLogRecord.builder() + .setName(NAME) + .setBody(BODY) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpochNanos(12345) + .build()))); assertThat(resourceLogsMarshalers).hasSize(1); @@ -82,18 +85,19 @@ void toProtoLogRecord() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - io.opentelemetry.sdk.logs.data.LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setName(NAME) - .setBody(BODY) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setTraceId(TRACE_ID) - .setSpanId(SPAN_ID) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) - .build())); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setName(NAME) + .setBody(BODY) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpochNanos(12345) + .build()))); assertThat(logRecord.getTraceId().toByteArray()).isEqualTo(TRACE_ID_BYTES); assertThat(logRecord.getSpanId().toByteArray()).isEqualTo(SPAN_ID_BYTES); @@ -115,14 +119,15 @@ void toProtoLogRecord_MinimalFields() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - io.opentelemetry.sdk.logs.data.LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setBody(BODY) - .setSeverity(Severity.INFO) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) - .build())); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setBody(BODY) + .setSeverity(Severity.INFO) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpochNanos(12345) + .build()))); assertThat(logRecord.getTraceId().toByteArray()).isEmpty(); assertThat(logRecord.getSpanId().toByteArray()).isEmpty(); diff --git a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java index 60827a30a6a..fc176730f65 100644 --- a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java +++ b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java @@ -32,7 +32,8 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.io.ByteArrayOutputStream; @@ -357,19 +358,20 @@ void usingGrpc() { } private static LogData generateFakeLog() { - return LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build(); + return ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); } private static final class FakeCollector extends LogsServiceGrpc.LogsServiceImplBase { diff --git a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 5b7e872ff72..a3622fae660 100644 --- a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,8 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -39,19 +40,20 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build()); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build())); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 5b7e872ff72..a3622fae660 100644 --- a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,8 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -39,19 +40,20 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build()); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build())); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 5b7e872ff72..a3622fae660 100644 --- a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,8 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -39,19 +40,20 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build()); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build())); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java index 02c2f08d281..cf2b40fd37b 100644 --- a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java +++ b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java @@ -20,7 +20,8 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.net.InetAddress; @@ -40,19 +41,20 @@ class OkHttpOnlyExportTest { private static final List LOGS = Collections.singletonList( - LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build()); + ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build())); private static final HeldCertificate HELD_CERTIFICATE; diff --git a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java index 3ba3766ee8f..87aebee2b78 100644 --- a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java +++ b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java @@ -52,7 +52,9 @@ import io.opentelemetry.proto.trace.v1.Span.Link; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -372,23 +374,23 @@ void testOtlpHttpLogExport(String compression) { } private static void testLogExporter(LogExporter logExporter) { - LogRecord logRecord = - LogRecord.builder( - RESOURCE, - InstrumentationLibraryInfo.create( - OtlpExporterIntegrationTest.class.getName(), null)) - .setName("log-name") - .setBody(Body.stringBody("log body")) - .setAttributes(Attributes.builder().put("key", "value").build()) - .setSeverity(Severity.DEBUG) - .setSeverityText("DEBUG") - .setTraceId(IdGenerator.random().generateTraceId()) - .setSpanId(IdGenerator.random().generateSpanId()) - .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) - .setFlags(0) - .build(); + LogData logData = + ReadableLogData.create( + RESOURCE, + InstrumentationLibraryInfo.create(OtlpExporterIntegrationTest.class.getName(), null), + ReadableLogRecord.builder() + .setName("log-name") + .setBody(Body.stringBody("log body")) + .setAttributes(Attributes.builder().put("key", "value").build()) + .setSeverity(Severity.DEBUG) + .setSeverityText("DEBUG") + .setTraceId(IdGenerator.random().generateTraceId()) + .setSpanId(IdGenerator.random().generateSpanId()) + .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) + .setFlags(0) + .build()); - logExporter.export(Collections.singletonList(logRecord)); + logExporter.export(Collections.singletonList(logData)); await() .atMost(Duration.ofSeconds(30)) @@ -422,14 +424,13 @@ private static void testLogExporter(LogExporter logExporter) { .setValue(AnyValue.newBuilder().setStringValue("value").build()) .build())); assertThat(protoLog.getSeverityNumber().getNumber()) - .isEqualTo(logRecord.getSeverity().getSeverityNumber()); + .isEqualTo(logData.getSeverity().getSeverityNumber()); assertThat(protoLog.getSeverityText()).isEqualTo("DEBUG"); assertThat(TraceId.fromBytes(protoLog.getTraceId().toByteArray())) - .isEqualTo(logRecord.getTraceId()); - assertThat(SpanId.fromBytes(protoLog.getSpanId().toByteArray())) - .isEqualTo(logRecord.getSpanId()); - assertThat(protoLog.getTimeUnixNano()).isEqualTo(logRecord.getEpochNanos()); - assertThat(protoLog.getFlags()).isEqualTo(logRecord.getFlags()); + .isEqualTo(logData.getTraceId()); + assertThat(SpanId.fromBytes(protoLog.getSpanId().toByteArray())).isEqualTo(logData.getSpanId()); + assertThat(protoLog.getTimeUnixNano()).isEqualTo(logData.getEpochNanos()); + assertThat(protoLog.getFlags()).isEqualTo(logData.getFlags()); } private static class OtlpGrpcServer extends ServerExtension { diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java new file mode 100644 index 00000000000..0cd65c163bd --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; +import io.opentelemetry.sdk.resources.Resource; + +/** + * A {@link LogEmitter} is the entry point into a log pipeline. Log emitters accept {@link + * ReadableLogRecordBuilder}, and after associating them with a {@link Resource} and {@link + * InstrumentationLibraryInfo}, pushes them to downstream {@link LogProcessor#emit(LogData)}. + */ +public final class LogEmitter { + + private final LogEmitterSharedState logEmitterSharedState; + private final InstrumentationLibraryInfo instrumentationLibraryInfo; + + LogEmitter( + LogEmitterSharedState logEmitterSharedState, + InstrumentationLibraryInfo instrumentationLibraryInfo) { + this.logEmitterSharedState = logEmitterSharedState; + this.instrumentationLibraryInfo = instrumentationLibraryInfo; + } + + /** + * Emit a log record. Associates the log with a {@link Resource} and {@link + * InstrumentationLibraryInfo}, and pushes it to {@link LogProcessor#emit(LogData)}. + * + * @param logRecord the log record + */ + public void emit(LogRecord logRecord) { + logEmitterSharedState + .getActiveLogProcessor() + .emit( + ReadableLogData.create( + logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java new file mode 100644 index 00000000000..b8185919796 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.internal.ComponentRegistry; +import javax.annotation.Nullable; + +/** Builder class for {@link LogEmitter} instances. */ +public final class LogEmitterBuilder { + + private final ComponentRegistry registry; + private final String instrumentationName; + @Nullable private String getInstrumentationVersion; + @Nullable private String schemaUrl; + + LogEmitterBuilder(ComponentRegistry registry, String instrumentationName) { + this.registry = registry; + this.instrumentationName = instrumentationName; + } + + /** + * Assign an OpenTelemetry schema URL to the resulting {@link LogEmitter}. + * + * @param schemaUrl the URL of the OpenTelemetry schema being used by this instrumentation library + * @return this + */ + public LogEmitterBuilder setSchemaUrl(String schemaUrl) { + this.schemaUrl = schemaUrl; + return this; + } + + /** + * Assign a version to the instrumenation library that is using the resulting {@link LogEmitter}. + * + * @param instrumentationVersion the versino of the instrumenation library + * @return this + */ + public LogEmitterBuilder setInstrumentationVersion(String instrumentationVersion) { + this.getInstrumentationVersion = instrumentationVersion; + return this; + } + + /** + * Gets or creates a {@link LogEmitter} instance. + * + * @return a log emitter instance configured with the provided options + */ + public LogEmitter build() { + return registry.get(instrumentationName, getInstrumentationVersion, schemaUrl); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java new file mode 100644 index 00000000000..50035397749 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java @@ -0,0 +1,107 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.internal.ComponentRegistry; +import io.opentelemetry.sdk.resources.Resource; +import java.io.Closeable; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** Provides instances of {@link LogEmitter}. */ +public final class LogEmitterProvider implements Closeable { + + private static final Logger LOGGER = Logger.getLogger(LogEmitterProvider.class.getName()); + private static final String DEFAULT_EMITTER_NAME = "unknown"; + + private final LogEmitterSharedState sharedState; + private final ComponentRegistry logEmitterComponentRegistry; + + /** + * Returns a new {@link LogEmitterProviderBuilder} for {@link LogEmitterProvider}. + * + * @return a new builder instance + */ + public static LogEmitterProviderBuilder builder() { + return new LogEmitterProviderBuilder(); + } + + LogEmitterProvider(Resource resource, List processors) { + this.sharedState = new LogEmitterSharedState(resource, processors); + this.logEmitterComponentRegistry = + new ComponentRegistry<>( + instrumentationLibraryInfo -> new LogEmitter(sharedState, instrumentationLibraryInfo)); + } + + /** + * Gets or creates a {@link LogEmitter} instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log emitter instance + */ + public LogEmitter get(String instrumentationName) { + return logEmitterBuilder(instrumentationName).build(); + } + + /** + * Gets or creates a {@link LogEmitter} instance. + * + * @param instrumentationName the name of the instrumentation library + * @param instrumentationVersion the version of the instrumentation library + * @return a log emitter instance + */ + public LogEmitter get(String instrumentationName, String instrumentationVersion) { + return logEmitterBuilder(instrumentationName) + .setInstrumentationVersion(instrumentationVersion) + .build(); + } + + /** + * Creates a {@link LogEmitterBuilder} instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log emitter builder instance + */ + public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) { + if (instrumentationName == null || instrumentationName.isEmpty()) { + LOGGER.fine("Meter requested without instrumentation name."); + instrumentationName = DEFAULT_EMITTER_NAME; + } + return new LogEmitterBuilder(logEmitterComponentRegistry, instrumentationName); + } + + /** + * Request the active log processor to process all logs that have not yet been processed. + * + * @return a {@link CompletableResultCode} which is completed when the flush is finished + */ + public CompletableResultCode forceFlush() { + return sharedState.getActiveLogProcessor().forceFlush(); + } + + /** + * Attempt to shut down the active log processor. + * + * @return a {@link CompletableResultCode} which is completed when the active log process has been + * shut down. + */ + public CompletableResultCode shutdown() { + if (sharedState.hasBeenShutdown()) { + LOGGER.log(Level.WARNING, "Calling shutdown() multiple times."); + return CompletableResultCode.ofSuccess(); + } + return sharedState.shutdown(); + } + + @Override + public void close() { + shutdown().join(10, TimeUnit.SECONDS); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java new file mode 100644 index 00000000000..3152c60d31b --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java @@ -0,0 +1,59 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.resources.Resource; +import java.util.ArrayList; +import java.util.List; + +/** Builder class for {@link LogEmitterProvider} instances. */ +public final class LogEmitterProviderBuilder { + + private final List logProcessors = new ArrayList<>(); + private Resource resource = Resource.getDefault(); + + LogEmitterProviderBuilder() {} + + /** + * Assign a {@link Resource} to be attached to all {@link LogData} created by {@link LogEmitter}s + * obtained from the {@link LogEmitterProvider}. + * + * @param resource the resource + * @return this + */ + public LogEmitterProviderBuilder setResource(Resource resource) { + requireNonNull(resource, "resource"); + this.resource = resource; + return this; + } + + /** + * Add a log processor. {@link LogProcessor#emit(LogData)} will be called each time {@link + * LogEmitter#emit(LogRecord)} is called for emitter instances obtained from the {@link + * LogEmitterProvider}. + * + * @param processor the log processor + * @return this + */ + public LogEmitterProviderBuilder addLogProcessor(LogProcessor processor) { + requireNonNull(processor, "processor"); + logProcessors.add(processor); + return this; + } + + /** + * Create a {@link LogEmitterProvider} instance. + * + * @return an instance configured with the provided options + */ + public LogEmitterProvider build() { + return new LogEmitterProvider(resource, logProcessors); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java similarity index 80% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java index e227bd22354..7239b6d23ee 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSharedState.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java @@ -10,13 +10,17 @@ import java.util.List; import javax.annotation.Nullable; -final class LogSinkSharedState { +/** + * Represents shared state and config between all {@link LogEmitter}s created by the same {@link + * LogEmitterProvider}. + */ +final class LogEmitterSharedState { private final Object lock = new Object(); private final Resource resource; private final LogProcessor activeLogProcessor; @Nullable private volatile CompletableResultCode shutdownResult = null; - LogSinkSharedState(Resource resource, List logProcessors) { + LogEmitterSharedState(Resource resource, List logProcessors) { this.resource = resource; this.activeLogProcessor = LogProcessor.composite(logProcessors); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java index da889dbec1e..08b3b4f727f 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java @@ -7,20 +7,27 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.LogRecord; import java.io.Closeable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.ThreadSafe; +/** + * {@link LogProcessor} is the interface to allow synchronous hooks for when {@link + * LogEmitter#emit(LogRecord)} is called. + */ +@ThreadSafe public interface LogProcessor extends Closeable { /** - * Process a log. + * Emit a log. * * @param logData the log */ - void process(LogData logData); + void emit(LogData logData); /** * Shutdown the log processor. @@ -40,6 +47,9 @@ default CompletableResultCode forceFlush() { return CompletableResultCode.ofSuccess(); } + /** + * Closes this {@link LogProcessor} after processing any remaining logs, releasing any resources. + */ @Override default void close() { shutdown().join(10, TimeUnit.SECONDS); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java deleted file mode 100644 index 6a17a6bae39..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSink.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import io.opentelemetry.sdk.logs.data.LogBuilder; -import io.opentelemetry.sdk.logs.data.LogData; - -/** A LogSink accepts logging records for transmission to an aggregator or log processing system. */ -public interface LogSink { - - /** - * Create a log builder. {@link LogBuilder#build()} can be passed to {@link #offer(LogData)}. - * - * @return the builder - */ - LogBuilder builder(); - - /** - * Pass the {@link LogData} to the sink. - * - * @param logData the log - */ - void offer(LogData logData); -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java deleted file mode 100644 index 816ce8fe21c..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogSinkSdkProviderBuilder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import static java.util.Objects.requireNonNull; - -import io.opentelemetry.sdk.resources.Resource; -import java.util.ArrayList; -import java.util.List; - -public final class LogSinkSdkProviderBuilder { - - private final List logProcessors = new ArrayList<>(); - private Resource resource = Resource.getDefault(); - - LogSinkSdkProviderBuilder() {} - - /** - * Set the resource. - * - * @param resource the resource - * @return this - */ - public LogSinkSdkProviderBuilder setResource(Resource resource) { - requireNonNull(resource, "resource"); - this.resource = resource; - return this; - } - - /** - * Add a log processor. - * - * @param processor the log processor - * @return this - */ - public LogSinkSdkProviderBuilder addLogProcessor(LogProcessor processor) { - requireNonNull(processor, "processor"); - logProcessors.add(processor); - return this; - } - - /** - * Create a {@link SdkLogSinkProvider} instance. - * - * @return an instance configured with the provided options - */ - public SdkLogSinkProvider build() { - return new SdkLogSinkProvider(resource, logProcessors); - } -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java index 985c45f7260..8f07c00a3b6 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/MultiLogProcessor.java @@ -12,20 +12,29 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; +/** + * Implementation of {@link LogProcessor} that forwards all logs to a list of {@link LogProcessor}s. + */ final class MultiLogProcessor implements LogProcessor { private final List logProcessors; private final AtomicBoolean isShutdown = new AtomicBoolean(false); + /** + * Create a new {@link MultiLogProcessor}. + * + * @param logProcessorsList list of log processors to forward logs to + * @return a multi log processor instance + */ static LogProcessor create(List logProcessorsList) { return new MultiLogProcessor( new ArrayList<>(Objects.requireNonNull(logProcessorsList, "logProcessorsList"))); } @Override - public void process(LogData logData) { + public void emit(LogData logData) { for (LogProcessor logProcessor : logProcessors) { - logProcessor.process(logData); + logProcessor.emit(logData); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java index 52b06182e9e..a7ef2f2f22d 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/NoopLogProcessor.java @@ -17,5 +17,5 @@ static LogProcessor getInstance() { private NoopLogProcessor() {} @Override - public void process(LogData logData) {} + public void emit(LogData logData) {} } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java deleted file mode 100644 index 5b4b106f93b..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSink.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.LogBuilder; -import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; - -class SdkLogSink implements LogSink { - - private final LogSinkSharedState logSinkSharedState; - private final InstrumentationLibraryInfo instrumentationLibraryInfo; - - SdkLogSink( - LogSinkSharedState logSinkSharedState, - InstrumentationLibraryInfo instrumentationLibraryInfo) { - this.logSinkSharedState = logSinkSharedState; - this.instrumentationLibraryInfo = instrumentationLibraryInfo; - } - - @Override - public void offer(LogData logData) { - logSinkSharedState.getActiveLogProcessor().process(logData); - } - - @Override - public LogBuilder builder() { - return LogRecord.builder(logSinkSharedState.getResource(), instrumentationLibraryInfo); - } -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java deleted file mode 100644 index 2ef7a9f1a89..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkBuilder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import io.opentelemetry.sdk.internal.ComponentRegistry; -import javax.annotation.Nullable; - -public final class SdkLogSinkBuilder { - - private final ComponentRegistry registry; - private final String instrumentationName; - @Nullable private String getInstrumentationVersion; - @Nullable private String schemaUrl; - - SdkLogSinkBuilder(ComponentRegistry registry, String instrumentationName) { - this.registry = registry; - this.instrumentationName = instrumentationName; - } - - public SdkLogSinkBuilder setSchemaUrl(String schemaUrl) { - this.schemaUrl = schemaUrl; - return this; - } - - public SdkLogSinkBuilder setInstrumentationVersion(String instrumentationVersion) { - this.getInstrumentationVersion = instrumentationVersion; - return this; - } - - public LogSink build() { - return registry.get(instrumentationName, getInstrumentationVersion, schemaUrl); - } -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java deleted file mode 100644 index 5477f9bc47a..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogSinkProvider.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.internal.ComponentRegistry; -import io.opentelemetry.sdk.resources.Resource; -import java.io.Closeable; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -public final class SdkLogSinkProvider implements Closeable { - private static final Logger logger = Logger.getLogger(SdkLogSinkProvider.class.getName()); - private final LogSinkSharedState sharedState; - private final ComponentRegistry logSinkSdkComponentRegistry; - - public static LogSinkSdkProviderBuilder builder() { - return new LogSinkSdkProviderBuilder(); - } - - SdkLogSinkProvider(Resource resource, List processors) { - this.sharedState = new LogSinkSharedState(resource, processors); - this.logSinkSdkComponentRegistry = - new ComponentRegistry<>( - instrumentationLibraryInfo -> new SdkLogSink(sharedState, instrumentationLibraryInfo)); - } - - /** - * Create a log sink instance. - * - * @param instrumentationName the name of the instrumentation library - * @return a log sink instance - */ - public LogSink get(String instrumentationName) { - return logSinkBuilder(instrumentationName).build(); - } - - /** - * Create a log sink instance. - * - * @param instrumentationName the name of the instrumentation library - * @param instrumentationVersion the version of the instrumentation library - * @return a log sink instance - */ - public LogSink get(String instrumentationName, String instrumentationVersion) { - return logSinkBuilder(instrumentationName) - .setInstrumentationVersion(instrumentationVersion) - .build(); - } - - /** - * Create a log sink builder. - * - * @param instrumentationName the name of the instrumentation library - * @return a log sink builder instance - */ - public SdkLogSinkBuilder logSinkBuilder(String instrumentationName) { - // TODO: should instrumentationName be nullable - return new SdkLogSinkBuilder(logSinkSdkComponentRegistry, instrumentationName); - } - - /** - * Request the active log processor to process all logs that have not yet been processed. - * - * @return a {@link CompletableResultCode} which is completed when the flush is finished - */ - public CompletableResultCode forceFlush() { - return sharedState.getActiveLogProcessor().forceFlush(); - } - - /** - * Attempt to shut down the active log processor. - * - * @return a {@link CompletableResultCode} which is completed when the active log process has been - * shut down. - */ - public CompletableResultCode shutdown() { - if (sharedState.hasBeenShutdown()) { - logger.log(Level.WARNING, "Calling shutdown() multiple times."); - return CompletableResultCode.ofSuccess(); - } - return sharedState.shutdown(); - } - - @Override - public void close() { - shutdown().join(10, TimeUnit.SECONDS); - } -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java deleted file mode 100644 index 5062f48e064..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogBuilder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs.data; - -import io.opentelemetry.api.common.Attributes; - -public interface LogBuilder { - - LogBuilder setEpochNanos(long timestamp); - - LogBuilder setEpochMillis(long timestamp); - - LogBuilder setTraceId(String traceId); - - LogBuilder setSpanId(String spanId); - - LogBuilder setFlags(int flags); - - LogBuilder setSeverity(Severity severity); - - LogBuilder setSeverityText(String severityText); - - LogBuilder setName(String name); - - LogBuilder setBody(Body body); - - LogBuilder setBody(String body); - - LogBuilder setAttributes(Attributes attributes); - - LogData build(); -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java index 4b5dd5a07f2..f95931634b5 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java @@ -5,19 +5,15 @@ package io.opentelemetry.sdk.logs.data; -import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.resources.Resource; -import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** - * The interface for a log as defined in the OpenTelemetry - * logging model. + * A {@link LogRecord} with an associated {@link Resource} and {@link InstrumentationLibraryInfo}. */ @Immutable -public interface LogData { +public interface LogData extends LogRecord { /** * Returns the resource of this log. @@ -32,71 +28,4 @@ public interface LogData { * @return an instance of {@link InstrumentationLibraryInfo}. */ InstrumentationLibraryInfo getInstrumentationLibraryInfo(); - - /** - * Returns the epoch timestamp in nanos when the log was recorded. - * - * @return the epoch timestamp in nanos. - */ - long getEpochNanos(); - - /** - * Returns the trace id for this log. - * - * @return the trace id. - */ - @Nullable - String getTraceId(); - - /** - * Returns the span id for this log. - * - * @return the span id. - */ - @Nullable - String getSpanId(); - - /** - * Returns the flags for this log. - * - * @return the flags. - */ - int getFlags(); - - /** - * Returns the severity for this log. - * - * @return the severity. - */ - Severity getSeverity(); - - /** - * Returns the severity text for this log. - * - * @return the severity text. - */ - @Nullable - String getSeverityText(); - - /** - * Returns the name for this log. - * - * @return the name. - */ - @Nullable - String getName(); - - /** - * Returns the body for this log. - * - * @return the body. - */ - Body getBody(); - - /** - * Returns the attributes for this log. - * - * @return the attributes. - */ - Attributes getAttributes(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java index c24bd4cf991..ba739ee66f0 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java @@ -5,47 +5,80 @@ package io.opentelemetry.sdk.logs.data; -import com.google.auto.value.AutoValue; import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.resources.Resource; import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -@Immutable -@AutoValue -public abstract class LogRecord implements LogData { - - LogRecord() {} - - public static LogRecordBuilder builder( - Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) { - return new LogRecordBuilder(resource, instrumentationLibraryInfo); - } - - static LogRecord create( - Resource resource, - InstrumentationLibraryInfo instrumentationLibraryInfo, - long epochNanos, - @Nullable String traceId, - @Nullable String spanId, - int flags, - Severity severity, - @Nullable String severityText, - @Nullable String name, - Body body, - Attributes attributes) { - return new AutoValue_LogRecord( - resource, - instrumentationLibraryInfo, - epochNanos, - traceId, - spanId, - flags, - severity, - severityText, - name, - body, - attributes); - } + +/** + * Implementation of a log as defined in OpenTelemetry + * Log Data Model. + */ +public interface LogRecord { + + /** + * Returns the epoch timestamp in nanos when the log was recorded. + * + * @return the epoch timestamp in nanos + */ + long getEpochNanos(); + + /** + * Returns the trace id for this log. + * + * @return the trace id + */ + @Nullable + String getTraceId(); + + /** + * Returns the span id for this log. + * + * @return the span id + */ + @Nullable + String getSpanId(); + + /** + * Returns the flags for this log. + * + * @return the flags + */ + int getFlags(); + + /** + * Returns the severity for this log. + * + * @return the severity + */ + Severity getSeverity(); + + /** + * Returns the severity text for this log. + * + * @return the severity text + */ + @Nullable + String getSeverityText(); + + /** + * Returns the name for this log. + * + * @return the name + */ + @Nullable + String getName(); + + /** + * Returns the body for this log. + * + * @return the body + */ + Body getBody(); + + /** + * Returns the attributes for this log. + * + * @return the attributes + */ + Attributes getAttributes(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java new file mode 100644 index 00000000000..65c536e9861 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java @@ -0,0 +1,44 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs.data; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.resources.Resource; +import javax.annotation.concurrent.Immutable; + +@AutoValue +@Immutable +public abstract class ReadableLogData implements LogData { + + ReadableLogData() {} + + /** + * Create a {@link ReadableLogData} instance. + * + * @param resource the resource + * @param instrumentationLibraryInfo the instrumentation library info + * @param logRecord the log record + * @return the instance + */ + public static ReadableLogData create( + Resource resource, + InstrumentationLibraryInfo instrumentationLibraryInfo, + LogRecord logRecord) { + return new AutoValue_ReadableLogData( + logRecord.getEpochNanos(), + logRecord.getTraceId(), + logRecord.getSpanId(), + logRecord.getFlags(), + logRecord.getSeverity(), + logRecord.getSeverityText(), + logRecord.getName(), + logRecord.getBody(), + logRecord.getAttributes(), + resource, + instrumentationLibraryInfo); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java new file mode 100644 index 00000000000..2458e565af1 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs.data; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.api.common.Attributes; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@AutoValue +@Immutable +public abstract class ReadableLogRecord implements LogRecord { + + ReadableLogRecord() {} + + /** + * Create a {@link ReadableLogRecordBuilder} instance. + * + * @return the instance + */ + public static ReadableLogRecordBuilder builder() { + return new ReadableLogRecordBuilder(); + } + + static ReadableLogRecord create( + long epochNanos, + @Nullable String traceId, + @Nullable String spanId, + int flags, + Severity severity, + @Nullable String severityText, + @Nullable String name, + Body body, + Attributes attributes) { + return new AutoValue_ReadableLogRecord( + epochNanos, traceId, spanId, flags, severity, severityText, name, body, attributes); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java similarity index 52% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java index 1d050ee6d0d..97b0db4c3f6 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java @@ -7,15 +7,11 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.resources.Resource; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -/** Builder for {@link LogRecord}. */ -public final class LogRecordBuilder implements LogBuilder { - private final Resource resource; - private final InstrumentationLibraryInfo instrumentationLibraryInfo; +/** Builder for {@link ReadableLogRecordBuilder}. */ +public final class ReadableLogRecordBuilder { private long epochNanos; @Nullable private String traceId; @@ -27,88 +23,71 @@ public final class LogRecordBuilder implements LogBuilder { private Body body = Body.stringBody(""); private final AttributesBuilder attributeBuilder = Attributes.builder(); - LogRecordBuilder(Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) { - this.resource = resource; - this.instrumentationLibraryInfo = instrumentationLibraryInfo; - } + ReadableLogRecordBuilder() {} - @Override - public LogRecordBuilder setEpochNanos(long timestamp) { + public ReadableLogRecordBuilder setEpochNanos(long timestamp) { this.epochNanos = timestamp; return this; } - @Override - public LogRecordBuilder setEpochMillis(long timestamp) { + public ReadableLogRecordBuilder setEpochMillis(long timestamp) { return setEpochNanos(TimeUnit.MILLISECONDS.toNanos(timestamp)); } - @Override - public LogRecordBuilder setTraceId(String traceId) { + public ReadableLogRecordBuilder setTraceId(String traceId) { this.traceId = traceId; return this; } - @Override - public LogRecordBuilder setSpanId(String spanId) { + public ReadableLogRecordBuilder setSpanId(String spanId) { this.spanId = spanId; return this; } - @Override - public LogRecordBuilder setFlags(int flags) { + public ReadableLogRecordBuilder setFlags(int flags) { this.flags = flags; return this; } - @Override - public LogRecordBuilder setSeverity(Severity severity) { + public ReadableLogRecordBuilder setSeverity(Severity severity) { this.severity = severity; return this; } - @Override - public LogRecordBuilder setSeverityText(String severityText) { + public ReadableLogRecordBuilder setSeverityText(String severityText) { this.severityText = severityText; return this; } - @Override - public LogRecordBuilder setName(String name) { + public ReadableLogRecordBuilder setName(String name) { this.name = name; return this; } - @Override - public LogRecordBuilder setBody(Body body) { + public ReadableLogRecordBuilder setBody(Body body) { this.body = body; return this; } - @Override - public LogRecordBuilder setBody(String body) { + public ReadableLogRecordBuilder setBody(String body) { return setBody(Body.stringBody(body)); } - @Override - public LogRecordBuilder setAttributes(Attributes attributes) { + public ReadableLogRecordBuilder setAttributes(Attributes attributes) { this.attributeBuilder.putAll(attributes); return this; } /** - * Build a LogRecord instance. + * Build a {@link ReadableLogRecord} instance. * - * @return value object being built + * @return the instance */ - @Override - public LogRecord build() { + public ReadableLogRecord build() { if (epochNanos == 0) { epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); } - return LogRecord.create( - resource, - instrumentationLibraryInfo, + return ReadableLogRecord.create( epochNanos, traceId, spanId, diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java index f53ff773c60..8f6b4cb3177 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/BatchLogProcessor.java @@ -50,7 +50,7 @@ public static BatchLogProcessorBuilder builder(LogExporter logExporter) { } @Override - public void process(LogData logData) { + public void emit(LogData logData) { worker.addLog(logData); } @@ -68,7 +68,7 @@ public CompletableResultCode forceFlush() { private static class Worker implements Runnable { static { // TODO: As of Specification 1.4, this should have a telemetry schema version. - Meter meter = GlobalMeterProvider.get().meterBuilder("io.opentelemetry.sdk.trace").build(); + Meter meter = GlobalMeterProvider.get().meterBuilder("io.opentelemetry.sdk.logs").build(); LongCounter logRecordsProcessed = meter .counterBuilder("logRecordsProcessed") diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java index 6f0e2299810..43227bacdc0 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java @@ -7,12 +7,12 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; import java.util.Collection; /** - * An exporter is responsible for taking a list of {@link LogRecord}s and transmitting them to their - * ultimate destination. + * An exporter is responsible for taking a list of {@link ReadableLogRecordBuilder}s and + * transmitting them to their ultimate destination. */ public interface LogExporter { CompletableResultCode export(Collection logs); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java index 7607958fb84..1ee6fd83a10 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java @@ -6,7 +6,7 @@ /** * The OpenTelemetry SDK implementation of logging. * - * @see io.opentelemetry.sdk.logs.SdkLogSinkProvider + * @see io.opentelemetry.sdk.logs.LogEmitterProvider */ @ParametersAreNonnullByDefault package io.opentelemetry.sdk.logs; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java index 34e39927928..f67a096232f 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.export.BatchLogProcessor; import io.opentelemetry.sdk.logs.util.TestLogExporter; import io.opentelemetry.sdk.resources.Resource; @@ -26,20 +27,19 @@ class DemoTest { void usageTest() { TestLogExporter testLogExporter = new TestLogExporter(); - SdkLogSinkProvider sdkLogSinkProvider = - SdkLogSinkProvider.builder() + LogEmitterProvider logEmitterProvider = + LogEmitterProvider.builder() .setResource(Resource.builder().put("key", "value").build()) .addLogProcessor(System.out::println) .addLogProcessor( BatchLogProcessor.builder(testLogExporter).setExporterTimeoutMillis(1000).build()) .build(); - LogSink logSink = sdkLogSinkProvider.get("my-library"); + LogEmitter logEmitter = logEmitterProvider.get("my-library"); for (int i = 0; i < 10; i++) { - logSink.offer( - logSink - .builder() + logEmitter.emit( + ReadableLogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setBody("my message " + i) .setAttributes(Attributes.builder().put("foo", "bar").build()) diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java similarity index 66% rename from sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java rename to sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java index 13d35b390a0..6ee2386498a 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogSinkProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java @@ -17,6 +17,8 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.BatchLogProcessor; import io.opentelemetry.sdk.logs.util.TestLogExporter; @@ -27,12 +29,18 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; -class SdkLogSinkProviderTest { +class LogEmitterProviderTest { - private static LogRecord createLog(Severity severity, String message) { - return LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) + private static final String INSTRUMENTATION_LIBRARY = + LogEmitterProviderTest.class.getSimpleName(); + private static final String INSTRUMENTATION_LIBRARY_VERSION = "0.1"; + private static final Resource RESOURCE = + Resource.create(Attributes.builder().put("key", "value").build()); + private static final InstrumentationLibraryInfo INSTRUMENTATION_LIBRARY_INFO = + InstrumentationLibraryInfo.create(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); + + private static LogRecord createLogRecord(Severity severity, String message) { + return ReadableLogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) @@ -45,18 +53,22 @@ private static LogRecord createLog(Severity severity, String message) { .build(); } + private static LogData toLogData(LogRecord logRecord) { + return ReadableLogData.create(RESOURCE, INSTRUMENTATION_LIBRARY_INFO, logRecord); + } + @Test - void testLogSinkSdkProvider() { + void testLogEmitterProvider() { TestLogExporter exporter = new TestLogExporter(); LogProcessor processor = BatchLogProcessor.builder(exporter).build(); - SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); - LogSink sink = provider.get("test", "0.1a"); - LogRecord log = createLog(Severity.ERROR, "test"); - sink.offer(log); + LogEmitterProvider provider = + LogEmitterProvider.builder().setResource(RESOURCE).addLogProcessor(processor).build(); + LogEmitter emitter = provider.get(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); + LogRecord logRecord = createLogRecord(Severity.ERROR, "test"); + emitter.emit(logRecord); provider.forceFlush().join(500, TimeUnit.MILLISECONDS); List records = exporter.getRecords(); - assertThat(records).singleElement().isEqualTo(log); - assertThat(log.getSeverity().getSeverityNumber()).isEqualTo(Severity.ERROR.getSeverityNumber()); + assertThat(records).singleElement().isEqualTo(toLogData(logRecord)); } @Test @@ -68,11 +80,11 @@ void testBatchSize() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); - LogSink sink = provider.get("test", "0.1a"); + LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + LogEmitter emitter = provider.get("test", "0.1a"); for (int i = 0; i < 7; i++) { - sink.offer(createLog(Severity.WARN, "test #" + i)); + emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); } // Ensure that more than batch size kicks off a flush await().atMost(Duration.ofSeconds(5)).until(() -> exporter.getRecords().size() > 0); @@ -99,13 +111,13 @@ void testNoBlocking() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - SdkLogSinkProvider provider = SdkLogSinkProvider.builder().addLogProcessor(processor).build(); - LogSink sink = provider.get("test", "0.1a"); + LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + LogEmitter emitter = provider.get("test", "0.1a"); long start = System.currentTimeMillis(); int testRecordCount = 700; for (int i = 0; i < testRecordCount; i++) { - sink.offer(createLog(Severity.WARN, "test #" + i)); + emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); } long end = System.currentTimeMillis(); assertThat(end - start).isLessThan(250L); @@ -117,18 +129,20 @@ void testNoBlocking() { void testMultipleProcessors() { TestLogProcessor processorOne = new TestLogProcessor(); TestLogProcessor processorTwo = new TestLogProcessor(); - SdkLogSinkProvider provider = - SdkLogSinkProvider.builder() + LogEmitterProvider provider = + LogEmitterProvider.builder() + .setResource(RESOURCE) .addLogProcessor(processorOne) .addLogProcessor(processorTwo) .build(); - LogSink sink = provider.get("test", "0.1"); - LogRecord record = createLog(Severity.INFO, "test"); - sink.offer(record); + LogEmitter emitter = provider.get(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); + LogRecord logRecord = createLogRecord(Severity.INFO, "test"); + emitter.emit(logRecord); + LogData logData = toLogData(logRecord); assertThat(processorOne.getRecords().size()).isEqualTo(1); assertThat(processorTwo.getRecords().size()).isEqualTo(1); - assertThat(processorOne.getRecords().get(0)).isEqualTo(record); - assertThat(processorTwo.getRecords().get(0)).isEqualTo(record); + assertThat(processorOne.getRecords().get(0)).isEqualTo(logData); + assertThat(processorTwo.getRecords().get(0)).isEqualTo(logData); CompletableResultCode flushResult = provider.forceFlush(); flushResult.join(1, TimeUnit.SECONDS); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java index 18bb41c75b1..34590d8f9e0 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/sdk/BatchLogProcessorTest.java @@ -13,7 +13,9 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceId; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.ReadableLogData; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.BatchLogProcessor; import io.opentelemetry.sdk.logs.util.TestLogExporter; @@ -23,20 +25,21 @@ class BatchLogProcessorTest { - private static LogRecord createLog(Severity severity, String message) { - return LogRecord.builder( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1")) - .setEpochMillis(System.currentTimeMillis()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(severity) - .setSeverityText("really severe") - .setName("log1") - .setBody(message) - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build(); + private static LogData createLogData(Severity severity, String message) { + return ReadableLogData.create( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1"), + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(severity) + .setSeverityText("really severe") + .setName("log1") + .setBody(message) + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); } @Test @@ -51,8 +54,8 @@ void testForceExport() { .setScheduleDelayMillis(2000) // longer than test .build(); for (int i = 0; i < 17; i++) { - LogRecord record = createLog(Severity.INFO, Integer.toString(i)); - processor.process(record); + LogData logData = createLogData(Severity.INFO, Integer.toString(i)); + processor.emit(logData); } await().until(() -> exporter.getCallCount() > 0); assertThat(exporter.getRecords().size()).isEqualTo(batchSize); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java index 0535c57b222..5fcd4041d2f 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java @@ -17,7 +17,7 @@ public class TestLogProcessor implements LogProcessor { private int flushes = 0; @Override - public void process(LogData logData) { + public void emit(LogData logData) { records.add(logData); } From d7208c3339d9686a8670f4d59f080f51354888ee Mon Sep 17 00:00:00 2001 From: jack-berg Date: Mon, 18 Oct 2021 13:55:32 -0500 Subject: [PATCH 06/13] Fix typo --- .../main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java index 50035397749..5c3182851e5 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java @@ -71,7 +71,7 @@ public LogEmitter get(String instrumentationName, String instrumentationVersion) */ public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) { if (instrumentationName == null || instrumentationName.isEmpty()) { - LOGGER.fine("Meter requested without instrumentation name."); + LOGGER.fine("LogEmitter requested without instrumentation name."); instrumentationName = DEFAULT_EMITTER_NAME; } return new LogEmitterBuilder(logEmitterComponentRegistry, instrumentationName); From 95274e78045e558c4bee741ae598472a058fa08f Mon Sep 17 00:00:00 2001 From: jack-berg Date: Tue, 19 Oct 2021 17:19:48 -0500 Subject: [PATCH 07/13] Add unit tests --- .../io/opentelemetry/sdk/logs/LogEmitter.java | 8 +- .../sdk/logs/LogEmitterProvider.java | 2 +- .../io/opentelemetry/sdk/logs/DemoTest.java | 70 ----- .../sdk/logs/LogEmitterProviderTest.java | 256 ++++++++++-------- .../sdk/logs/LogEmitterTest.java | 67 +++++ .../sdk/logs/MultiLogProcessorTest.java | 70 +++++ .../sdk/logs/NoopLogProcessorTest.java | 23 ++ .../logs/export/BatchLogProcessorTest.java | 63 +++++ .../sdk/logs/util/TestLogProcessor.java | 47 ---- 9 files changed, 378 insertions(+), 228 deletions(-) delete mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java create mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java create mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogProcessorTest.java create mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogProcessorTest.java delete mode 100644 sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java index 0cd65c163bd..b34e99b849b 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java @@ -9,12 +9,11 @@ import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; import io.opentelemetry.sdk.resources.Resource; /** * A {@link LogEmitter} is the entry point into a log pipeline. Log emitters accept {@link - * ReadableLogRecordBuilder}, and after associating them with a {@link Resource} and {@link + * LogRecord}, and after associating them with a {@link Resource} and {@link * InstrumentationLibraryInfo}, pushes them to downstream {@link LogProcessor#emit(LogData)}. */ public final class LogEmitter { @@ -42,4 +41,9 @@ public void emit(LogRecord logRecord) { ReadableLogData.create( logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); } + + // VisibleForTesting + InstrumentationLibraryInfo getInstrumentationLibraryInfo() { + return instrumentationLibraryInfo; + } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java index 5c3182851e5..fb698831075 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java @@ -18,8 +18,8 @@ /** Provides instances of {@link LogEmitter}. */ public final class LogEmitterProvider implements Closeable { + static final String DEFAULT_EMITTER_NAME = "unknown"; private static final Logger LOGGER = Logger.getLogger(LogEmitterProvider.class.getName()); - private static final String DEFAULT_EMITTER_NAME = "unknown"; private final LogEmitterSharedState sharedState; private final ComponentRegistry logEmitterComponentRegistry; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java deleted file mode 100644 index f67a096232f..00000000000 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/DemoTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; -import io.opentelemetry.sdk.logs.export.BatchLogProcessor; -import io.opentelemetry.sdk.logs.util.TestLogExporter; -import io.opentelemetry.sdk.resources.Resource; -import java.time.Duration; -import java.util.List; -import java.util.function.Consumer; -import org.junit.jupiter.api.Test; - -class DemoTest { - - @Test - @SuppressWarnings("SystemOut") - void usageTest() { - TestLogExporter testLogExporter = new TestLogExporter(); - - LogEmitterProvider logEmitterProvider = - LogEmitterProvider.builder() - .setResource(Resource.builder().put("key", "value").build()) - .addLogProcessor(System.out::println) - .addLogProcessor( - BatchLogProcessor.builder(testLogExporter).setExporterTimeoutMillis(1000).build()) - .build(); - - LogEmitter logEmitter = logEmitterProvider.get("my-library"); - - for (int i = 0; i < 10; i++) { - logEmitter.emit( - ReadableLogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) - .setBody("my message " + i) - .setAttributes(Attributes.builder().put("foo", "bar").build()) - .build()); - } - - await() - .atMost(Duration.ofSeconds(30)) - .untilAsserted( - () -> { - List logs = testLogExporter.getRecords(); - - assertThat(logs.size()).isEqualTo(10); - assertThat(logs) - .allSatisfy( - (Consumer) - logData -> { - assertThat(logData.getResource()) - .isEqualTo(Resource.builder().put("key", "value").build()); - assertThat(logData.getInstrumentationLibraryInfo()) - .isEqualTo(InstrumentationLibraryInfo.create("my-library", null)); - assertThat(logData.getBody().asString()).startsWith("my message"); - assertThat(logData.getAttributes()) - .isEqualTo(Attributes.builder().put("foo", "bar").build()); - }); - }); - } -} diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java index 9d95eb59a93..38147986ea1 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java @@ -5,136 +5,176 @@ package io.opentelemetry.sdk.logs; -import static io.opentelemetry.sdk.logs.util.TestUtil.createLogRecord; +import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.awaitility.Awaitility.await; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.Severity; -import io.opentelemetry.sdk.logs.export.BatchLogProcessor; -import io.opentelemetry.sdk.logs.util.TestLogExporter; -import io.opentelemetry.sdk.logs.util.TestLogProcessor; import io.opentelemetry.sdk.resources.Resource; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.TimeUnit; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) class LogEmitterProviderTest { - private static final String INSTRUMENTATION_LIBRARY = - LogEmitterProviderTest.class.getSimpleName(); - private static final String INSTRUMENTATION_LIBRARY_VERSION = "0.1"; - private static final Resource RESOURCE = - Resource.create(Attributes.builder().put("key", "value").build()); - private static final InstrumentationLibraryInfo INSTRUMENTATION_LIBRARY_INFO = - InstrumentationLibraryInfo.create(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); + @Mock private LogProcessor logProcessor; - private static LogData toLogData(LogRecord logRecord) { - return ReadableLogData.create(RESOURCE, INSTRUMENTATION_LIBRARY_INFO, logRecord); + private LogEmitterProvider logEmitterProvider; + + @BeforeEach + void setup() { + logEmitterProvider = LogEmitterProvider.builder().addLogProcessor(logProcessor).build(); + when(logProcessor.forceFlush()).thenReturn(CompletableResultCode.ofSuccess()); + when(logProcessor.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + } + + @Test + void builder_defaultResource() { + assertThat(LogEmitterProvider.builder().build()) + .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) + .extracting(LogEmitterSharedState::getResource) + .isEqualTo(Resource.getDefault()); + } + + @Test + void builder_resourceProvided() { + Resource resource = Resource.create(Attributes.builder().put("key", "value").build()); + + assertThat(LogEmitterProvider.builder().setResource(resource).build()) + .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) + .extracting(LogEmitterSharedState::getResource) + .isEqualTo(resource); + } + + @Test + void builder_noProcessor() { + assertThat(LogEmitterProvider.builder().build()) + .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) + .extracting(LogEmitterSharedState::getActiveLogProcessor) + .isSameAs(NoopLogProcessor.getInstance()); + } + + @Test + void builder_multipleProcessors() { + assertThat( + LogEmitterProvider.builder() + .addLogProcessor(logProcessor) + .addLogProcessor(logProcessor) + .build()) + .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) + .extracting(LogEmitterSharedState::getActiveLogProcessor) + .satisfies( + activeLogProcessor -> { + assertThat(activeLogProcessor).isInstanceOf(MultiLogProcessor.class); + assertThat(activeLogProcessor) + .extracting( + "logProcessors", as(InstanceOfAssertFactories.list(LogProcessor.class))) + .hasSize(2); + }); } @Test - void testLogEmitterProvider() { - TestLogExporter exporter = new TestLogExporter(); - LogProcessor processor = BatchLogProcessor.builder(exporter).build(); - LogEmitterProvider provider = - LogEmitterProvider.builder().setResource(RESOURCE).addLogProcessor(processor).build(); - LogEmitter emitter = provider.get(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); - LogRecord logRecord = createLogRecord(Severity.ERROR, "test"); - emitter.emit(logRecord); - provider.forceFlush().join(500, TimeUnit.MILLISECONDS); - List records = exporter.getRecords(); - assertThat(records).singleElement().isEqualTo(toLogData(logRecord)); + void get_SameName() { + assertThat(logEmitterProvider.get("test")) + .isSameAs(logEmitterProvider.get("test")) + .isSameAs(logEmitterProvider.get("test", null)) + .isSameAs(logEmitterProvider.logEmitterBuilder("test").build()) + .isNotSameAs(logEmitterProvider.get("test", "version")); + } + + @Test + void get_SameNameAndVersion() { + assertThat(logEmitterProvider.get("test", "version")) + .isSameAs(logEmitterProvider.get("test", "version")) + .isSameAs( + logEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .build()) + .isNotSameAs( + logEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .setSchemaUrl("http://url") + .build()); + } + + @Test + void logEmitterBuilder_SameNameVersionAndSchema() { + assertThat( + logEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .setSchemaUrl("http://url") + .build()) + .isSameAs( + logEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .setSchemaUrl("http://url") + .build()); + } + + @Test + void logEmitterBuilder_PropagatesToEmitter() { + InstrumentationLibraryInfo expected = + InstrumentationLibraryInfo.create("test", "version", "http://url"); + assertThat( + logEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .setSchemaUrl("http://url") + .build() + .getInstrumentationLibraryInfo()) + .isEqualTo(expected); + } + + @Test + void logEmitterBuilder_DefaultEmitterName() { + assertThat( + logEmitterProvider + .logEmitterBuilder(null) + .build() + .getInstrumentationLibraryInfo() + .getName()) + .isEqualTo(LogEmitterProvider.DEFAULT_EMITTER_NAME); + + assertThat( + logEmitterProvider + .logEmitterBuilder("") + .build() + .getInstrumentationLibraryInfo() + .getName()) + .isEqualTo(LogEmitterProvider.DEFAULT_EMITTER_NAME); } @Test - void testBatchSize() { - TestLogExporter exporter = new TestLogExporter(); - LogProcessor processor = - BatchLogProcessor.builder(exporter) - .setScheduleDelayMillis(10000) // Long enough to not be in play - .setMaxExportBatchSize(5) - .setMaxQueueSize(10) - .build(); - LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); - LogEmitter emitter = provider.get("test", "0.1a"); - - for (int i = 0; i < 7; i++) { - emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); - } - // Ensure that more than batch size kicks off a flush - await().atMost(Duration.ofSeconds(5)).until(() -> exporter.getRecords().size() > 0); - // Ensure that everything gets through - CompletableResultCode result = provider.forceFlush(); - result.join(1, TimeUnit.SECONDS); - assertThat(exporter.getCallCount()).isGreaterThanOrEqualTo(2); + void forceFlush() { + logEmitterProvider.forceFlush(); + verify(logProcessor).forceFlush(); } @Test - void testNoBlocking() { - TestLogExporter exporter = new TestLogExporter(); - exporter.setOnCall( - () -> { - try { - Thread.sleep(250); - } catch (InterruptedException ex) { - fail("Exporter wait interrupted", ex); - } - }); - LogProcessor processor = - BatchLogProcessor.builder(exporter) - .setScheduleDelayMillis(3000) // Long enough to not be in play - .setMaxExportBatchSize(5) - .setMaxQueueSize(10) - .build(); - LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); - LogEmitter emitter = provider.get("test", "0.1a"); - - long start = System.currentTimeMillis(); - int testRecordCount = 700; - for (int i = 0; i < testRecordCount; i++) { - emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); - } - long end = System.currentTimeMillis(); - assertThat(end - start).isLessThan(250L); - provider.forceFlush().join(1, TimeUnit.SECONDS); - assertThat(exporter.getRecords().size()).isLessThan(testRecordCount); // We dropped records + void shutdown() { + logEmitterProvider.shutdown(); + logEmitterProvider.shutdown(); + verify(logProcessor, times(1)).shutdown(); } @Test - void testMultipleProcessors() { - TestLogProcessor processorOne = new TestLogProcessor(); - TestLogProcessor processorTwo = new TestLogProcessor(); - LogEmitterProvider provider = - LogEmitterProvider.builder() - .setResource(RESOURCE) - .addLogProcessor(processorOne) - .addLogProcessor(processorTwo) - .build(); - LogEmitter emitter = provider.get(INSTRUMENTATION_LIBRARY, INSTRUMENTATION_LIBRARY_VERSION); - LogRecord logRecord = createLogRecord(Severity.INFO, "test"); - emitter.emit(logRecord); - LogData logData = toLogData(logRecord); - assertThat(processorOne.getRecords().size()).isEqualTo(1); - assertThat(processorTwo.getRecords().size()).isEqualTo(1); - assertThat(processorOne.getRecords().get(0)).isEqualTo(logData); - assertThat(processorTwo.getRecords().get(0)).isEqualTo(logData); - - CompletableResultCode flushResult = provider.forceFlush(); - flushResult.join(1, TimeUnit.SECONDS); - assertThat(processorOne.getFlushes()).isEqualTo(1); - assertThat(processorTwo.getFlushes()).isEqualTo(1); - - CompletableResultCode shutdownResult = provider.shutdown(); - shutdownResult.join(1, TimeUnit.SECONDS); - assertThat(processorOne.shutdownHasBeenCalled()).isEqualTo(true); - assertThat(processorTwo.shutdownHasBeenCalled()).isEqualTo(true); + void close() { + logEmitterProvider.close(); + verify(logProcessor).shutdown(); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java new file mode 100644 index 00000000000..a90e12eeb3f --- /dev/null +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; + +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.Body; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.resources.Resource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class LogEmitterTest { + + private static final String INSTRUMENTATION_LIBRARY_NAME = LogEmitter.class.getName(); + private static final String INSTRUMENTATION_LIBRARY_VERSION = "0.0.1"; + private static final String SCHEMA_URL = "http://schemaurl"; + + @Mock private LogProcessor logProcessor; + private LogEmitter logEmitter; + + @BeforeEach + void setup() { + logEmitter = + LogEmitterProvider.builder() + .addLogProcessor(logProcessor) + .build() + .logEmitterBuilder(INSTRUMENTATION_LIBRARY_NAME) + .setInstrumentationVersion(INSTRUMENTATION_LIBRARY_VERSION) + .setSchemaUrl(SCHEMA_URL) + .build(); + } + + @Test + void emit() { + LogRecord logRecord = + ReadableLogRecord.builder() + .setEpochMillis(System.currentTimeMillis()) + .setBody(Body.stringBody("message")) + .build(); + logEmitter.emit(logRecord); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LogData.class); + verify(logProcessor).emit(captor.capture()); + + LogData logData = captor.getValue(); + assertThat(logData.getResource()).isEqualTo(Resource.getDefault()); + assertThat(logData.getInstrumentationLibraryInfo()) + .isEqualTo( + InstrumentationLibraryInfo.create( + INSTRUMENTATION_LIBRARY_NAME, INSTRUMENTATION_LIBRARY_VERSION, SCHEMA_URL)); + assertThat(logData.getEpochNanos()).isEqualTo(logRecord.getEpochNanos()); + assertThat(logData.getBody()).isEqualTo(logRecord.getBody()); + } +} diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogProcessorTest.java new file mode 100644 index 00000000000..5d8e1c23585 --- /dev/null +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/MultiLogProcessorTest.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.data.LogData; +import io.opentelemetry.sdk.logs.data.Severity; +import io.opentelemetry.sdk.logs.util.TestUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class MultiLogProcessorTest { + + @Mock private LogProcessor logProcessor1; + @Mock private LogProcessor logProcessor2; + private static final LogData logData = TestUtil.createLogData(Severity.DEBUG, "message"); + + @BeforeEach + void setup() { + when(logProcessor1.forceFlush()).thenReturn(CompletableResultCode.ofSuccess()); + when(logProcessor2.forceFlush()).thenReturn(CompletableResultCode.ofSuccess()); + when(logProcessor1.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + when(logProcessor2.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + } + + @Test + void empty() { + LogProcessor multiLogProcessor = LogProcessor.composite(); + assertThat(multiLogProcessor).isInstanceOf(NoopLogProcessor.class); + multiLogProcessor.emit(logData); + multiLogProcessor.shutdown(); + } + + @Test + void oneLogProcessor() { + LogProcessor multiLogProcessor = LogProcessor.composite(logProcessor1); + assertThat(multiLogProcessor).isSameAs(logProcessor1); + } + + @Test + void twoLogProcessor() { + LogProcessor multiLogProcessor = LogProcessor.composite(logProcessor1, logProcessor2); + multiLogProcessor.emit(logData); + verify(logProcessor1).emit(same(logData)); + verify(logProcessor2).emit(same(logData)); + + multiLogProcessor.forceFlush(); + verify(logProcessor1).forceFlush(); + verify(logProcessor2).forceFlush(); + + multiLogProcessor.shutdown(); + verify(logProcessor1).shutdown(); + verify(logProcessor2).shutdown(); + } +} diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogProcessorTest.java new file mode 100644 index 00000000000..40ac3f57820 --- /dev/null +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/NoopLogProcessorTest.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import io.opentelemetry.sdk.logs.data.Severity; +import io.opentelemetry.sdk.logs.util.TestUtil; +import org.junit.jupiter.api.Test; + +class NoopLogProcessorTest { + + @Test + void noCrash() { + LogProcessor logProcessor = NoopLogProcessor.getInstance(); + logProcessor.emit(TestUtil.createLogData(Severity.DEBUG, "message")); + assertThat(logProcessor.forceFlush().isSuccess()).isEqualTo(true); + assertThat(logProcessor.shutdown().isSuccess()).isEqualTo(true); + } +} diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java index f81b419d34a..77275e9e1b3 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java @@ -6,17 +6,80 @@ package io.opentelemetry.sdk.logs.export; import static io.opentelemetry.sdk.logs.util.TestUtil.createLogData; +import static io.opentelemetry.sdk.logs.util.TestUtil.createLogRecord; +import static org.assertj.core.api.Assertions.fail; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.awaitility.Awaitility.await; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.logs.LogEmitter; +import io.opentelemetry.sdk.logs.LogEmitterProvider; +import io.opentelemetry.sdk.logs.LogProcessor; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.util.TestLogExporter; +import java.time.Duration; import java.util.concurrent.TimeUnit; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; class BatchLogProcessorTest { + @Test + void testBatchSize() { + TestLogExporter exporter = new TestLogExporter(); + LogProcessor processor = + BatchLogProcessor.builder(exporter) + .setScheduleDelayMillis(10000) // Long enough to not be in play + .setMaxExportBatchSize(5) + .setMaxQueueSize(10) + .build(); + LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + LogEmitter emitter = provider.get("test", "0.1a"); + + for (int i = 0; i < 7; i++) { + emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); + } + // Ensure that more than batch size kicks off a flush + await().atMost(Duration.ofSeconds(5)).until(() -> exporter.getRecords().size() > 0); + // Ensure that everything gets through + CompletableResultCode result = provider.forceFlush(); + result.join(1, TimeUnit.SECONDS); + Assertions.assertThat(exporter.getCallCount()).isGreaterThanOrEqualTo(2); + } + + @Test + void testNoBlocking() { + TestLogExporter exporter = new TestLogExporter(); + exporter.setOnCall( + () -> { + try { + Thread.sleep(250); + } catch (InterruptedException ex) { + fail("Exporter wait interrupted", ex); + } + }); + LogProcessor processor = + BatchLogProcessor.builder(exporter) + .setScheduleDelayMillis(3000) // Long enough to not be in play + .setMaxExportBatchSize(5) + .setMaxQueueSize(10) + .build(); + LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + LogEmitter emitter = provider.get("test", "0.1a"); + + long start = System.currentTimeMillis(); + int testRecordCount = 700; + for (int i = 0; i < testRecordCount; i++) { + emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); + } + long end = System.currentTimeMillis(); + Assertions.assertThat(end - start).isLessThan(250L); + provider.forceFlush().join(1, TimeUnit.SECONDS); + Assertions.assertThat(exporter.getRecords().size()) + .isLessThan(testRecordCount); // We dropped records + } + @Test void testForceExport() { int batchSize = 10; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java deleted file mode 100644 index 5fcd4041d2f..00000000000 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestLogProcessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs.util; - -import io.opentelemetry.sdk.common.CompletableResultCode; -import io.opentelemetry.sdk.logs.LogProcessor; -import io.opentelemetry.sdk.logs.data.LogData; -import java.util.ArrayList; -import java.util.List; - -public class TestLogProcessor implements LogProcessor { - private final List records = new ArrayList<>(); - private boolean shutdownCalled = false; - private int flushes = 0; - - @Override - public void emit(LogData logData) { - records.add(logData); - } - - @Override - public CompletableResultCode shutdown() { - shutdownCalled = true; - return CompletableResultCode.ofSuccess(); - } - - @Override - public CompletableResultCode forceFlush() { - flushes++; - return CompletableResultCode.ofSuccess(); - } - - public List getRecords() { - return records; - } - - public int getFlushes() { - return flushes; - } - - public boolean shutdownHasBeenCalled() { - return shutdownCalled; - } -} From 56072d203b1979c313370eaa6448a7d383149d7e Mon Sep 17 00:00:00 2001 From: jack-berg Date: Wed, 20 Oct 2021 15:57:50 -0500 Subject: [PATCH 08/13] Reorganize to facilitate potential future API --- .../io/opentelemetry/sdk/logs/LogEmitter.java | 28 ++------ .../sdk/logs/LogEmitterBuilder.java | 35 ++-------- .../sdk/logs/LogEmitterSharedState.java | 4 +- .../opentelemetry/sdk/logs/LogProcessor.java | 2 +- .../opentelemetry/sdk/logs/SdkLogEmitter.java | 38 +++++++++++ .../sdk/logs/SdkLogEmitterBuilder.java | 39 +++++++++++ ...ovider.java => SdkLogEmitterProvider.java} | 19 +++--- ...java => SdkLogEmitterProviderBuilder.java} | 20 +++--- .../opentelemetry/sdk/logs/package-info.java | 2 +- ...st.java => SdkLogEmitterProviderTest.java} | 67 +++++++++---------- ...mitterTest.java => SdkLogEmitterTest.java} | 12 ++-- .../logs/export/BatchLogProcessorTest.java | 8 ++- 12 files changed, 155 insertions(+), 119 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/{LogEmitterProvider.java => SdkLogEmitterProvider.java} (80%) rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/{LogEmitterProviderBuilder.java => SdkLogEmitterProviderBuilder.java} (68%) rename sdk/logs/src/test/java/io/opentelemetry/sdk/logs/{LogEmitterProviderTest.java => SdkLogEmitterProviderTest.java} (72%) rename sdk/logs/src/test/java/io/opentelemetry/sdk/logs/{LogEmitterTest.java => SdkLogEmitterTest.java} (89%) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java index b34e99b849b..1baa3b7c5be 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java @@ -8,25 +8,16 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.logs.data.ReadableLogData; import io.opentelemetry.sdk.resources.Resource; +import javax.annotation.concurrent.ThreadSafe; /** * A {@link LogEmitter} is the entry point into a log pipeline. Log emitters accept {@link * LogRecord}, and after associating them with a {@link Resource} and {@link * InstrumentationLibraryInfo}, pushes them to downstream {@link LogProcessor#emit(LogData)}. */ -public final class LogEmitter { - - private final LogEmitterSharedState logEmitterSharedState; - private final InstrumentationLibraryInfo instrumentationLibraryInfo; - - LogEmitter( - LogEmitterSharedState logEmitterSharedState, - InstrumentationLibraryInfo instrumentationLibraryInfo) { - this.logEmitterSharedState = logEmitterSharedState; - this.instrumentationLibraryInfo = instrumentationLibraryInfo; - } +@ThreadSafe +public interface LogEmitter { /** * Emit a log record. Associates the log with a {@link Resource} and {@link @@ -34,16 +25,5 @@ public final class LogEmitter { * * @param logRecord the log record */ - public void emit(LogRecord logRecord) { - logEmitterSharedState - .getActiveLogProcessor() - .emit( - ReadableLogData.create( - logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); - } - - // VisibleForTesting - InstrumentationLibraryInfo getInstrumentationLibraryInfo() { - return instrumentationLibraryInfo; - } + void emit(LogRecord logRecord); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java index b8185919796..b31986b853c 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterBuilder.java @@ -5,21 +5,8 @@ package io.opentelemetry.sdk.logs; -import io.opentelemetry.sdk.internal.ComponentRegistry; -import javax.annotation.Nullable; - -/** Builder class for {@link LogEmitter} instances. */ -public final class LogEmitterBuilder { - - private final ComponentRegistry registry; - private final String instrumentationName; - @Nullable private String getInstrumentationVersion; - @Nullable private String schemaUrl; - - LogEmitterBuilder(ComponentRegistry registry, String instrumentationName) { - this.registry = registry; - this.instrumentationName = instrumentationName; - } +/** Builder class for creating {@link LogEmitter} instances. */ +public interface LogEmitterBuilder { /** * Assign an OpenTelemetry schema URL to the resulting {@link LogEmitter}. @@ -27,28 +14,20 @@ public final class LogEmitterBuilder { * @param schemaUrl the URL of the OpenTelemetry schema being used by this instrumentation library * @return this */ - public LogEmitterBuilder setSchemaUrl(String schemaUrl) { - this.schemaUrl = schemaUrl; - return this; - } + LogEmitterBuilder setSchemaUrl(String schemaUrl); /** - * Assign a version to the instrumenation library that is using the resulting {@link LogEmitter}. + * Assign a version to the instrumentation library that is using the resulting {@link LogEmitter}. * - * @param instrumentationVersion the versino of the instrumenation library + * @param instrumentationVersion the version of the instrumentation library * @return this */ - public LogEmitterBuilder setInstrumentationVersion(String instrumentationVersion) { - this.getInstrumentationVersion = instrumentationVersion; - return this; - } + LogEmitterBuilder setInstrumentationVersion(String instrumentationVersion); /** * Gets or creates a {@link LogEmitter} instance. * * @return a log emitter instance configured with the provided options */ - public LogEmitter build() { - return registry.get(instrumentationName, getInstrumentationVersion, schemaUrl); - } + LogEmitter build(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java index 7239b6d23ee..fe40f9f0a45 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java @@ -11,8 +11,8 @@ import javax.annotation.Nullable; /** - * Represents shared state and config between all {@link LogEmitter}s created by the same {@link - * LogEmitterProvider}. + * Represents shared state and config between all {@link SdkLogEmitter}s created by the same {@link + * SdkLogEmitterProvider}. */ final class LogEmitterSharedState { private final Object lock = new Object(); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java index 08b3b4f727f..c8a226396f7 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java @@ -17,7 +17,7 @@ /** * {@link LogProcessor} is the interface to allow synchronous hooks for when {@link - * LogEmitter#emit(LogRecord)} is called. + * SdkLogEmitter#emit(LogRecord)} is called. */ @ThreadSafe public interface LogProcessor extends Closeable { diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java new file mode 100644 index 00000000000..b5b0d12498c --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.ReadableLogData; + +/** {@link SdkLogEmitter} is the SDK implementation of {@link LogEmitter}. */ +final class SdkLogEmitter implements LogEmitter { + + private final LogEmitterSharedState logEmitterSharedState; + private final InstrumentationLibraryInfo instrumentationLibraryInfo; + + SdkLogEmitter( + LogEmitterSharedState logEmitterSharedState, + InstrumentationLibraryInfo instrumentationLibraryInfo) { + this.logEmitterSharedState = logEmitterSharedState; + this.instrumentationLibraryInfo = instrumentationLibraryInfo; + } + + @Override + public void emit(LogRecord logRecord) { + logEmitterSharedState + .getActiveLogProcessor() + .emit( + ReadableLogData.create( + logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); + } + + // VisibleForTesting + InstrumentationLibraryInfo getInstrumentationLibraryInfo() { + return instrumentationLibraryInfo; + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java new file mode 100644 index 00000000000..a1e2929a4a5 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.sdk.internal.ComponentRegistry; +import javax.annotation.Nullable; + +class SdkLogEmitterBuilder implements LogEmitterBuilder { + + private final ComponentRegistry registry; + private final String instrumentationName; + @Nullable private String getInstrumentationVersion; + @Nullable private String schemaUrl; + + SdkLogEmitterBuilder(ComponentRegistry registry, String instrumentationName) { + this.registry = registry; + this.instrumentationName = instrumentationName; + } + + @Override + public SdkLogEmitterBuilder setSchemaUrl(String schemaUrl) { + this.schemaUrl = schemaUrl; + return this; + } + + @Override + public SdkLogEmitterBuilder setInstrumentationVersion(String instrumentationVersion) { + this.getInstrumentationVersion = instrumentationVersion; + return this; + } + + @Override + public SdkLogEmitter build() { + return registry.get(instrumentationName, getInstrumentationVersion, schemaUrl); + } +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java similarity index 80% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java index fb698831075..38d5c45ea5c 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java @@ -16,28 +16,29 @@ import javax.annotation.Nullable; /** Provides instances of {@link LogEmitter}. */ -public final class LogEmitterProvider implements Closeable { +public final class SdkLogEmitterProvider implements Closeable { static final String DEFAULT_EMITTER_NAME = "unknown"; - private static final Logger LOGGER = Logger.getLogger(LogEmitterProvider.class.getName()); + private static final Logger LOGGER = Logger.getLogger(SdkLogEmitterProvider.class.getName()); private final LogEmitterSharedState sharedState; - private final ComponentRegistry logEmitterComponentRegistry; + private final ComponentRegistry logEmitterComponentRegistry; /** - * Returns a new {@link LogEmitterProviderBuilder} for {@link LogEmitterProvider}. + * Returns a new {@link SdkLogEmitterProviderBuilder} for {@link SdkLogEmitterProvider}. * * @return a new builder instance */ - public static LogEmitterProviderBuilder builder() { - return new LogEmitterProviderBuilder(); + public static SdkLogEmitterProviderBuilder builder() { + return new SdkLogEmitterProviderBuilder(); } - LogEmitterProvider(Resource resource, List processors) { + SdkLogEmitterProvider(Resource resource, List processors) { this.sharedState = new LogEmitterSharedState(resource, processors); this.logEmitterComponentRegistry = new ComponentRegistry<>( - instrumentationLibraryInfo -> new LogEmitter(sharedState, instrumentationLibraryInfo)); + instrumentationLibraryInfo -> + new SdkLogEmitter(sharedState, instrumentationLibraryInfo)); } /** @@ -74,7 +75,7 @@ public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) LOGGER.fine("LogEmitter requested without instrumentation name."); instrumentationName = DEFAULT_EMITTER_NAME; } - return new LogEmitterBuilder(logEmitterComponentRegistry, instrumentationName); + return new SdkLogEmitterBuilder(logEmitterComponentRegistry, instrumentationName); } /** diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java similarity index 68% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java index 3152c60d31b..1ffbae3bcff 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProviderBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java @@ -13,22 +13,22 @@ import java.util.ArrayList; import java.util.List; -/** Builder class for {@link LogEmitterProvider} instances. */ -public final class LogEmitterProviderBuilder { +/** Builder class for {@link SdkLogEmitterProvider} instances. */ +public final class SdkLogEmitterProviderBuilder { private final List logProcessors = new ArrayList<>(); private Resource resource = Resource.getDefault(); - LogEmitterProviderBuilder() {} + SdkLogEmitterProviderBuilder() {} /** * Assign a {@link Resource} to be attached to all {@link LogData} created by {@link LogEmitter}s - * obtained from the {@link LogEmitterProvider}. + * obtained from the {@link SdkLogEmitterProvider}. * * @param resource the resource * @return this */ - public LogEmitterProviderBuilder setResource(Resource resource) { + public SdkLogEmitterProviderBuilder setResource(Resource resource) { requireNonNull(resource, "resource"); this.resource = resource; return this; @@ -37,23 +37,23 @@ public LogEmitterProviderBuilder setResource(Resource resource) { /** * Add a log processor. {@link LogProcessor#emit(LogData)} will be called each time {@link * LogEmitter#emit(LogRecord)} is called for emitter instances obtained from the {@link - * LogEmitterProvider}. + * SdkLogEmitterProvider}. * * @param processor the log processor * @return this */ - public LogEmitterProviderBuilder addLogProcessor(LogProcessor processor) { + public SdkLogEmitterProviderBuilder addLogProcessor(LogProcessor processor) { requireNonNull(processor, "processor"); logProcessors.add(processor); return this; } /** - * Create a {@link LogEmitterProvider} instance. + * Create a {@link SdkLogEmitterProvider} instance. * * @return an instance configured with the provided options */ - public LogEmitterProvider build() { - return new LogEmitterProvider(resource, logProcessors); + public SdkLogEmitterProvider build() { + return new SdkLogEmitterProvider(resource, logProcessors); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java index 1ee6fd83a10..3382f24ef97 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/package-info.java @@ -6,7 +6,7 @@ /** * The OpenTelemetry SDK implementation of logging. * - * @see io.opentelemetry.sdk.logs.LogEmitterProvider + * @see io.opentelemetry.sdk.logs.SdkLogEmitterProvider */ @ParametersAreNonnullByDefault package io.opentelemetry.sdk.logs; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java similarity index 72% rename from sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java rename to sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java index 38147986ea1..d795ede7215 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java @@ -26,22 +26,22 @@ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) -class LogEmitterProviderTest { +class SdkLogEmitterProviderTest { @Mock private LogProcessor logProcessor; - private LogEmitterProvider logEmitterProvider; + private SdkLogEmitterProvider sdkLogEmitterProvider; @BeforeEach void setup() { - logEmitterProvider = LogEmitterProvider.builder().addLogProcessor(logProcessor).build(); + sdkLogEmitterProvider = SdkLogEmitterProvider.builder().addLogProcessor(logProcessor).build(); when(logProcessor.forceFlush()).thenReturn(CompletableResultCode.ofSuccess()); when(logProcessor.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); } @Test void builder_defaultResource() { - assertThat(LogEmitterProvider.builder().build()) + assertThat(SdkLogEmitterProvider.builder().build()) .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) .extracting(LogEmitterSharedState::getResource) .isEqualTo(Resource.getDefault()); @@ -51,7 +51,7 @@ void builder_defaultResource() { void builder_resourceProvided() { Resource resource = Resource.create(Attributes.builder().put("key", "value").build()); - assertThat(LogEmitterProvider.builder().setResource(resource).build()) + assertThat(SdkLogEmitterProvider.builder().setResource(resource).build()) .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) .extracting(LogEmitterSharedState::getResource) .isEqualTo(resource); @@ -59,7 +59,7 @@ void builder_resourceProvided() { @Test void builder_noProcessor() { - assertThat(LogEmitterProvider.builder().build()) + assertThat(SdkLogEmitterProvider.builder().build()) .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) .extracting(LogEmitterSharedState::getActiveLogProcessor) .isSameAs(NoopLogProcessor.getInstance()); @@ -68,7 +68,7 @@ void builder_noProcessor() { @Test void builder_multipleProcessors() { assertThat( - LogEmitterProvider.builder() + SdkLogEmitterProvider.builder() .addLogProcessor(logProcessor) .addLogProcessor(logProcessor) .build()) @@ -86,24 +86,24 @@ void builder_multipleProcessors() { @Test void get_SameName() { - assertThat(logEmitterProvider.get("test")) - .isSameAs(logEmitterProvider.get("test")) - .isSameAs(logEmitterProvider.get("test", null)) - .isSameAs(logEmitterProvider.logEmitterBuilder("test").build()) - .isNotSameAs(logEmitterProvider.get("test", "version")); + assertThat(sdkLogEmitterProvider.get("test")) + .isSameAs(sdkLogEmitterProvider.get("test")) + .isSameAs(sdkLogEmitterProvider.get("test", null)) + .isSameAs(sdkLogEmitterProvider.logEmitterBuilder("test").build()) + .isNotSameAs(sdkLogEmitterProvider.get("test", "version")); } @Test void get_SameNameAndVersion() { - assertThat(logEmitterProvider.get("test", "version")) - .isSameAs(logEmitterProvider.get("test", "version")) + assertThat(sdkLogEmitterProvider.get("test", "version")) + .isSameAs(sdkLogEmitterProvider.get("test", "version")) .isSameAs( - logEmitterProvider + sdkLogEmitterProvider .logEmitterBuilder("test") .setInstrumentationVersion("version") .build()) .isNotSameAs( - logEmitterProvider + sdkLogEmitterProvider .logEmitterBuilder("test") .setInstrumentationVersion("version") .setSchemaUrl("http://url") @@ -113,13 +113,13 @@ void get_SameNameAndVersion() { @Test void logEmitterBuilder_SameNameVersionAndSchema() { assertThat( - logEmitterProvider + sdkLogEmitterProvider .logEmitterBuilder("test") .setInstrumentationVersion("version") .setSchemaUrl("http://url") .build()) .isSameAs( - logEmitterProvider + sdkLogEmitterProvider .logEmitterBuilder("test") .setInstrumentationVersion("version") .setSchemaUrl("http://url") @@ -131,11 +131,12 @@ void logEmitterBuilder_PropagatesToEmitter() { InstrumentationLibraryInfo expected = InstrumentationLibraryInfo.create("test", "version", "http://url"); assertThat( - logEmitterProvider - .logEmitterBuilder("test") - .setInstrumentationVersion("version") - .setSchemaUrl("http://url") - .build() + ((SdkLogEmitter) + sdkLogEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .setSchemaUrl("http://url") + .build()) .getInstrumentationLibraryInfo()) .isEqualTo(expected); } @@ -143,38 +144,34 @@ void logEmitterBuilder_PropagatesToEmitter() { @Test void logEmitterBuilder_DefaultEmitterName() { assertThat( - logEmitterProvider - .logEmitterBuilder(null) - .build() + ((SdkLogEmitter) sdkLogEmitterProvider.logEmitterBuilder(null).build()) .getInstrumentationLibraryInfo() .getName()) - .isEqualTo(LogEmitterProvider.DEFAULT_EMITTER_NAME); + .isEqualTo(SdkLogEmitterProvider.DEFAULT_EMITTER_NAME); assertThat( - logEmitterProvider - .logEmitterBuilder("") - .build() + ((SdkLogEmitter) sdkLogEmitterProvider.logEmitterBuilder("").build()) .getInstrumentationLibraryInfo() .getName()) - .isEqualTo(LogEmitterProvider.DEFAULT_EMITTER_NAME); + .isEqualTo(SdkLogEmitterProvider.DEFAULT_EMITTER_NAME); } @Test void forceFlush() { - logEmitterProvider.forceFlush(); + sdkLogEmitterProvider.forceFlush(); verify(logProcessor).forceFlush(); } @Test void shutdown() { - logEmitterProvider.shutdown(); - logEmitterProvider.shutdown(); + sdkLogEmitterProvider.shutdown(); + sdkLogEmitterProvider.shutdown(); verify(logProcessor, times(1)).shutdown(); } @Test void close() { - logEmitterProvider.close(); + sdkLogEmitterProvider.close(); verify(logProcessor).shutdown(); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java similarity index 89% rename from sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java rename to sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java index a90e12eeb3f..ef57d55ccb8 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/LogEmitterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java @@ -22,19 +22,19 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class LogEmitterTest { +class SdkLogEmitterTest { - private static final String INSTRUMENTATION_LIBRARY_NAME = LogEmitter.class.getName(); + private static final String INSTRUMENTATION_LIBRARY_NAME = SdkLogEmitter.class.getName(); private static final String INSTRUMENTATION_LIBRARY_VERSION = "0.0.1"; private static final String SCHEMA_URL = "http://schemaurl"; @Mock private LogProcessor logProcessor; - private LogEmitter logEmitter; + private LogEmitter sdkLogEmitter; @BeforeEach void setup() { - logEmitter = - LogEmitterProvider.builder() + sdkLogEmitter = + SdkLogEmitterProvider.builder() .addLogProcessor(logProcessor) .build() .logEmitterBuilder(INSTRUMENTATION_LIBRARY_NAME) @@ -50,7 +50,7 @@ void emit() { .setEpochMillis(System.currentTimeMillis()) .setBody(Body.stringBody("message")) .build(); - logEmitter.emit(logRecord); + sdkLogEmitter.emit(logRecord); ArgumentCaptor captor = ArgumentCaptor.forClass(LogData.class); verify(logProcessor).emit(captor.capture()); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java index 77275e9e1b3..6fe4d917e23 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java @@ -13,8 +13,8 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.LogEmitter; -import io.opentelemetry.sdk.logs.LogEmitterProvider; import io.opentelemetry.sdk.logs.LogProcessor; +import io.opentelemetry.sdk.logs.SdkLogEmitterProvider; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.util.TestLogExporter; @@ -34,7 +34,8 @@ void testBatchSize() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + SdkLogEmitterProvider provider = + SdkLogEmitterProvider.builder().addLogProcessor(processor).build(); LogEmitter emitter = provider.get("test", "0.1a"); for (int i = 0; i < 7; i++) { @@ -65,7 +66,8 @@ void testNoBlocking() { .setMaxExportBatchSize(5) .setMaxQueueSize(10) .build(); - LogEmitterProvider provider = LogEmitterProvider.builder().addLogProcessor(processor).build(); + SdkLogEmitterProvider provider = + SdkLogEmitterProvider.builder().addLogProcessor(processor).build(); LogEmitter emitter = provider.get("test", "0.1a"); long start = System.currentTimeMillis(); From 52aa806bee2ee8fdb187912527f7d10d90eca5c2 Mon Sep 17 00:00:00 2001 From: jack-berg Date: Wed, 27 Oct 2021 13:26:45 -0500 Subject: [PATCH 09/13] Rename ReadableLog* to SdkLog*, make SdkLog* package private --- .../otlp/OtlpJsonLoggingLogExporterTest.java | 11 ++-- .../logging/SystemOutLogExporterTest.java | 7 +-- .../http/logs/OtlpHttpLogExporterTest.java | 7 +-- .../internal/logs/LogsRequestMarshaler.java | 4 +- .../logs/LogsRequestMarshalerTest.java | 15 +++-- .../otlp/logs/OtlpGrpcLogsExporterTest.java | 7 +-- .../exporter/otlp/logs/ExportTest.java | 7 +-- .../exporter/otlp/logs/ExportTest.java | 7 +-- .../exporter/otlp/logs/ExportTest.java | 7 +-- .../otlp/logs/OkHttpOnlyExportTest.java | 7 +-- .../OtlpExporterIntegrationTest.java | 7 +-- .../opentelemetry/sdk/logs/SdkLogEmitter.java | 4 +- .../opentelemetry/sdk/logs/data/LogData.java | 20 +++---- .../sdk/logs/data/LogRecord.java | 59 +++++-------------- .../sdk/logs/data/LogRecordBuilder.java | 48 +++++++++++++++ .../{ReadableLogData.java => SdkLogData.java} | 17 ++---- ...adableLogRecord.java => SdkLogRecord.java} | 18 ++---- ...dBuilder.java => SdkLogRecordBuilder.java} | 49 ++++++++------- .../sdk/logs/export/LogExporter.java | 17 +++++- .../sdk/logs/SdkLogEmitterTest.java | 3 +- .../logs/export/InMemoryLogExporterTest.java | 49 +++++++-------- .../opentelemetry/sdk/logs/util/TestUtil.java | 6 +- 22 files changed, 191 insertions(+), 185 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{ReadableLogData.java => SdkLogData.java} (67%) rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{ReadableLogRecord.java => SdkLogRecord.java} (64%) rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{ReadableLogRecordBuilder.java => SdkLogRecordBuilder.java} (61%) diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java index c7ffcfa37e6..8e85bd4c6c2 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java @@ -14,8 +14,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.resources.Resource; @@ -32,10 +31,10 @@ class OtlpJsonLoggingLogExporterTest { Resource.create(Attributes.builder().put("key", "value").build()); private static final LogData LOG1 = - ReadableLogData.create( + LogData.create( RESOURCE, InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setName("testLog1") .setBody("body1") .setFlags(0) @@ -48,10 +47,10 @@ class OtlpJsonLoggingLogExporterTest { .build()); private static final LogData LOG2 = - ReadableLogData.create( + LogData.create( RESOURCE, InstrumentationLibraryInfo.create("instrumentation2", "2"), - ReadableLogRecord.builder() + LogRecord.builder() .setName("testLog2") .setBody("body2") .setFlags(0) diff --git a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java index 31dd0d9a720..d9978279060 100644 --- a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java +++ b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java @@ -17,8 +17,7 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.time.LocalDateTime; @@ -51,10 +50,10 @@ void format() { } private static LogData sampleLog(long timestamp) { - return ReadableLogData.create( + return LogData.create( Resource.empty(), InstrumentationLibraryInfo.create("logTest", "1.0"), - ReadableLogRecord.builder() + LogRecord.builder() .setAttributes(Attributes.of(stringKey("cheese"), "cheddar", longKey("amount"), 1L)) .setBody(Body.stringBody("message")) .setSeverity(Severity.ERROR3) diff --git a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java index 893ff5fb285..ca149d6424b 100644 --- a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java +++ b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java @@ -31,8 +31,7 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.IdGenerator; @@ -320,10 +319,10 @@ private static HttpResponse buildResponse(HttpStatus httpSta } private static LogData generateFakeLog() { - return ReadableLogData.create( + return LogData.create( Resource.getDefault(), InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), - ReadableLogRecord.builder() + LogRecord.builder() .setName("log-name") .setBody(Body.stringBody("log body")) .setAttributes(Attributes.builder().put("key", "value").build()) diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java index a0d9b04223a..336890fad49 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshaler.java @@ -11,14 +11,12 @@ import io.opentelemetry.exporter.otlp.internal.Serializer; import io.opentelemetry.proto.collector.logs.v1.internal.ExportLogsServiceRequest; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; import io.opentelemetry.sdk.trace.data.SpanData; import java.io.IOException; import java.util.Collection; /** - * {@link Marshaler} to convert SDK {@link ReadableLogRecordBuilder} to OTLP - * ExportLogsServiceRequest. + * {@link Marshaler} to convert SDK {@link LogData} to OTLP ExportLogsServiceRequest. * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java index 165722e7cee..cd4d3199169 100644 --- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java +++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java @@ -24,8 +24,7 @@ import io.opentelemetry.proto.logs.v1.LogRecord; import io.opentelemetry.proto.logs.v1.ResourceLogs; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.io.ByteArrayOutputStream; @@ -51,10 +50,10 @@ void toProtoResourceLogs() { ResourceLogsMarshaler[] resourceLogsMarshalers = ResourceLogsMarshaler.create( Collections.singleton( - ReadableLogData.create( + LogData.create( Resource.builder().put("one", 1).setSchemaUrl("http://url").build(), InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), - ReadableLogRecord.builder() + io.opentelemetry.sdk.logs.data.LogRecord.builder() .setName(NAME) .setBody(BODY) .setSeverity(Severity.INFO) @@ -85,10 +84,10 @@ void toProtoLogRecord() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + io.opentelemetry.sdk.logs.data.LogRecord.builder() .setName(NAME) .setBody(BODY) .setSeverity(Severity.INFO) @@ -119,10 +118,10 @@ void toProtoLogRecord_MinimalFields() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + io.opentelemetry.sdk.logs.data.LogRecord.builder() .setBody(BODY) .setSeverity(Severity.INFO) .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) diff --git a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java index fc176730f65..d2f60d53c9e 100644 --- a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java +++ b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java @@ -32,8 +32,7 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.io.ByteArrayOutputStream; @@ -358,10 +357,10 @@ void usingGrpc() { } private static LogData generateFakeLog() { - return ReadableLogData.create( + return LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) diff --git a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index a3622fae660..eb9dfdd00a2 100644 --- a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,8 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,10 +39,10 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) diff --git a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index a3622fae660..eb9dfdd00a2 100644 --- a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,8 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,10 +39,10 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) diff --git a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index a3622fae660..eb9dfdd00a2 100644 --- a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,8 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,10 +39,10 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) diff --git a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java index e31056591e1..2716bb2dc18 100644 --- a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java +++ b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java @@ -20,8 +20,7 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.net.InetAddress; @@ -41,10 +40,10 @@ class OkHttpOnlyExportTest { private static final List LOGS = Collections.singletonList( - ReadableLogData.create( + LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) diff --git a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java index 6a55ec4ca21..89e28ad880c 100644 --- a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java +++ b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java @@ -53,8 +53,7 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; +import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -378,10 +377,10 @@ void testOtlpHttpLogExport(String compression) { private static void testLogExporter(LogExporter logExporter) { LogData logData = - ReadableLogData.create( + LogData.create( RESOURCE, InstrumentationLibraryInfo.create(OtlpExporterIntegrationTest.class.getName(), null), - ReadableLogRecord.builder() + LogRecord.builder() .setName("log-name") .setBody(Body.stringBody("log body")) .setAttributes(Attributes.builder().put("key", "value").build()) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java index b5b0d12498c..6577498285b 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java @@ -6,8 +6,8 @@ package io.opentelemetry.sdk.logs; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.logs.data.ReadableLogData; /** {@link SdkLogEmitter} is the SDK implementation of {@link LogEmitter}. */ final class SdkLogEmitter implements LogEmitter { @@ -27,7 +27,7 @@ public void emit(LogRecord logRecord) { logEmitterSharedState .getActiveLogProcessor() .emit( - ReadableLogData.create( + LogData.create( logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java index f95931634b5..9055aed10f5 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java @@ -15,17 +15,17 @@ @Immutable public interface LogData extends LogRecord { - /** - * Returns the resource of this log. - * - * @return the resource. - */ + /** Create a log data instance. */ + static LogData create( + Resource resource, + InstrumentationLibraryInfo instrumentationLibraryInfo, + LogRecord logRecord) { + return SdkLogData.create(resource, instrumentationLibraryInfo, logRecord); + } + + /** Returns the resource of this log. */ Resource getResource(); - /** - * Returns the instrumentation library that generated this log. - * - * @return an instance of {@link InstrumentationLibraryInfo}. - */ + /** Returns the instrumentation library that generated this log. */ InstrumentationLibraryInfo getInstrumentationLibraryInfo(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java index ba739ee66f0..f955d25f393 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java @@ -15,70 +15,39 @@ */ public interface LogRecord { - /** - * Returns the epoch timestamp in nanos when the log was recorded. - * - * @return the epoch timestamp in nanos - */ + /** Returns a new {@link LogRecordBuilder}. */ + static LogRecordBuilder builder() { + return new SdkLogRecordBuilder(); + } + + /** Returns the epoch timestamp in nanos when the log was recorded. */ long getEpochNanos(); - /** - * Returns the trace id for this log. - * - * @return the trace id - */ + /** Returns the trace id for this log. */ @Nullable String getTraceId(); - /** - * Returns the span id for this log. - * - * @return the span id - */ + /** Returns the span id for this log. */ @Nullable String getSpanId(); - /** - * Returns the flags for this log. - * - * @return the flags - */ + /** Returns the flags for this log. */ int getFlags(); - /** - * Returns the severity for this log. - * - * @return the severity - */ + /** Returns the severity for this log. */ Severity getSeverity(); - /** - * Returns the severity text for this log. - * - * @return the severity text - */ + /** Returns the severity text for this log. */ @Nullable String getSeverityText(); - /** - * Returns the name for this log. - * - * @return the name - */ + /** Returns the name for this log. */ @Nullable String getName(); - /** - * Returns the body for this log. - * - * @return the body - */ + /** Returns the body for this log. */ Body getBody(); - /** - * Returns the attributes for this log. - * - * @return the attributes - */ + /** Returns the attributes for this log. */ Attributes getAttributes(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java new file mode 100644 index 00000000000..c33275c2ddc --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java @@ -0,0 +1,48 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs.data; + +import io.opentelemetry.api.common.Attributes; + +/** Interface for building for {@link LogRecord}. */ +public interface LogRecordBuilder { + + /** Set the epoch timestamp in nanos. */ + LogRecordBuilder setEpochNanos(long timestamp); + + /** Set the epoch timestamp in millis. */ + LogRecordBuilder setEpochMillis(long timestamp); + + /** Set the trace id. */ + LogRecordBuilder setTraceId(String traceId); + + /** Set the span id. */ + LogRecordBuilder setSpanId(String spanId); + + /** Set the flags. */ + LogRecordBuilder setFlags(int flags); + + /** Set the severity. */ + LogRecordBuilder setSeverity(Severity severity); + + /** Set the severity text. */ + LogRecordBuilder setSeverityText(String severityText); + + /** Set the name. */ + LogRecordBuilder setName(String name); + + /** Set the body. */ + LogRecordBuilder setBody(Body body); + + /** Set the body string. */ + LogRecordBuilder setBody(String body); + + /** Set the attributes. */ + LogRecordBuilder setAttributes(Attributes attributes); + + /** Build a {@link LogRecord} instance from the configured properties. */ + LogRecord build(); +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java similarity index 67% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java index 65c536e9861..bbf269140ba 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogData.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java @@ -10,25 +10,18 @@ import io.opentelemetry.sdk.resources.Resource; import javax.annotation.concurrent.Immutable; +/** Sdk implementation of {@link LogData}. */ @AutoValue @Immutable -public abstract class ReadableLogData implements LogData { +abstract class SdkLogData implements LogData { - ReadableLogData() {} + SdkLogData() {} - /** - * Create a {@link ReadableLogData} instance. - * - * @param resource the resource - * @param instrumentationLibraryInfo the instrumentation library info - * @param logRecord the log record - * @return the instance - */ - public static ReadableLogData create( + static SdkLogData create( Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo, LogRecord logRecord) { - return new AutoValue_ReadableLogData( + return new AutoValue_SdkLogData( logRecord.getEpochNanos(), logRecord.getTraceId(), logRecord.getSpanId(), diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java similarity index 64% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java index 2458e565af1..a11083d6696 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecord.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java @@ -10,22 +10,14 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +/** Sdk implementation of {@link LogRecord}. */ @AutoValue @Immutable -public abstract class ReadableLogRecord implements LogRecord { +abstract class SdkLogRecord implements LogRecord { - ReadableLogRecord() {} + SdkLogRecord() {} - /** - * Create a {@link ReadableLogRecordBuilder} instance. - * - * @return the instance - */ - public static ReadableLogRecordBuilder builder() { - return new ReadableLogRecordBuilder(); - } - - static ReadableLogRecord create( + static SdkLogRecord create( long epochNanos, @Nullable String traceId, @Nullable String spanId, @@ -35,7 +27,7 @@ static ReadableLogRecord create( @Nullable String name, Body body, Attributes attributes) { - return new AutoValue_ReadableLogRecord( + return new AutoValue_SdkLogRecord( epochNanos, traceId, spanId, flags, severity, severityText, name, body, attributes); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java similarity index 61% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java index 97b0db4c3f6..624cc99c05a 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/ReadableLogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java @@ -10,8 +10,8 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -/** Builder for {@link ReadableLogRecordBuilder}. */ -public final class ReadableLogRecordBuilder { +/** Builder for {@link SdkLogRecordBuilder}. */ +final class SdkLogRecordBuilder implements LogRecordBuilder { private long epochNanos; @Nullable private String traceId; @@ -23,71 +23,78 @@ public final class ReadableLogRecordBuilder { private Body body = Body.stringBody(""); private final AttributesBuilder attributeBuilder = Attributes.builder(); - ReadableLogRecordBuilder() {} + SdkLogRecordBuilder() {} - public ReadableLogRecordBuilder setEpochNanos(long timestamp) { + @Override + public SdkLogRecordBuilder setEpochNanos(long timestamp) { this.epochNanos = timestamp; return this; } - public ReadableLogRecordBuilder setEpochMillis(long timestamp) { + @Override + public SdkLogRecordBuilder setEpochMillis(long timestamp) { return setEpochNanos(TimeUnit.MILLISECONDS.toNanos(timestamp)); } - public ReadableLogRecordBuilder setTraceId(String traceId) { + @Override + public SdkLogRecordBuilder setTraceId(String traceId) { this.traceId = traceId; return this; } - public ReadableLogRecordBuilder setSpanId(String spanId) { + @Override + public SdkLogRecordBuilder setSpanId(String spanId) { this.spanId = spanId; return this; } - public ReadableLogRecordBuilder setFlags(int flags) { + @Override + public SdkLogRecordBuilder setFlags(int flags) { this.flags = flags; return this; } - public ReadableLogRecordBuilder setSeverity(Severity severity) { + @Override + public SdkLogRecordBuilder setSeverity(Severity severity) { this.severity = severity; return this; } - public ReadableLogRecordBuilder setSeverityText(String severityText) { + @Override + public SdkLogRecordBuilder setSeverityText(String severityText) { this.severityText = severityText; return this; } - public ReadableLogRecordBuilder setName(String name) { + @Override + public SdkLogRecordBuilder setName(String name) { this.name = name; return this; } - public ReadableLogRecordBuilder setBody(Body body) { + @Override + public SdkLogRecordBuilder setBody(Body body) { this.body = body; return this; } - public ReadableLogRecordBuilder setBody(String body) { + @Override + public SdkLogRecordBuilder setBody(String body) { return setBody(Body.stringBody(body)); } - public ReadableLogRecordBuilder setAttributes(Attributes attributes) { + @Override + public SdkLogRecordBuilder setAttributes(Attributes attributes) { this.attributeBuilder.putAll(attributes); return this; } - /** - * Build a {@link ReadableLogRecord} instance. - * - * @return the instance - */ - public ReadableLogRecord build() { + @Override + public SdkLogRecord build() { if (epochNanos == 0) { epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); } - return ReadableLogRecord.create( + return SdkLogRecord.create( epochNanos, traceId, spanId, diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java index 43227bacdc0..5628823577d 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/LogExporter.java @@ -7,15 +7,26 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecordBuilder; import java.util.Collection; /** - * An exporter is responsible for taking a list of {@link ReadableLogRecordBuilder}s and - * transmitting them to their ultimate destination. + * An exporter is responsible for taking a collection of {@link LogData}s and transmitting them to + * their ultimate destination. */ public interface LogExporter { + + /** + * Exports the collections of given {@link LogData}. + * + * @param logs the collection of {@link LogData} to be exported + * @return the result of the export, which is often an asynchronous operation + */ CompletableResultCode export(Collection logs); + /** + * Exports the collection of {@link LogData} that have not yet been exported. + * + * @return the result of the flush, which is often an asynchronous operation + */ CompletableResultCode shutdown(); } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java index ef57d55ccb8..a08efbb2539 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java @@ -12,7 +12,6 @@ import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.resources.Resource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -46,7 +45,7 @@ void setup() { @Test void emit() { LogRecord logRecord = - ReadableLogRecord.builder() + LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setBody(Body.stringBody("message")) .build(); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java index 49297f9be28..8362a9713ed 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java @@ -6,13 +6,12 @@ package io.opentelemetry.sdk.logs.export; import static io.opentelemetry.sdk.logs.data.Severity.DEBUG; -import static io.opentelemetry.sdk.logs.util.TestUtil.createLog; +import static io.opentelemetry.sdk.logs.util.TestUtil.createLogData; import static org.assertj.core.api.Assertions.assertThat; -import io.opentelemetry.sdk.logs.LogSink; -import io.opentelemetry.sdk.logs.LogSinkSdkProvider; +import io.opentelemetry.sdk.logs.LogEmitter; +import io.opentelemetry.sdk.logs.SdkLogEmitterProvider; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -23,26 +22,28 @@ class InMemoryLogExporterTest { private final InMemoryLogExporter exporter = InMemoryLogExporter.create(); - private LogSinkSdkProvider logSinkSdkProvider; - private LogSink logSink; + private SdkLogEmitterProvider logEmitterProvider; + private LogEmitter logEmitter; @BeforeEach void setup() { - logSinkSdkProvider = - LogSinkSdkProvider.builder().addLogProcessor(SimpleLogProcessor.create(exporter)).build(); - logSink = logSinkSdkProvider.get(null, null); + logEmitterProvider = + SdkLogEmitterProvider.builder() + .addLogProcessor(SimpleLogProcessor.create(exporter)) + .build(); + logEmitter = logEmitterProvider.get(null, null); } @AfterEach void tearDown() { - logSinkSdkProvider.shutdown(); + logEmitterProvider.shutdown(); } @Test void getFinishedLogItems() { - logSink.offer(createLog(DEBUG, "message 1")); - logSink.offer(createLog(DEBUG, "message 2")); - logSink.offer(createLog(DEBUG, "message 3")); + logEmitter.emit(createLogData(DEBUG, "message 1")); + logEmitter.emit(createLogData(DEBUG, "message 2")); + logEmitter.emit(createLogData(DEBUG, "message 3")); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); @@ -54,9 +55,9 @@ void getFinishedLogItems() { @Test void reset() { - logSink.offer(createLog(DEBUG, "message 1")); - logSink.offer(createLog(DEBUG, "message 2")); - logSink.offer(createLog(DEBUG, "message 3")); + logEmitter.emit(createLogData(DEBUG, "message 1")); + logEmitter.emit(createLogData(DEBUG, "message 2")); + logEmitter.emit(createLogData(DEBUG, "message 3")); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); assertThat(logItems.size()).isEqualTo(3); @@ -67,9 +68,9 @@ void reset() { @Test void shutdown() { - logSink.offer(createLog(DEBUG, "message 1")); - logSink.offer(createLog(DEBUG, "message 2")); - logSink.offer(createLog(DEBUG, "message 3")); + logEmitter.emit(createLogData(DEBUG, "message 1")); + logEmitter.emit(createLogData(DEBUG, "message 2")); + logEmitter.emit(createLogData(DEBUG, "message 3")); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); assertThat(logItems.size()).isEqualTo(3); @@ -77,19 +78,19 @@ void shutdown() { exporter.shutdown(); assertThat(exporter.getFinishedLogItems()).isEmpty(); // Cannot add new elements after the shutdown. - logSink.offer(createLog(DEBUG, "message 1")); + logEmitter.emit(createLogData(DEBUG, "message 1")); assertThat(exporter.getFinishedLogItems()).isEmpty(); } @Test void export_ReturnCode() { - LogRecord logRecord = createLog(DEBUG, "message 1"); - assertThat(exporter.export(Collections.singletonList(logRecord)).isSuccess()).isTrue(); + LogData logData = createLogData(DEBUG, "message 1"); + assertThat(exporter.export(Collections.singletonList(logData)).isSuccess()).isTrue(); exporter.shutdown(); // After shutdown no more export. - assertThat(exporter.export(Collections.singletonList(logRecord)).isSuccess()).isFalse(); + assertThat(exporter.export(Collections.singletonList(logData)).isSuccess()).isFalse(); exporter.reset(); // Reset does not do anything if already shutdown. - assertThat(exporter.export(Collections.singletonList(logRecord)).isSuccess()).isFalse(); + assertThat(exporter.export(Collections.singletonList(logData)).isSuccess()).isFalse(); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java index ecd47ad7036..6c18936e0ee 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java @@ -12,15 +12,13 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.logs.data.ReadableLogData; -import io.opentelemetry.sdk.logs.data.ReadableLogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; public final class TestUtil { public static LogRecord createLogRecord(Severity severity, String message) { - return ReadableLogRecord.builder() + return LogRecord.builder() .setEpochMillis(System.currentTimeMillis()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) @@ -34,7 +32,7 @@ public static LogRecord createLogRecord(Severity severity, String message) { } public static LogData createLogData(Severity severity, String message) { - return ReadableLogData.create( + return LogData.create( Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), createLogRecord(severity, message)); From 21a98e30c6b7a472b8feba29c78d8b77592f9440 Mon Sep 17 00:00:00 2001 From: jack-berg Date: Wed, 27 Oct 2021 16:22:06 -0500 Subject: [PATCH 10/13] Add LogEmitterProvider interface, tidy up some javadoc --- .../io/opentelemetry/sdk/logs/LogEmitter.java | 2 +- .../sdk/logs/LogEmitterProvider.java | 37 +++++++++++++++++++ .../opentelemetry/sdk/logs/SdkLogEmitter.java | 2 +- .../sdk/logs/SdkLogEmitterProvider.java | 26 +++---------- .../sdk/logs/data/SdkLogData.java | 2 +- .../sdk/logs/data/SdkLogRecord.java | 2 +- 6 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java index 1baa3b7c5be..05a2dc1d908 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java @@ -13,7 +13,7 @@ /** * A {@link LogEmitter} is the entry point into a log pipeline. Log emitters accept {@link - * LogRecord}, and after associating them with a {@link Resource} and {@link + * LogRecord}s, and after associating them with a {@link Resource} and {@link * InstrumentationLibraryInfo}, pushes them to downstream {@link LogProcessor#emit(LogData)}. */ @ThreadSafe diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java new file mode 100644 index 00000000000..90d235ee7bd --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import javax.annotation.Nullable; + +/** A registry for creating {@link LogEmitter}s. */ +public interface LogEmitterProvider { + + /** + * Gets or creates a {@link LogEmitter} instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log emitter instance + */ + LogEmitter get(String instrumentationName); + + /** + * Gets or creates a {@link LogEmitter} instance. + * + * @param instrumentationName the name of the instrumentation library + * @param instrumentationVersion the version of the instrumentation library + * @return a log emitter instance + */ + LogEmitter get(String instrumentationName, String instrumentationVersion); + + /** + * Creates a {@link LogEmitterBuilder} instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log emitter builder instance + */ + LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName); +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java index 6577498285b..61b4fee725a 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; -/** {@link SdkLogEmitter} is the SDK implementation of {@link LogEmitter}. */ +/** SDK implementation of {@link LogEmitter}. */ final class SdkLogEmitter implements LogEmitter { private final LogEmitterSharedState logEmitterSharedState; diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java index 38d5c45ea5c..740bee4efb4 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java @@ -15,8 +15,8 @@ import java.util.logging.Logger; import javax.annotation.Nullable; -/** Provides instances of {@link LogEmitter}. */ -public final class SdkLogEmitterProvider implements Closeable { +/** SDK implementation of {@link LogEmitterProvider}. */ +public final class SdkLogEmitterProvider implements LogEmitterProvider, Closeable { static final String DEFAULT_EMITTER_NAME = "unknown"; private static final Logger LOGGER = Logger.getLogger(SdkLogEmitterProvider.class.getName()); @@ -41,35 +41,19 @@ public static SdkLogEmitterProviderBuilder builder() { new SdkLogEmitter(sharedState, instrumentationLibraryInfo)); } - /** - * Gets or creates a {@link LogEmitter} instance. - * - * @param instrumentationName the name of the instrumentation library - * @return a log emitter instance - */ + @Override public LogEmitter get(String instrumentationName) { return logEmitterBuilder(instrumentationName).build(); } - /** - * Gets or creates a {@link LogEmitter} instance. - * - * @param instrumentationName the name of the instrumentation library - * @param instrumentationVersion the version of the instrumentation library - * @return a log emitter instance - */ + @Override public LogEmitter get(String instrumentationName, String instrumentationVersion) { return logEmitterBuilder(instrumentationName) .setInstrumentationVersion(instrumentationVersion) .build(); } - /** - * Creates a {@link LogEmitterBuilder} instance. - * - * @param instrumentationName the name of the instrumentation library - * @return a log emitter builder instance - */ + @Override public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) { if (instrumentationName == null || instrumentationName.isEmpty()) { LOGGER.fine("LogEmitter requested without instrumentation name."); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java index bbf269140ba..ccbef88c850 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java @@ -10,7 +10,7 @@ import io.opentelemetry.sdk.resources.Resource; import javax.annotation.concurrent.Immutable; -/** Sdk implementation of {@link LogData}. */ +/** SDK implementation of {@link LogData}. */ @AutoValue @Immutable abstract class SdkLogData implements LogData { diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java index a11083d6696..16a73954ddc 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java @@ -10,7 +10,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -/** Sdk implementation of {@link LogRecord}. */ +/** SDK implementation of {@link LogRecord}. */ @AutoValue @Immutable abstract class SdkLogRecord implements LogRecord { From f9e31acb92afa6f1b78646fd27e87ef7accf4fdb Mon Sep 17 00:00:00 2001 From: jack-berg Date: Thu, 28 Oct 2021 14:30:19 -0500 Subject: [PATCH 11/13] Respond to PR feedback --- CHANGELOG.md | 10 ++++ .../otlp/OtlpJsonLoggingLogExporterTest.java | 5 +- .../logging/SystemOutLogExporterTest.java | 3 +- .../http/logs/OtlpHttpLogExporterTest.java | 2 +- .../logs/LogsRequestMarshalerTest.java | 7 +-- .../otlp/logs/OtlpGrpcLogsExporterTest.java | 3 +- .../exporter/otlp/logs/ExportTest.java | 3 +- .../exporter/otlp/logs/ExportTest.java | 3 +- .../exporter/otlp/logs/ExportTest.java | 3 +- .../otlp/logs/OkHttpOnlyExportTest.java | 3 +- .../OtlpExporterIntegrationTest.java | 3 +- .../sdk/logs/LogEmitterProvider.java | 37 ------------- .../sdk/logs/LogEmitterSharedState.java | 10 ++-- .../opentelemetry/sdk/logs/LogProcessor.java | 52 +++++++++---------- .../opentelemetry/sdk/logs/SdkLogEmitter.java | 2 +- .../sdk/logs/SdkLogEmitterProvider.java | 28 ++++------ .../sdk/logs/data/LogRecordBuilder.java | 12 +++-- .../sdk/logs/data/SdkLogRecordBuilder.java | 10 ++-- .../sdk/logs/SdkLogEmitterProviderTest.java | 25 +++++---- .../sdk/logs/SdkLogEmitterTest.java | 6 +-- .../logs/export/BatchLogProcessorTest.java | 6 ++- .../logs/export/InMemoryLogExporterTest.java | 2 +- .../opentelemetry/sdk/logs/util/TestUtil.java | 3 +- 23 files changed, 110 insertions(+), 128 deletions(-) delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 406ff1e8ee5..d60dffb8697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## Version 1.8.0 (unreleased): +### SDK + +#### Logging (alpha) + +- This release includes a rework of the Log SDK to + implement [OTEP-0150](https://github.com/open-telemetry/oteps/blob/main/text/logs/0150-logging-library-sdk.md) + and to have more symmetry to the Trace SDK. `LogSink` is now `LogEmitter`. `LogEmitter` instances + are obtained from `SdkLogEmitterProvider`. Other additions include `MultiLogProcessor` (accessed + via `LogProcessor#composite(...)`), `SimpleLogProcessor`, and `InMemoryLogExporter`. + ### Auto-configuration (alpha) - BREAKING CHANGE: Remove deprecated `otel.experimental.exporter.otlp.protocol`, diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java index 8e85bd4c6c2..9704120a563 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java @@ -19,6 +19,7 @@ import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.resources.Resource; import java.util.Arrays; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -42,7 +43,7 @@ class OtlpJsonLoggingLogExporterTest { .setSeverityText("INFO") .setSpanId("8765432112345876") .setTraceId("12345678876543211234567887654322") - .setEpochMillis(1631533710L) + .setEpoch(1631533710L, TimeUnit.MILLISECONDS) .setAttributes(Attributes.of(stringKey("animal"), "cat", longKey("lives"), 9L)) .build()); @@ -58,7 +59,7 @@ class OtlpJsonLoggingLogExporterTest { .setSeverityText("INFO") .setSpanId("8765432112345875") .setTraceId("12345678876543211234567887654322") - .setEpochMillis(1631533710L) + .setEpoch(1631533710L, TimeUnit.MILLISECONDS) .setAttributes(Attributes.of(booleanKey("important"), true)) .build()); diff --git a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java index d9978279060..4124ccaad0c 100644 --- a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java +++ b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java @@ -23,6 +23,7 @@ import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneOffset; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; class SystemOutLogExporterTest { @@ -57,7 +58,7 @@ private static LogData sampleLog(long timestamp) { .setAttributes(Attributes.of(stringKey("cheese"), "cheddar", longKey("amount"), 1L)) .setBody(Body.stringBody("message")) .setSeverity(Severity.ERROR3) - .setEpochMillis(timestamp) + .setEpoch(timestamp, TimeUnit.MILLISECONDS) .setTraceId(TraceId.fromLongs(1, 2)) .setSpanId(SpanId.fromLong(3)) .build()); diff --git a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java index ca149d6424b..5f0258713c6 100644 --- a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java +++ b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java @@ -330,7 +330,7 @@ private static LogData generateFakeLog() { .setSeverityText(Severity.INFO.name()) .setTraceId(IdGenerator.random().generateTraceId()) .setSpanId(IdGenerator.random().generateSpanId()) - .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) + .setEpoch(Instant.now()) .setFlags(0) .build()); } diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java index cd4d3199169..f8bfe6a4a77 100644 --- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java +++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java @@ -34,6 +34,7 @@ import java.util.Base64; import java.util.Collections; import java.util.Locale; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; class LogsRequestMarshalerTest { @@ -61,7 +62,7 @@ void toProtoResourceLogs() { .setTraceId(TRACE_ID) .setSpanId(SPAN_ID) .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) + .setEpoch(12345, TimeUnit.NANOSECONDS) .build()))); assertThat(resourceLogsMarshalers).hasSize(1); @@ -95,7 +96,7 @@ void toProtoLogRecord() { .setTraceId(TRACE_ID) .setSpanId(SPAN_ID) .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) + .setEpoch(12345, TimeUnit.NANOSECONDS) .build()))); assertThat(logRecord.getTraceId().toByteArray()).isEqualTo(TRACE_ID_BYTES); @@ -125,7 +126,7 @@ void toProtoLogRecord_MinimalFields() { .setBody(BODY) .setSeverity(Severity.INFO) .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpochNanos(12345) + .setEpoch(12345, TimeUnit.NANOSECONDS) .build()))); assertThat(logRecord.getTraceId().toByteArray()).isEmpty(); diff --git a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java index d2f60d53c9e..150e7d70c0d 100644 --- a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java +++ b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java @@ -40,6 +40,7 @@ import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -361,7 +362,7 @@ private static LogData generateFakeLog() { Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(Instant.now()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) diff --git a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index eb9dfdd00a2..73adea71ba5 100644 --- a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -28,6 +28,7 @@ import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -43,7 +44,7 @@ class ExportTest { Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(Instant.now()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) diff --git a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index eb9dfdd00a2..73adea71ba5 100644 --- a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -28,6 +28,7 @@ import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -43,7 +44,7 @@ class ExportTest { Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(Instant.now()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) diff --git a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index eb9dfdd00a2..73adea71ba5 100644 --- a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -28,6 +28,7 @@ import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -43,7 +44,7 @@ class ExportTest { Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(Instant.now()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) diff --git a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java index 2716bb2dc18..f8ee78c748b 100644 --- a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java +++ b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java @@ -26,6 +26,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -44,7 +45,7 @@ class OkHttpOnlyExportTest { Resource.create(Attributes.builder().put("testKey", "testValue").build()), InstrumentationLibraryInfo.create("instrumentation", "1"), LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(Instant.now()) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) diff --git a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java index 89e28ad880c..aa2bad08063 100644 --- a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java +++ b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java @@ -73,7 +73,6 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import org.junit.jupiter.api.AfterAll; @@ -388,7 +387,7 @@ private static void testLogExporter(LogExporter logExporter) { .setSeverityText("DEBUG") .setTraceId(IdGenerator.random().generateTraceId()) .setSpanId(IdGenerator.random().generateSpanId()) - .setEpochNanos(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())) + .setEpoch(Instant.now()) .setFlags(0) .build()); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java deleted file mode 100644 index 90d235ee7bd..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs; - -import javax.annotation.Nullable; - -/** A registry for creating {@link LogEmitter}s. */ -public interface LogEmitterProvider { - - /** - * Gets or creates a {@link LogEmitter} instance. - * - * @param instrumentationName the name of the instrumentation library - * @return a log emitter instance - */ - LogEmitter get(String instrumentationName); - - /** - * Gets or creates a {@link LogEmitter} instance. - * - * @param instrumentationName the name of the instrumentation library - * @param instrumentationVersion the version of the instrumentation library - * @return a log emitter instance - */ - LogEmitter get(String instrumentationName, String instrumentationVersion); - - /** - * Creates a {@link LogEmitterBuilder} instance. - * - * @param instrumentationName the name of the instrumentation library - * @return a log emitter builder instance - */ - LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName); -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java index fe40f9f0a45..59349debb7b 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitterSharedState.java @@ -17,20 +17,20 @@ final class LogEmitterSharedState { private final Object lock = new Object(); private final Resource resource; - private final LogProcessor activeLogProcessor; + private final LogProcessor logProcessor; @Nullable private volatile CompletableResultCode shutdownResult = null; LogEmitterSharedState(Resource resource, List logProcessors) { this.resource = resource; - this.activeLogProcessor = LogProcessor.composite(logProcessors); + this.logProcessor = LogProcessor.composite(logProcessors); } Resource getResource() { return resource; } - LogProcessor getActiveLogProcessor() { - return activeLogProcessor; + LogProcessor getLogProcessor() { + return logProcessor; } boolean hasBeenShutdown() { @@ -42,7 +42,7 @@ CompletableResultCode shutdown() { if (shutdownResult != null) { return shutdownResult; } - shutdownResult = activeLogProcessor.shutdown(); + shutdownResult = logProcessor.shutdown(); return shutdownResult; } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java index c8a226396f7..bf2fbcd0cf1 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java @@ -22,6 +22,32 @@ @ThreadSafe public interface LogProcessor extends Closeable { + /** + * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code + * processors} in order. + */ + static LogProcessor composite(LogProcessor... processors) { + return composite(Arrays.asList(processors)); + } + + /** + * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code + * processors} in order. + */ + static LogProcessor composite(Iterable processors) { + List processorList = new ArrayList<>(); + for (LogProcessor processor : processors) { + processorList.add(processor); + } + if (processorList.isEmpty()) { + return NoopLogProcessor.getInstance(); + } + if (processorList.size() == 1) { + return processorList.get(0); + } + return MultiLogProcessor.create(processorList); + } + /** * Emit a log. * @@ -54,30 +80,4 @@ default CompletableResultCode forceFlush() { default void close() { shutdown().join(10, TimeUnit.SECONDS); } - - /** - * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code - * processors} in order. - */ - static LogProcessor composite(LogProcessor... processors) { - return composite(Arrays.asList(processors)); - } - - /** - * Returns a {@link LogProcessor} which simply delegates to all processing to the {@code - * processors} in order. - */ - static LogProcessor composite(Iterable processors) { - List processorList = new ArrayList<>(); - for (LogProcessor processor : processors) { - processorList.add(processor); - } - if (processorList.isEmpty()) { - return NoopLogProcessor.getInstance(); - } - if (processorList.size() == 1) { - return processorList.get(0); - } - return MultiLogProcessor.create(processorList); - } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java index 61b4fee725a..93c48f72b53 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java @@ -25,7 +25,7 @@ final class SdkLogEmitter implements LogEmitter { @Override public void emit(LogRecord logRecord) { logEmitterSharedState - .getActiveLogProcessor() + .getLogProcessor() .emit( LogData.create( logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java index 740bee4efb4..a963606f75c 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProvider.java @@ -13,10 +13,9 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.Nullable; -/** SDK implementation of {@link LogEmitterProvider}. */ -public final class SdkLogEmitterProvider implements LogEmitterProvider, Closeable { +/** SDK registry for creating {@link LogEmitter}s. */ +public final class SdkLogEmitterProvider implements Closeable { static final String DEFAULT_EMITTER_NAME = "unknown"; private static final Logger LOGGER = Logger.getLogger(SdkLogEmitterProvider.class.getName()); @@ -41,20 +40,13 @@ public static SdkLogEmitterProviderBuilder builder() { new SdkLogEmitter(sharedState, instrumentationLibraryInfo)); } - @Override - public LogEmitter get(String instrumentationName) { - return logEmitterBuilder(instrumentationName).build(); - } - - @Override - public LogEmitter get(String instrumentationName, String instrumentationVersion) { - return logEmitterBuilder(instrumentationName) - .setInstrumentationVersion(instrumentationVersion) - .build(); - } - - @Override - public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) { + /** + * Creates a {@link LogEmitterBuilder} instance. + * + * @param instrumentationName the name of the instrumentation library + * @return a log emitter builder instance + */ + public LogEmitterBuilder logEmitterBuilder(String instrumentationName) { if (instrumentationName == null || instrumentationName.isEmpty()) { LOGGER.fine("LogEmitter requested without instrumentation name."); instrumentationName = DEFAULT_EMITTER_NAME; @@ -68,7 +60,7 @@ public LogEmitterBuilder logEmitterBuilder(@Nullable String instrumentationName) * @return a {@link CompletableResultCode} which is completed when the flush is finished */ public CompletableResultCode forceFlush() { - return sharedState.getActiveLogProcessor().forceFlush(); + return sharedState.getLogProcessor().forceFlush(); } /** diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java index c33275c2ddc..a1b99e0e3be 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java @@ -6,15 +6,17 @@ package io.opentelemetry.sdk.logs.data; import io.opentelemetry.api.common.Attributes; +import java.time.Instant; +import java.util.concurrent.TimeUnit; -/** Interface for building for {@link LogRecord}. */ +/** Builder for {@link LogRecord}. */ public interface LogRecordBuilder { - /** Set the epoch timestamp in nanos. */ - LogRecordBuilder setEpochNanos(long timestamp); + /** Set the epoch timestamp using the timestamp and unit. */ + LogRecordBuilder setEpoch(long timestamp, TimeUnit unit); - /** Set the epoch timestamp in millis. */ - LogRecordBuilder setEpochMillis(long timestamp); + /** Set the epoch timestamp using the instant. */ + LogRecordBuilder setEpoch(Instant instant); /** Set the trace id. */ LogRecordBuilder setTraceId(String traceId); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java index 624cc99c05a..4b8a9283ea9 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import java.time.Instant; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -26,14 +27,15 @@ final class SdkLogRecordBuilder implements LogRecordBuilder { SdkLogRecordBuilder() {} @Override - public SdkLogRecordBuilder setEpochNanos(long timestamp) { - this.epochNanos = timestamp; + public SdkLogRecordBuilder setEpoch(long timestamp, TimeUnit unit) { + this.epochNanos = unit.toNanos(timestamp); return this; } @Override - public SdkLogRecordBuilder setEpochMillis(long timestamp) { - return setEpochNanos(TimeUnit.MILLISECONDS.toNanos(timestamp)); + public SdkLogRecordBuilder setEpoch(Instant instant) { + this.epochNanos = TimeUnit.SECONDS.toNanos(instant.getEpochSecond()) + instant.getNano(); + return this; } @Override diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java index d795ede7215..32b05de2738 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderTest.java @@ -61,7 +61,7 @@ void builder_resourceProvided() { void builder_noProcessor() { assertThat(SdkLogEmitterProvider.builder().build()) .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) - .extracting(LogEmitterSharedState::getActiveLogProcessor) + .extracting(LogEmitterSharedState::getLogProcessor) .isSameAs(NoopLogProcessor.getInstance()); } @@ -73,7 +73,7 @@ void builder_multipleProcessors() { .addLogProcessor(logProcessor) .build()) .extracting("sharedState", as(InstanceOfAssertFactories.type(LogEmitterSharedState.class))) - .extracting(LogEmitterSharedState::getActiveLogProcessor) + .extracting(LogEmitterSharedState::getLogProcessor) .satisfies( activeLogProcessor -> { assertThat(activeLogProcessor).isInstanceOf(MultiLogProcessor.class); @@ -85,18 +85,23 @@ void builder_multipleProcessors() { } @Test - void get_SameName() { - assertThat(sdkLogEmitterProvider.get("test")) - .isSameAs(sdkLogEmitterProvider.get("test")) - .isSameAs(sdkLogEmitterProvider.get("test", null)) + void logEmitterBuilder_SameName() { + assertThat(sdkLogEmitterProvider.logEmitterBuilder("test").build()) .isSameAs(sdkLogEmitterProvider.logEmitterBuilder("test").build()) - .isNotSameAs(sdkLogEmitterProvider.get("test", "version")); + .isNotSameAs( + sdkLogEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .build()); } @Test - void get_SameNameAndVersion() { - assertThat(sdkLogEmitterProvider.get("test", "version")) - .isSameAs(sdkLogEmitterProvider.get("test", "version")) + void logEmitterBuilder_SameNameAndVersion() { + assertThat( + sdkLogEmitterProvider + .logEmitterBuilder("test") + .setInstrumentationVersion("version") + .build()) .isSameAs( sdkLogEmitterProvider .logEmitterBuilder("test") diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java index a08efbb2539..a6090990f48 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java @@ -13,6 +13,7 @@ import io.opentelemetry.sdk.logs.data.LogData; import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.resources.Resource; +import java.time.Instant; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -45,10 +46,7 @@ void setup() { @Test void emit() { LogRecord logRecord = - LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) - .setBody(Body.stringBody("message")) - .build(); + LogRecord.builder().setEpoch(Instant.now()).setBody(Body.stringBody("message")).build(); sdkLogEmitter.emit(logRecord); ArgumentCaptor captor = ArgumentCaptor.forClass(LogData.class); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java index 6fe4d917e23..68f47ba9eec 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java @@ -36,7 +36,8 @@ void testBatchSize() { .build(); SdkLogEmitterProvider provider = SdkLogEmitterProvider.builder().addLogProcessor(processor).build(); - LogEmitter emitter = provider.get("test", "0.1a"); + LogEmitter emitter = + provider.logEmitterBuilder("test").setInstrumentationVersion("0.1a").build(); for (int i = 0; i < 7; i++) { emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); @@ -68,7 +69,8 @@ void testNoBlocking() { .build(); SdkLogEmitterProvider provider = SdkLogEmitterProvider.builder().addLogProcessor(processor).build(); - LogEmitter emitter = provider.get("test", "0.1a"); + LogEmitter emitter = + provider.logEmitterBuilder("test").setInstrumentationVersion("0.1a").build(); long start = System.currentTimeMillis(); int testRecordCount = 700; diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java index 8362a9713ed..cd28b6ed536 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java @@ -31,7 +31,7 @@ void setup() { SdkLogEmitterProvider.builder() .addLogProcessor(SimpleLogProcessor.create(exporter)) .build(); - logEmitter = logEmitterProvider.get(null, null); + logEmitter = logEmitterProvider.logEmitterBuilder("emitter").build(); } @AfterEach diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java index 6c18936e0ee..1bb63e85865 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java @@ -14,12 +14,13 @@ import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; +import java.util.concurrent.TimeUnit; public final class TestUtil { public static LogRecord createLogRecord(Severity severity, String message) { return LogRecord.builder() - .setEpochMillis(System.currentTimeMillis()) + .setEpoch(System.currentTimeMillis(), TimeUnit.MILLISECONDS) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) .setFlags(TraceFlags.getDefault().asByte()) From 8d4785cfad6a556b05dc8bd803d8e5dd4b3e825c Mon Sep 17 00:00:00 2001 From: jack-berg Date: Thu, 28 Oct 2021 15:21:54 -0500 Subject: [PATCH 12/13] Make SdkLogEmitterBuilder final --- .../java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java index a1e2929a4a5..30b8903dad1 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterBuilder.java @@ -8,7 +8,7 @@ import io.opentelemetry.sdk.internal.ComponentRegistry; import javax.annotation.Nullable; -class SdkLogEmitterBuilder implements LogEmitterBuilder { +final class SdkLogEmitterBuilder implements LogEmitterBuilder { private final ComponentRegistry registry; private final String instrumentationName; From ca91bec9b2dd16ad17cb11f2963c651b3321eca2 Mon Sep 17 00:00:00 2001 From: jack-berg Date: Fri, 29 Oct 2021 13:19:16 -0500 Subject: [PATCH 13/13] Switch to LogEmitter.logBuilder().emit() pattern --- .../otlp/OtlpJsonLoggingLogExporterTest.java | 51 +++++----- .../logging/SystemOutLogExporterTest.java | 20 ++-- .../http/logs/OtlpHttpLogExporterTest.java | 28 +++--- .../logs/LogsRequestMarshalerTest.java | 67 ++++++------- .../otlp/logs/OtlpGrpcLogsExporterTest.java | 28 +++--- .../exporter/otlp/logs/ExportTest.java | 28 +++--- .../exporter/otlp/logs/ExportTest.java | 28 +++--- .../exporter/otlp/logs/ExportTest.java | 28 +++--- .../otlp/logs/OkHttpOnlyExportTest.java | 28 +++--- .../OtlpExporterIntegrationTest.java | 29 +++--- .../io/opentelemetry/sdk/logs/LogBuilder.java | 57 +++++++++++ .../io/opentelemetry/sdk/logs/LogEmitter.java | 19 ++-- .../opentelemetry/sdk/logs/LogProcessor.java | 5 +- .../opentelemetry/sdk/logs/SdkLogEmitter.java | 99 +++++++++++++++++-- .../logs/SdkLogEmitterProviderBuilder.java | 6 +- .../opentelemetry/sdk/logs/data/LogData.java | 51 ++++++++-- ...RecordBuilder.java => LogDataBuilder.java} | 66 +++++++------ .../{SdkLogRecord.java => LogDataImpl.java} | 25 +++-- .../sdk/logs/data/LogRecord.java | 53 ---------- .../sdk/logs/data/LogRecordBuilder.java | 50 ---------- .../sdk/logs/data/SdkLogData.java | 37 ------- .../sdk/logs/export/SimpleLogProcessor.java | 3 +- .../sdk/logs/SdkLogEmitterTest.java | 34 +++++-- .../logs/export/BatchLogProcessorTest.java | 5 +- .../logs/export/InMemoryLogExporterTest.java | 20 ++-- .../opentelemetry/sdk/logs/util/TestUtil.java | 14 +-- 26 files changed, 456 insertions(+), 423 deletions(-) create mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogBuilder.java rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{SdkLogRecordBuilder.java => LogDataBuilder.java} (50%) rename sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/{SdkLogRecord.java => LogDataImpl.java} (51%) delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java delete mode 100644 sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java index 9704120a563..2c6ee030008 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogExporterTest.java @@ -14,7 +14,6 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.resources.Resource; @@ -32,36 +31,30 @@ class OtlpJsonLoggingLogExporterTest { Resource.create(Attributes.builder().put("key", "value").build()); private static final LogData LOG1 = - LogData.create( - RESOURCE, - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setName("testLog1") - .setBody("body1") - .setFlags(0) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setSpanId("8765432112345876") - .setTraceId("12345678876543211234567887654322") - .setEpoch(1631533710L, TimeUnit.MILLISECONDS) - .setAttributes(Attributes.of(stringKey("animal"), "cat", longKey("lives"), 9L)) - .build()); + LogData.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation", "1")) + .setName("testLog1") + .setBody("body1") + .setFlags(0) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setSpanId("8765432112345876") + .setTraceId("12345678876543211234567887654322") + .setEpoch(1631533710L, TimeUnit.MILLISECONDS) + .setAttributes(Attributes.of(stringKey("animal"), "cat", longKey("lives"), 9L)) + .build(); private static final LogData LOG2 = - LogData.create( - RESOURCE, - InstrumentationLibraryInfo.create("instrumentation2", "2"), - LogRecord.builder() - .setName("testLog2") - .setBody("body2") - .setFlags(0) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setSpanId("8765432112345875") - .setTraceId("12345678876543211234567887654322") - .setEpoch(1631533710L, TimeUnit.MILLISECONDS) - .setAttributes(Attributes.of(booleanKey("important"), true)) - .build()); + LogData.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation2", "2")) + .setName("testLog2") + .setBody("body2") + .setFlags(0) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setSpanId("8765432112345875") + .setTraceId("12345678876543211234567887654322") + .setEpoch(1631533710L, TimeUnit.MILLISECONDS) + .setAttributes(Attributes.of(booleanKey("important"), true)) + .build(); @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(OtlpJsonLoggingLogExporter.class); diff --git a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java index 4124ccaad0c..b124809eadf 100644 --- a/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java +++ b/exporters/logging/src/test/java/io/opentelemetry/exporter/logging/SystemOutLogExporterTest.java @@ -17,7 +17,6 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.time.LocalDateTime; @@ -51,16 +50,13 @@ void format() { } private static LogData sampleLog(long timestamp) { - return LogData.create( - Resource.empty(), - InstrumentationLibraryInfo.create("logTest", "1.0"), - LogRecord.builder() - .setAttributes(Attributes.of(stringKey("cheese"), "cheddar", longKey("amount"), 1L)) - .setBody(Body.stringBody("message")) - .setSeverity(Severity.ERROR3) - .setEpoch(timestamp, TimeUnit.MILLISECONDS) - .setTraceId(TraceId.fromLongs(1, 2)) - .setSpanId(SpanId.fromLong(3)) - .build()); + return LogData.builder(Resource.empty(), InstrumentationLibraryInfo.create("logTest", "1.0")) + .setAttributes(Attributes.of(stringKey("cheese"), "cheddar", longKey("amount"), 1L)) + .setBody(Body.stringBody("message")) + .setSeverity(Severity.ERROR3) + .setEpoch(timestamp, TimeUnit.MILLISECONDS) + .setTraceId(TraceId.fromLongs(1, 2)) + .setSpanId(SpanId.fromLong(3)) + .build(); } } diff --git a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java index 5f0258713c6..4dfa184c042 100644 --- a/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java +++ b/exporters/otlp-http/logs/src/test/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogExporterTest.java @@ -31,7 +31,6 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.IdGenerator; @@ -319,19 +318,18 @@ private static HttpResponse buildResponse(HttpStatus httpSta } private static LogData generateFakeLog() { - return LogData.create( - Resource.getDefault(), - InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), - LogRecord.builder() - .setName("log-name") - .setBody(Body.stringBody("log body")) - .setAttributes(Attributes.builder().put("key", "value").build()) - .setSeverity(Severity.INFO) - .setSeverityText(Severity.INFO.name()) - .setTraceId(IdGenerator.random().generateTraceId()) - .setSpanId(IdGenerator.random().generateSpanId()) - .setEpoch(Instant.now()) - .setFlags(0) - .build()); + return LogData.builder( + Resource.getDefault(), + InstrumentationLibraryInfo.create("testLib", "1.0", "http://url")) + .setName("log-name") + .setBody(Body.stringBody("log body")) + .setAttributes(Attributes.builder().put("key", "value").build()) + .setSeverity(Severity.INFO) + .setSeverityText(Severity.INFO.name()) + .setTraceId(IdGenerator.random().generateTraceId()) + .setSpanId(IdGenerator.random().generateSpanId()) + .setEpoch(Instant.now()) + .setFlags(0) + .build(); } } diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java index f8bfe6a4a77..e9dbca96534 100644 --- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java +++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/logs/LogsRequestMarshalerTest.java @@ -51,19 +51,18 @@ void toProtoResourceLogs() { ResourceLogsMarshaler[] resourceLogsMarshalers = ResourceLogsMarshaler.create( Collections.singleton( - LogData.create( - Resource.builder().put("one", 1).setSchemaUrl("http://url").build(), - InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"), - io.opentelemetry.sdk.logs.data.LogRecord.builder() - .setName(NAME) - .setBody(BODY) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setTraceId(TRACE_ID) - .setSpanId(SPAN_ID) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpoch(12345, TimeUnit.NANOSECONDS) - .build()))); + LogData.builder( + Resource.builder().put("one", 1).setSchemaUrl("http://url").build(), + InstrumentationLibraryInfo.create("testLib", "1.0", "http://url")) + .setName(NAME) + .setBody(BODY) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpoch(12345, TimeUnit.NANOSECONDS) + .build())); assertThat(resourceLogsMarshalers).hasSize(1); @@ -85,19 +84,18 @@ void toProtoLogRecord() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - io.opentelemetry.sdk.logs.data.LogRecord.builder() - .setName(NAME) - .setBody(BODY) - .setSeverity(Severity.INFO) - .setSeverityText("INFO") - .setTraceId(TRACE_ID) - .setSpanId(SPAN_ID) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpoch(12345, TimeUnit.NANOSECONDS) - .build()))); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setName(NAME) + .setBody(BODY) + .setSeverity(Severity.INFO) + .setSeverityText("INFO") + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpoch(12345, TimeUnit.NANOSECONDS) + .build())); assertThat(logRecord.getTraceId().toByteArray()).isEqualTo(TRACE_ID_BYTES); assertThat(logRecord.getSpanId().toByteArray()).isEqualTo(SPAN_ID_BYTES); @@ -119,15 +117,14 @@ void toProtoLogRecord_MinimalFields() { parse( LogRecord.getDefaultInstance(), LogMarshaler.create( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - io.opentelemetry.sdk.logs.data.LogRecord.builder() - .setBody(BODY) - .setSeverity(Severity.INFO) - .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) - .setEpoch(12345, TimeUnit.NANOSECONDS) - .build()))); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setBody(BODY) + .setSeverity(Severity.INFO) + .setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true)) + .setEpoch(12345, TimeUnit.NANOSECONDS) + .build())); assertThat(logRecord.getTraceId().toByteArray()).isEmpty(); assertThat(logRecord.getSpanId().toByteArray()).isEmpty(); diff --git a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java index 150e7d70c0d..a03c7a7942b 100644 --- a/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java +++ b/exporters/otlp/logs/src/test/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogsExporterTest.java @@ -32,7 +32,6 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.io.ByteArrayOutputStream; @@ -358,20 +357,19 @@ void usingGrpc() { } private static LogData generateFakeLog() { - return LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setEpoch(Instant.now()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build()); + return LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setEpoch(Instant.now()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build(); } private static final class FakeCollector extends LogsServiceGrpc.LogsServiceImplBase { diff --git a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 73adea71ba5..cfb4411b0f0 100644 --- a/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNetty/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,6 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,20 +39,19 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setEpoch(Instant.now()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build())); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setEpoch(Instant.now()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 73adea71ba5..cfb4411b0f0 100644 --- a/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcNettyShaded/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,6 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,20 +39,19 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setEpoch(Instant.now()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build())); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setEpoch(Instant.now()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java index 73adea71ba5..cfb4411b0f0 100644 --- a/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java +++ b/exporters/otlp/logs/src/testGrpcOkhttp/java/io/opentelemetry/exporter/otlp/logs/ExportTest.java @@ -23,7 +23,6 @@ import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.nio.charset.StandardCharsets; @@ -40,20 +39,19 @@ class ExportTest { private static final List LOGS = Collections.singletonList( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setEpoch(Instant.now()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build())); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setEpoch(Instant.now()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); @RegisterExtension @Order(1) diff --git a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java index f8ee78c748b..e604ff65569 100644 --- a/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java +++ b/exporters/otlp/logs/src/testOkHttpOnly/java/io/opentelemetry/exporter/otlp/logs/OkHttpOnlyExportTest.java @@ -20,7 +20,6 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.net.InetAddress; @@ -41,20 +40,19 @@ class OkHttpOnlyExportTest { private static final List LOGS = Collections.singletonList( - LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - LogRecord.builder() - .setEpoch(Instant.now()) - .setTraceId(TraceId.getInvalid()) - .setSpanId(SpanId.getInvalid()) - .setFlags(TraceFlags.getDefault().asByte()) - .setSeverity(Severity.ERROR) - .setSeverityText("really severe") - .setName("log1") - .setBody("message") - .setAttributes(Attributes.builder().put("animal", "cat").build()) - .build())); + LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) + .setEpoch(Instant.now()) + .setTraceId(TraceId.getInvalid()) + .setSpanId(SpanId.getInvalid()) + .setFlags(TraceFlags.getDefault().asByte()) + .setSeverity(Severity.ERROR) + .setSeverityText("really severe") + .setName("log1") + .setBody("message") + .setAttributes(Attributes.builder().put("animal", "cat").build()) + .build()); private static final HeldCertificate HELD_CERTIFICATE; private static final String canonicalHostName; diff --git a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java index aa2bad08063..59c13783325 100644 --- a/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java +++ b/integration-tests/src/testOtlpCommon/java/io/opentelemetry/integrationtest/OtlpExporterIntegrationTest.java @@ -53,7 +53,6 @@ import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.logs.export.LogExporter; import io.opentelemetry.sdk.metrics.SdkMeterProvider; @@ -376,20 +375,20 @@ void testOtlpHttpLogExport(String compression) { private static void testLogExporter(LogExporter logExporter) { LogData logData = - LogData.create( - RESOURCE, - InstrumentationLibraryInfo.create(OtlpExporterIntegrationTest.class.getName(), null), - LogRecord.builder() - .setName("log-name") - .setBody(Body.stringBody("log body")) - .setAttributes(Attributes.builder().put("key", "value").build()) - .setSeverity(Severity.DEBUG) - .setSeverityText("DEBUG") - .setTraceId(IdGenerator.random().generateTraceId()) - .setSpanId(IdGenerator.random().generateSpanId()) - .setEpoch(Instant.now()) - .setFlags(0) - .build()); + LogData.builder( + RESOURCE, + InstrumentationLibraryInfo.create( + OtlpExporterIntegrationTest.class.getName(), null)) + .setName("log-name") + .setBody(Body.stringBody("log body")) + .setAttributes(Attributes.builder().put("key", "value").build()) + .setSeverity(Severity.DEBUG) + .setSeverityText("DEBUG") + .setTraceId(IdGenerator.random().generateTraceId()) + .setSpanId(IdGenerator.random().generateSpanId()) + .setEpoch(Instant.now()) + .setFlags(0) + .build(); logExporter.export(Collections.singletonList(logData)); diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogBuilder.java new file mode 100644 index 00000000000..e9c80c95011 --- /dev/null +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogBuilder.java @@ -0,0 +1,57 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.logs; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.logs.data.Body; +import io.opentelemetry.sdk.logs.data.Severity; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +/** + * Used to construct and emit logs from a {@link LogEmitter}. + * + *

Obtain a {@link LogBuilder} via {@link LogEmitter#logBuilder()}, add properties using the + * setters, and emit the log to downstream {@link LogProcessor}(s) by calling {@link #emit()}. + */ +public interface LogBuilder { + + /** Set the epoch timestamp using the timestamp and unit. */ + LogBuilder setEpoch(long timestamp, TimeUnit unit); + + /** Set the epoch timestamp using the instant. */ + LogBuilder setEpoch(Instant instant); + + /** Set the trace id. */ + LogBuilder setTraceId(String traceId); + + /** Set the span id. */ + LogBuilder setSpanId(String spanId); + + /** Set the flags. */ + LogBuilder setFlags(int flags); + + /** Set the severity. */ + LogBuilder setSeverity(Severity severity); + + /** Set the severity text. */ + LogBuilder setSeverityText(String severityText); + + /** Set the name. */ + LogBuilder setName(String name); + + /** Set the body. */ + LogBuilder setBody(Body body); + + /** Set the body string. */ + LogBuilder setBody(String body); + + /** Set the attributes. */ + LogBuilder setAttributes(Attributes attributes); + + /** Emit the log to downstream {@link LogProcessor}(s). */ + void emit(); +} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java index 05a2dc1d908..37a0a48a822 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogEmitter.java @@ -5,25 +5,22 @@ package io.opentelemetry.sdk.logs; -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; -import io.opentelemetry.sdk.resources.Resource; import javax.annotation.concurrent.ThreadSafe; /** - * A {@link LogEmitter} is the entry point into a log pipeline. Log emitters accept {@link - * LogRecord}s, and after associating them with a {@link Resource} and {@link - * InstrumentationLibraryInfo}, pushes them to downstream {@link LogProcessor#emit(LogData)}. + * A {@link LogEmitter} is the entry point into a log pipeline. + * + *

Obtain a log builder via {@link #logBuilder()}, add properties using the setters, and emit it + * to downstream {@link LogProcessor}(s) via {@link LogBuilder#emit()}. */ @ThreadSafe public interface LogEmitter { /** - * Emit a log record. Associates the log with a {@link Resource} and {@link - * InstrumentationLibraryInfo}, and pushes it to {@link LogProcessor#emit(LogData)}. + * Return a {@link LogBuilder} to emit a log. * - * @param logRecord the log record + *

Build the log using the {@link LogBuilder} setters, and emit it to downstream {@link + * LogProcessor}(s) via {@link LogBuilder#emit()}. */ - void emit(LogRecord logRecord); + LogBuilder logBuilder(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java index bf2fbcd0cf1..77a6cbb8858 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/LogProcessor.java @@ -7,7 +7,6 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import java.io.Closeable; import java.util.ArrayList; import java.util.Arrays; @@ -16,8 +15,8 @@ import javax.annotation.concurrent.ThreadSafe; /** - * {@link LogProcessor} is the interface to allow synchronous hooks for when {@link - * SdkLogEmitter#emit(LogRecord)} is called. + * {@link LogProcessor} is the interface to allow synchronous hooks for logs emitted by {@link + * LogEmitter}s. */ @ThreadSafe public interface LogProcessor extends Closeable { diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java index 93c48f72b53..6d1ca7bf2bf 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitter.java @@ -5,9 +5,14 @@ package io.opentelemetry.sdk.logs; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; +import io.opentelemetry.sdk.logs.data.LogDataBuilder; +import io.opentelemetry.sdk.logs.data.Severity; +import java.time.Instant; +import java.util.concurrent.TimeUnit; /** SDK implementation of {@link LogEmitter}. */ final class SdkLogEmitter implements LogEmitter { @@ -23,16 +28,96 @@ final class SdkLogEmitter implements LogEmitter { } @Override - public void emit(LogRecord logRecord) { - logEmitterSharedState - .getLogProcessor() - .emit( - LogData.create( - logEmitterSharedState.getResource(), instrumentationLibraryInfo, logRecord)); + public LogBuilder logBuilder() { + return new SdkLogBuilder(); } // VisibleForTesting InstrumentationLibraryInfo getInstrumentationLibraryInfo() { return instrumentationLibraryInfo; } + + private final class SdkLogBuilder implements LogBuilder { + + private final LogDataBuilder logDataBuilder; + + SdkLogBuilder() { + this.logDataBuilder = + LogData.builder(logEmitterSharedState.getResource(), instrumentationLibraryInfo); + } + + @Override + public LogBuilder setEpoch(long timestamp, TimeUnit unit) { + logDataBuilder.setEpoch(timestamp, unit); + return this; + } + + @Override + public LogBuilder setEpoch(Instant instant) { + logDataBuilder.setEpoch(instant); + return this; + } + + @Override + public LogBuilder setTraceId(String traceId) { + logDataBuilder.setTraceId(traceId); + return this; + } + + @Override + public LogBuilder setSpanId(String spanId) { + logDataBuilder.setSpanId(spanId); + return this; + } + + @Override + public LogBuilder setFlags(int flags) { + logDataBuilder.setFlags(flags); + return this; + } + + @Override + public LogBuilder setSeverity(Severity severity) { + logDataBuilder.setSeverity(severity); + return this; + } + + @Override + public LogBuilder setSeverityText(String severityText) { + logDataBuilder.setSeverityText(severityText); + return this; + } + + @Override + public LogBuilder setName(String name) { + logDataBuilder.setName(name); + return this; + } + + @Override + public LogBuilder setBody(Body body) { + logDataBuilder.setBody(body); + return this; + } + + @Override + public LogBuilder setBody(String body) { + logDataBuilder.setBody(body); + return this; + } + + @Override + public LogBuilder setAttributes(Attributes attributes) { + logDataBuilder.setAttributes(attributes); + return this; + } + + @Override + public void emit() { + if (logEmitterSharedState.hasBeenShutdown()) { + return; + } + logEmitterSharedState.getLogProcessor().emit(logDataBuilder.build()); + } + } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java index 1ffbae3bcff..9b638dba1ae 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogEmitterProviderBuilder.java @@ -8,7 +8,6 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.resources.Resource; import java.util.ArrayList; import java.util.List; @@ -35,9 +34,8 @@ public SdkLogEmitterProviderBuilder setResource(Resource resource) { } /** - * Add a log processor. {@link LogProcessor#emit(LogData)} will be called each time {@link - * LogEmitter#emit(LogRecord)} is called for emitter instances obtained from the {@link - * SdkLogEmitterProvider}. + * Add a log processor. {@link LogProcessor#emit(LogData)} will be called each time a log is + * emitted by {@link LogEmitter} instances obtained from the {@link SdkLogEmitterProvider}. * * @param processor the log processor * @return this diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java index 9055aed10f5..61d6d74b710 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogData.java @@ -5,22 +5,24 @@ package io.opentelemetry.sdk.logs.data; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.resources.Resource; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** - * A {@link LogRecord} with an associated {@link Resource} and {@link InstrumentationLibraryInfo}. + * Log definition as described in OpenTelemetry + * Log Data Model. */ @Immutable -public interface LogData extends LogRecord { - - /** Create a log data instance. */ - static LogData create( - Resource resource, - InstrumentationLibraryInfo instrumentationLibraryInfo, - LogRecord logRecord) { - return SdkLogData.create(resource, instrumentationLibraryInfo, logRecord); +public interface LogData { + + /** Returns a new {@link LogDataBuilder}. */ + static LogDataBuilder builder( + Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) { + return new LogDataBuilder(resource, instrumentationLibraryInfo); } /** Returns the resource of this log. */ @@ -28,4 +30,35 @@ static LogData create( /** Returns the instrumentation library that generated this log. */ InstrumentationLibraryInfo getInstrumentationLibraryInfo(); + + /** Returns the epoch timestamp in nanos when the log was recorded. */ + long getEpochNanos(); + + /** Returns the trace id for this log. */ + @Nullable + String getTraceId(); + + /** Returns the span id for this log. */ + @Nullable + String getSpanId(); + + /** Returns the flags for this log. */ + int getFlags(); + + /** Returns the severity for this log. */ + Severity getSeverity(); + + /** Returns the severity text for this log. */ + @Nullable + String getSeverityText(); + + /** Returns the name for this log. */ + @Nullable + String getName(); + + /** Returns the body for this log. */ + Body getBody(); + + /** Returns the attributes for this log. */ + Attributes getAttributes(); } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataBuilder.java similarity index 50% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataBuilder.java index 4b8a9283ea9..7084c8f4263 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecordBuilder.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataBuilder.java @@ -7,12 +7,17 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.resources.Resource; import java.time.Instant; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -/** Builder for {@link SdkLogRecordBuilder}. */ -final class SdkLogRecordBuilder implements LogRecordBuilder { +/** Builder for {@link LogData}. */ +public final class LogDataBuilder { + + private final Resource resource; + private final InstrumentationLibraryInfo instrumentationLibraryInfo; private long epochNanos; @Nullable private String traceId; @@ -24,79 +29,84 @@ final class SdkLogRecordBuilder implements LogRecordBuilder { private Body body = Body.stringBody(""); private final AttributesBuilder attributeBuilder = Attributes.builder(); - SdkLogRecordBuilder() {} + LogDataBuilder(Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) { + this.resource = resource; + this.instrumentationLibraryInfo = instrumentationLibraryInfo; + } - @Override - public SdkLogRecordBuilder setEpoch(long timestamp, TimeUnit unit) { + /** Set the epoch timestamp using the timestamp and unit. */ + public LogDataBuilder setEpoch(long timestamp, TimeUnit unit) { this.epochNanos = unit.toNanos(timestamp); return this; } - @Override - public SdkLogRecordBuilder setEpoch(Instant instant) { + /** Set the epoch timestamp using the instant. */ + public LogDataBuilder setEpoch(Instant instant) { this.epochNanos = TimeUnit.SECONDS.toNanos(instant.getEpochSecond()) + instant.getNano(); return this; } - @Override - public SdkLogRecordBuilder setTraceId(String traceId) { + /** Set the trace id. */ + public LogDataBuilder setTraceId(String traceId) { this.traceId = traceId; return this; } - @Override - public SdkLogRecordBuilder setSpanId(String spanId) { + /** Set the span id. */ + public LogDataBuilder setSpanId(String spanId) { this.spanId = spanId; return this; } - @Override - public SdkLogRecordBuilder setFlags(int flags) { + /** Set the flags. */ + public LogDataBuilder setFlags(int flags) { this.flags = flags; return this; } - @Override - public SdkLogRecordBuilder setSeverity(Severity severity) { + /** Set the severity. */ + public LogDataBuilder setSeverity(Severity severity) { this.severity = severity; return this; } - @Override - public SdkLogRecordBuilder setSeverityText(String severityText) { + /** Set the severity text. */ + public LogDataBuilder setSeverityText(String severityText) { this.severityText = severityText; return this; } - @Override - public SdkLogRecordBuilder setName(String name) { + /** Set the name. */ + public LogDataBuilder setName(String name) { this.name = name; return this; } - @Override - public SdkLogRecordBuilder setBody(Body body) { + /** Set the body. */ + public LogDataBuilder setBody(Body body) { this.body = body; return this; } - @Override - public SdkLogRecordBuilder setBody(String body) { + /** Set the body string. */ + public LogDataBuilder setBody(String body) { return setBody(Body.stringBody(body)); } - @Override - public SdkLogRecordBuilder setAttributes(Attributes attributes) { + /** Set the attributes. */ + public LogDataBuilder setAttributes(Attributes attributes) { this.attributeBuilder.putAll(attributes); return this; } - @Override - public SdkLogRecord build() { + /** Build a {@link LogData} instance from the configured properties. */ + public LogData build() { if (epochNanos == 0) { epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); } - return SdkLogRecord.create( + return LogDataImpl.create( + resource, + instrumentationLibraryInfo, epochNanos, traceId, spanId, diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataImpl.java similarity index 51% rename from sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java rename to sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataImpl.java index 16a73954ddc..b6533630f6c 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogRecord.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogDataImpl.java @@ -7,17 +7,20 @@ import com.google.auto.value.AutoValue; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; +import io.opentelemetry.sdk.resources.Resource; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -/** SDK implementation of {@link LogRecord}. */ @AutoValue @Immutable -abstract class SdkLogRecord implements LogRecord { +abstract class LogDataImpl implements LogData { - SdkLogRecord() {} + LogDataImpl() {} - static SdkLogRecord create( + static LogDataImpl create( + Resource resource, + InstrumentationLibraryInfo instrumentationLibraryInfo, long epochNanos, @Nullable String traceId, @Nullable String spanId, @@ -27,7 +30,17 @@ static SdkLogRecord create( @Nullable String name, Body body, Attributes attributes) { - return new AutoValue_SdkLogRecord( - epochNanos, traceId, spanId, flags, severity, severityText, name, body, attributes); + return new AutoValue_LogDataImpl( + resource, + instrumentationLibraryInfo, + epochNanos, + traceId, + spanId, + flags, + severity, + severityText, + name, + body, + attributes); } } diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java deleted file mode 100644 index f955d25f393..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecord.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs.data; - -import io.opentelemetry.api.common.Attributes; -import javax.annotation.Nullable; - -/** - * Implementation of a log as defined in OpenTelemetry - * Log Data Model. - */ -public interface LogRecord { - - /** Returns a new {@link LogRecordBuilder}. */ - static LogRecordBuilder builder() { - return new SdkLogRecordBuilder(); - } - - /** Returns the epoch timestamp in nanos when the log was recorded. */ - long getEpochNanos(); - - /** Returns the trace id for this log. */ - @Nullable - String getTraceId(); - - /** Returns the span id for this log. */ - @Nullable - String getSpanId(); - - /** Returns the flags for this log. */ - int getFlags(); - - /** Returns the severity for this log. */ - Severity getSeverity(); - - /** Returns the severity text for this log. */ - @Nullable - String getSeverityText(); - - /** Returns the name for this log. */ - @Nullable - String getName(); - - /** Returns the body for this log. */ - Body getBody(); - - /** Returns the attributes for this log. */ - Attributes getAttributes(); -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java deleted file mode 100644 index a1b99e0e3be..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/LogRecordBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs.data; - -import io.opentelemetry.api.common.Attributes; -import java.time.Instant; -import java.util.concurrent.TimeUnit; - -/** Builder for {@link LogRecord}. */ -public interface LogRecordBuilder { - - /** Set the epoch timestamp using the timestamp and unit. */ - LogRecordBuilder setEpoch(long timestamp, TimeUnit unit); - - /** Set the epoch timestamp using the instant. */ - LogRecordBuilder setEpoch(Instant instant); - - /** Set the trace id. */ - LogRecordBuilder setTraceId(String traceId); - - /** Set the span id. */ - LogRecordBuilder setSpanId(String spanId); - - /** Set the flags. */ - LogRecordBuilder setFlags(int flags); - - /** Set the severity. */ - LogRecordBuilder setSeverity(Severity severity); - - /** Set the severity text. */ - LogRecordBuilder setSeverityText(String severityText); - - /** Set the name. */ - LogRecordBuilder setName(String name); - - /** Set the body. */ - LogRecordBuilder setBody(Body body); - - /** Set the body string. */ - LogRecordBuilder setBody(String body); - - /** Set the attributes. */ - LogRecordBuilder setAttributes(Attributes attributes); - - /** Build a {@link LogRecord} instance from the configured properties. */ - LogRecord build(); -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java deleted file mode 100644 index ccbef88c850..00000000000 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/data/SdkLogData.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.logs.data; - -import com.google.auto.value.AutoValue; -import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; -import io.opentelemetry.sdk.resources.Resource; -import javax.annotation.concurrent.Immutable; - -/** SDK implementation of {@link LogData}. */ -@AutoValue -@Immutable -abstract class SdkLogData implements LogData { - - SdkLogData() {} - - static SdkLogData create( - Resource resource, - InstrumentationLibraryInfo instrumentationLibraryInfo, - LogRecord logRecord) { - return new AutoValue_SdkLogData( - logRecord.getEpochNanos(), - logRecord.getTraceId(), - logRecord.getSpanId(), - logRecord.getFlags(), - logRecord.getSeverity(), - logRecord.getSeverityText(), - logRecord.getName(), - logRecord.getBody(), - logRecord.getAttributes(), - resource, - instrumentationLibraryInfo); - } -} diff --git a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogProcessor.java b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogProcessor.java index 8045f41cdc3..8e68af8ba8d 100644 --- a/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogProcessor.java +++ b/sdk/logs/src/main/java/io/opentelemetry/sdk/logs/export/SimpleLogProcessor.java @@ -10,7 +10,6 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.logs.LogProcessor; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import java.util.Collections; import java.util.List; import java.util.Set; @@ -20,7 +19,7 @@ import java.util.logging.Logger; /** - * An implementation of the {@link LogProcessor} that passes {@link LogRecord }it directly to the + * An implementation of the {@link LogProcessor} that passes {@link LogData} directly to the * configured exporter. * *

This processor will cause all logs to be exported directly as they finish, meaning each export diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java index a6090990f48..ba217108527 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogEmitterTest.java @@ -6,22 +6,29 @@ package io.opentelemetry.sdk.logs; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.Body; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.resources.Resource; import java.time.Instant; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; @ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) class SdkLogEmitterTest { private static final String INSTRUMENTATION_LIBRARY_NAME = SdkLogEmitter.class.getName(); @@ -29,14 +36,15 @@ class SdkLogEmitterTest { private static final String SCHEMA_URL = "http://schemaurl"; @Mock private LogProcessor logProcessor; + private SdkLogEmitterProvider sdkLogEmitterProvider; private LogEmitter sdkLogEmitter; @BeforeEach void setup() { + when(logProcessor.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + sdkLogEmitterProvider = SdkLogEmitterProvider.builder().addLogProcessor(logProcessor).build(); sdkLogEmitter = - SdkLogEmitterProvider.builder() - .addLogProcessor(logProcessor) - .build() + sdkLogEmitterProvider .logEmitterBuilder(INSTRUMENTATION_LIBRARY_NAME) .setInstrumentationVersion(INSTRUMENTATION_LIBRARY_VERSION) .setSchemaUrl(SCHEMA_URL) @@ -45,9 +53,9 @@ void setup() { @Test void emit() { - LogRecord logRecord = - LogRecord.builder().setEpoch(Instant.now()).setBody(Body.stringBody("message")).build(); - sdkLogEmitter.emit(logRecord); + long epochMillis = System.currentTimeMillis(); + Body body = Body.stringBody("message"); + sdkLogEmitter.logBuilder().setEpoch(epochMillis, TimeUnit.MILLISECONDS).setBody(body).emit(); ArgumentCaptor captor = ArgumentCaptor.forClass(LogData.class); verify(logProcessor).emit(captor.capture()); @@ -58,7 +66,15 @@ void emit() { .isEqualTo( InstrumentationLibraryInfo.create( INSTRUMENTATION_LIBRARY_NAME, INSTRUMENTATION_LIBRARY_VERSION, SCHEMA_URL)); - assertThat(logData.getEpochNanos()).isEqualTo(logRecord.getEpochNanos()); - assertThat(logData.getBody()).isEqualTo(logRecord.getBody()); + assertThat(logData.getEpochNanos()).isEqualTo(TimeUnit.MILLISECONDS.toNanos(epochMillis)); + assertThat(logData.getBody()).isEqualTo(body); + } + + @Test + void emit_AfterShutdown() { + sdkLogEmitterProvider.shutdown().join(10, TimeUnit.SECONDS); + + sdkLogEmitter.logBuilder().setEpoch(Instant.now()).setBody("message").emit(); + verify(logProcessor, never()).emit(any()); } } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java index 68f47ba9eec..2e0ba4cc91d 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/BatchLogProcessorTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.sdk.logs.export; import static io.opentelemetry.sdk.logs.util.TestUtil.createLogData; -import static io.opentelemetry.sdk.logs.util.TestUtil.createLogRecord; import static org.assertj.core.api.Assertions.fail; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.awaitility.Awaitility.await; @@ -40,7 +39,7 @@ void testBatchSize() { provider.logEmitterBuilder("test").setInstrumentationVersion("0.1a").build(); for (int i = 0; i < 7; i++) { - emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); + emitter.logBuilder().setSeverity(Severity.WARN).setBody("test #" + i).emit(); } // Ensure that more than batch size kicks off a flush await().atMost(Duration.ofSeconds(5)).until(() -> exporter.getRecords().size() > 0); @@ -75,7 +74,7 @@ void testNoBlocking() { long start = System.currentTimeMillis(); int testRecordCount = 700; for (int i = 0; i < testRecordCount; i++) { - emitter.emit(createLogRecord(Severity.WARN, "test #" + i)); + emitter.logBuilder().setSeverity(Severity.WARN).setBody("test #" + i).emit(); } long end = System.currentTimeMillis(); Assertions.assertThat(end - start).isLessThan(250L); diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java index cd28b6ed536..15644382fba 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/export/InMemoryLogExporterTest.java @@ -41,9 +41,9 @@ void tearDown() { @Test void getFinishedLogItems() { - logEmitter.emit(createLogData(DEBUG, "message 1")); - logEmitter.emit(createLogData(DEBUG, "message 2")); - logEmitter.emit(createLogData(DEBUG, "message 3")); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 1").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 2").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 3").emit(); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); @@ -55,9 +55,9 @@ void getFinishedLogItems() { @Test void reset() { - logEmitter.emit(createLogData(DEBUG, "message 1")); - logEmitter.emit(createLogData(DEBUG, "message 2")); - logEmitter.emit(createLogData(DEBUG, "message 3")); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 1").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 2").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 3").emit(); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); assertThat(logItems.size()).isEqualTo(3); @@ -68,9 +68,9 @@ void reset() { @Test void shutdown() { - logEmitter.emit(createLogData(DEBUG, "message 1")); - logEmitter.emit(createLogData(DEBUG, "message 2")); - logEmitter.emit(createLogData(DEBUG, "message 3")); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 1").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 2").emit(); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 3").emit(); List logItems = exporter.getFinishedLogItems(); assertThat(logItems).isNotNull(); assertThat(logItems.size()).isEqualTo(3); @@ -78,7 +78,7 @@ void shutdown() { exporter.shutdown(); assertThat(exporter.getFinishedLogItems()).isEmpty(); // Cannot add new elements after the shutdown. - logEmitter.emit(createLogData(DEBUG, "message 1")); + logEmitter.logBuilder().setSeverity(DEBUG).setBody("message 1").emit(); assertThat(exporter.getFinishedLogItems()).isEmpty(); } diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java index 1bb63e85865..194db14f8e1 100644 --- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java +++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/util/TestUtil.java @@ -11,15 +11,16 @@ import io.opentelemetry.api.trace.TraceId; import io.opentelemetry.sdk.common.InstrumentationLibraryInfo; import io.opentelemetry.sdk.logs.data.LogData; -import io.opentelemetry.sdk.logs.data.LogRecord; import io.opentelemetry.sdk.logs.data.Severity; import io.opentelemetry.sdk.resources.Resource; import java.util.concurrent.TimeUnit; public final class TestUtil { - public static LogRecord createLogRecord(Severity severity, String message) { - return LogRecord.builder() + public static LogData createLogData(Severity severity, String message) { + return LogData.builder( + Resource.create(Attributes.builder().put("testKey", "testValue").build()), + InstrumentationLibraryInfo.create("instrumentation", "1")) .setEpoch(System.currentTimeMillis(), TimeUnit.MILLISECONDS) .setTraceId(TraceId.getInvalid()) .setSpanId(SpanId.getInvalid()) @@ -32,12 +33,5 @@ public static LogRecord createLogRecord(Severity severity, String message) { .build(); } - public static LogData createLogData(Severity severity, String message) { - return LogData.create( - Resource.create(Attributes.builder().put("testKey", "testValue").build()), - InstrumentationLibraryInfo.create("instrumentation", "1"), - createLogRecord(severity, message)); - } - private TestUtil() {} }