Let clock be overridden for log creators (#3823)
* Allow the clock to be overridden so that we aren't directly coupled to System.currentTimeMillis() * move clock usage to dedicated test * move clock foolery to its own dedicated test method * address some code review comments and checkstyle violations * cleanup: remove builder() from LogData interface and remove clock methods from LogBuilder interface. * make inner impl static * make method package private * factor builder out to top-level class and remove creation work from constructor * fix up tests for SdkLogEmitter and SdkLogBuilder * backfill coverage for second shutdown * remove mock
This commit is contained in:
parent
4b7e50928f
commit
7b86d53427
|
@ -14,6 +14,7 @@ import io.github.netmikey.logunit.api.LogCapturer;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
@ -31,7 +32,7 @@ class OtlpJsonLoggingLogExporterTest {
|
|||
Resource.create(Attributes.builder().put("key", "value").build());
|
||||
|
||||
private static final LogData LOG1 =
|
||||
LogData.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
LogDataBuilder.create(RESOURCE, InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setName("testLog1")
|
||||
.setBody("body1")
|
||||
.setFlags(0)
|
||||
|
@ -44,7 +45,7 @@ class OtlpJsonLoggingLogExporterTest {
|
|||
.build();
|
||||
|
||||
private static final LogData LOG2 =
|
||||
LogData.builder(RESOURCE, InstrumentationLibraryInfo.create("instrumentation2", "2"))
|
||||
LogDataBuilder.create(RESOURCE, InstrumentationLibraryInfo.create("instrumentation2", "2"))
|
||||
.setName("testLog2")
|
||||
.setBody("body2")
|
||||
.setFlags(0)
|
||||
|
|
|
@ -17,6 +17,7 @@ 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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -50,7 +51,8 @@ class SystemOutLogExporterTest {
|
|||
}
|
||||
|
||||
private static LogData sampleLog(long timestamp) {
|
||||
return LogData.builder(Resource.empty(), InstrumentationLibraryInfo.create("logTest", "1.0"))
|
||||
return LogDataBuilder.create(
|
||||
Resource.empty(), InstrumentationLibraryInfo.create("logTest", "1.0"))
|
||||
.setAttributes(Attributes.of(stringKey("cheese"), "cheddar", longKey("amount"), 1L))
|
||||
.setBody(Body.stringBody("message"))
|
||||
.setSeverity(Severity.ERROR3)
|
||||
|
|
|
@ -31,6 +31,7 @@ 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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.trace.IdGenerator;
|
||||
|
@ -318,7 +319,7 @@ class OtlpHttpLogExporterTest {
|
|||
}
|
||||
|
||||
private static LogData generateFakeLog() {
|
||||
return LogData.builder(
|
||||
return LogDataBuilder.create(
|
||||
Resource.getDefault(),
|
||||
InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"))
|
||||
.setName("log-name")
|
||||
|
|
|
@ -24,7 +24,7 @@ import io.opentelemetry.proto.logs.v1.InstrumentationLibraryLogs;
|
|||
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.LogData;
|
||||
import io.opentelemetry.sdk.logs.data.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -51,7 +51,7 @@ class LogsRequestMarshalerTest {
|
|||
ResourceLogsMarshaler[] resourceLogsMarshalers =
|
||||
ResourceLogsMarshaler.create(
|
||||
Collections.singleton(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.builder().put("one", 1).setSchemaUrl("http://url").build(),
|
||||
InstrumentationLibraryInfo.create("testLib", "1.0", "http://url"))
|
||||
.setName(NAME)
|
||||
|
@ -84,7 +84,7 @@ class LogsRequestMarshalerTest {
|
|||
parse(
|
||||
LogRecord.getDefaultInstance(),
|
||||
LogMarshaler.create(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setName(NAME)
|
||||
|
@ -117,7 +117,7 @@ class LogsRequestMarshalerTest {
|
|||
parse(
|
||||
LogRecord.getDefaultInstance(),
|
||||
LogMarshaler.create(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setBody(BODY)
|
||||
|
|
|
@ -33,6 +33,7 @@ import io.opentelemetry.proto.logs.v1.ResourceLogs;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -368,7 +369,7 @@ class OtlpGrpcLogsExporterTest {
|
|||
}
|
||||
|
||||
private static LogData generateFakeLog() {
|
||||
return LogData.builder(
|
||||
return LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(Instant.now())
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -39,7 +40,7 @@ class ExportTest {
|
|||
|
||||
private static final List<LogData> LOGS =
|
||||
Collections.singletonList(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(Instant.now())
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -39,7 +40,7 @@ class ExportTest {
|
|||
|
||||
private static final List<LogData> LOGS =
|
||||
Collections.singletonList(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(Instant.now())
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -39,7 +40,7 @@ class ExportTest {
|
|||
|
||||
private static final List<LogData> LOGS =
|
||||
Collections.singletonList(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(Instant.now())
|
||||
|
|
|
@ -20,6 +20,7 @@ import io.opentelemetry.exporter.otlp.internal.grpc.OkHttpGrpcExporterBuilder;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.net.InetAddress;
|
||||
|
@ -40,7 +41,7 @@ class OkHttpOnlyExportTest {
|
|||
|
||||
private static final List<LogData> LOGS =
|
||||
Collections.singletonList(
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(Instant.now())
|
||||
|
|
|
@ -53,6 +53,7 @@ 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.LogData;
|
||||
import io.opentelemetry.sdk.logs.data.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
|
@ -375,7 +376,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
|
||||
private static void testLogExporter(LogExporter logExporter) {
|
||||
LogData logData =
|
||||
LogData.builder(
|
||||
LogDataBuilder.create(
|
||||
RESOURCE,
|
||||
InstrumentationLibraryInfo.create(
|
||||
OtlpExporterIntegrationTest.class.getName(), null))
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package io.opentelemetry.sdk.logs;
|
||||
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.List;
|
||||
|
@ -18,11 +19,13 @@ final class LogEmitterSharedState {
|
|||
private final Object lock = new Object();
|
||||
private final Resource resource;
|
||||
private final LogProcessor logProcessor;
|
||||
private final Clock clock;
|
||||
@Nullable private volatile CompletableResultCode shutdownResult = null;
|
||||
|
||||
LogEmitterSharedState(Resource resource, List<LogProcessor> logProcessors) {
|
||||
LogEmitterSharedState(Resource resource, List<LogProcessor> logProcessors, Clock clock) {
|
||||
this.resource = resource;
|
||||
this.logProcessor = LogProcessor.composite(logProcessors);
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
Resource getResource() {
|
||||
|
@ -33,6 +36,10 @@ final class LogEmitterSharedState {
|
|||
return logProcessor;
|
||||
}
|
||||
|
||||
Clock getClock() {
|
||||
return clock;
|
||||
}
|
||||
|
||||
boolean hasBeenShutdown() {
|
||||
return shutdownResult != null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** {@link SdkLogBuilder} is the SDK implementation of {@link LogBuilder}. */
|
||||
final class SdkLogBuilder implements LogBuilder {
|
||||
|
||||
private final LogDataBuilder logDataBuilder;
|
||||
private final LogEmitterSharedState logEmitterSharedState;
|
||||
|
||||
SdkLogBuilder(LogEmitterSharedState logEmitterSharedState, LogDataBuilder logDataBuilder) {
|
||||
this.logEmitterSharedState = logEmitterSharedState;
|
||||
this.logDataBuilder = logDataBuilder;
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
|
@ -5,14 +5,8 @@
|
|||
|
||||
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.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 {
|
||||
|
@ -29,95 +23,16 @@ final class SdkLogEmitter implements LogEmitter {
|
|||
|
||||
@Override
|
||||
public LogBuilder logBuilder() {
|
||||
return new SdkLogBuilder();
|
||||
LogDataBuilder logDataBuilder =
|
||||
LogDataBuilder.create(
|
||||
logEmitterSharedState.getResource(),
|
||||
instrumentationLibraryInfo,
|
||||
logEmitterSharedState.getClock());
|
||||
return new SdkLogBuilder(logEmitterSharedState, logDataBuilder);
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package io.opentelemetry.sdk.logs;
|
||||
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.internal.ComponentRegistry;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
@ -32,8 +33,8 @@ public final class SdkLogEmitterProvider implements Closeable {
|
|||
return new SdkLogEmitterProviderBuilder();
|
||||
}
|
||||
|
||||
SdkLogEmitterProvider(Resource resource, List<LogProcessor> processors) {
|
||||
this.sharedState = new LogEmitterSharedState(resource, processors);
|
||||
SdkLogEmitterProvider(Resource resource, List<LogProcessor> processors, Clock clock) {
|
||||
this.sharedState = new LogEmitterSharedState(resource, processors, clock);
|
||||
this.logEmitterComponentRegistry =
|
||||
new ComponentRegistry<>(
|
||||
instrumentationLibraryInfo ->
|
||||
|
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.sdk.logs;
|
|||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.logs.data.LogData;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.ArrayList;
|
||||
|
@ -17,6 +18,7 @@ public final class SdkLogEmitterProviderBuilder {
|
|||
|
||||
private final List<LogProcessor> logProcessors = new ArrayList<>();
|
||||
private Resource resource = Resource.getDefault();
|
||||
private Clock clock = Clock.getDefault();
|
||||
|
||||
SdkLogEmitterProviderBuilder() {}
|
||||
|
||||
|
@ -46,12 +48,28 @@ public final class SdkLogEmitterProviderBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a {@link Clock}. The {@link Clock} may be used to determine "now" in the event that the
|
||||
* epoch millis are not set directly.
|
||||
*
|
||||
* <p>The {@code clock} must be thread-safe and return immediately (no remote calls, as contention
|
||||
* free as possible).
|
||||
*
|
||||
* @param clock The clock to use for all temporal needs.
|
||||
* @return this
|
||||
*/
|
||||
public SdkLogEmitterProviderBuilder setClock(Clock clock) {
|
||||
requireNonNull(clock, "clock");
|
||||
this.clock = clock;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link SdkLogEmitterProvider} instance.
|
||||
*
|
||||
* @return an instance configured with the provided options
|
||||
*/
|
||||
public SdkLogEmitterProvider build() {
|
||||
return new SdkLogEmitterProvider(resource, logProcessors);
|
||||
return new SdkLogEmitterProvider(resource, logProcessors, clock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,6 @@ import javax.annotation.concurrent.Immutable;
|
|||
@Immutable
|
||||
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. */
|
||||
Resource getResource();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.sdk.logs.data;
|
|||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.time.Instant;
|
||||
|
@ -27,11 +28,26 @@ public final class LogDataBuilder {
|
|||
@Nullable private String severityText;
|
||||
@Nullable private String name;
|
||||
private Body body = Body.stringBody("");
|
||||
private final Clock clock;
|
||||
private final AttributesBuilder attributeBuilder = Attributes.builder();
|
||||
|
||||
LogDataBuilder(Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) {
|
||||
private LogDataBuilder(
|
||||
Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo, Clock clock) {
|
||||
this.resource = resource;
|
||||
this.instrumentationLibraryInfo = instrumentationLibraryInfo;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/** Returns a new {@link LogDataBuilder} with the default clock. */
|
||||
public static LogDataBuilder create(
|
||||
Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo) {
|
||||
return create(resource, instrumentationLibraryInfo, Clock.getDefault());
|
||||
}
|
||||
|
||||
/** Returns a new {@link LogDataBuilder}. */
|
||||
public static LogDataBuilder create(
|
||||
Resource resource, InstrumentationLibraryInfo instrumentationLibraryInfo, Clock clock) {
|
||||
return new LogDataBuilder(resource, instrumentationLibraryInfo, clock);
|
||||
}
|
||||
|
||||
/** Set the epoch timestamp using the timestamp and unit. */
|
||||
|
@ -102,7 +118,7 @@ public final class LogDataBuilder {
|
|||
/** Build a {@link LogData} instance from the configured properties. */
|
||||
public LogData build() {
|
||||
if (epochNanos == 0) {
|
||||
epochNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
|
||||
epochNanos = clock.now();
|
||||
}
|
||||
return LogDataImpl.create(
|
||||
resource,
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.logs;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LogEmitterSharedStateTest {
|
||||
|
||||
@Test
|
||||
void shutdown() {
|
||||
LogProcessor logProcessor = mock(LogProcessor.class);
|
||||
CompletableResultCode code = new CompletableResultCode();
|
||||
when(logProcessor.shutdown()).thenReturn(code);
|
||||
List<LogProcessor> processors = Collections.singletonList(logProcessor);
|
||||
LogEmitterSharedState state = new LogEmitterSharedState(null, processors, null);
|
||||
state.shutdown();
|
||||
state.shutdown();
|
||||
verify(logProcessor, times(1)).shutdown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.logs;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.logs.data.Body;
|
||||
import io.opentelemetry.sdk.logs.data.LogData;
|
||||
import io.opentelemetry.sdk.logs.data.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SdkLogBuilderTest {
|
||||
|
||||
@Test
|
||||
void buildAndEmit() {
|
||||
Instant now = Instant.now();
|
||||
String name = "skippy";
|
||||
String bodyStr = "body";
|
||||
String spanId = "abc123";
|
||||
String traceId = "99321";
|
||||
int flags = 21;
|
||||
String sevText = "sevText";
|
||||
Severity severity = Severity.DEBUG3;
|
||||
Attributes attrs = Attributes.empty();
|
||||
AtomicReference<LogData> seenLog = new AtomicReference<>();
|
||||
LogProcessor logProcessor = seenLog::set;
|
||||
|
||||
LogEmitterSharedState state = mock(LogEmitterSharedState.class);
|
||||
LogDataBuilder delegate = mock(LogDataBuilder.class);
|
||||
LogData logData = mock(LogData.class);
|
||||
Body body = mock(Body.class);
|
||||
|
||||
when(state.getLogProcessor()).thenReturn(logProcessor);
|
||||
when(delegate.build()).thenReturn(logData);
|
||||
|
||||
SdkLogBuilder builder = new SdkLogBuilder(state, delegate);
|
||||
builder.setBody(body);
|
||||
verify(delegate).setBody(body);
|
||||
builder.setBody(bodyStr);
|
||||
verify(delegate).setBody(bodyStr);
|
||||
builder.setEpoch(123, TimeUnit.SECONDS);
|
||||
verify(delegate).setEpoch(123, TimeUnit.SECONDS);
|
||||
builder.setEpoch(now);
|
||||
verify(delegate).setEpoch(now);
|
||||
builder.setAttributes(attrs);
|
||||
verify(delegate).setAttributes(attrs);
|
||||
builder.setFlags(flags);
|
||||
verify(delegate).setFlags(flags);
|
||||
builder.setName(name);
|
||||
verify(delegate).setName(name);
|
||||
builder.setSeverity(severity);
|
||||
verify(delegate).setSeverity(severity);
|
||||
builder.setSeverityText(sevText);
|
||||
verify(delegate).setSeverityText(sevText);
|
||||
builder.setSpanId(spanId);
|
||||
verify(delegate).setSpanId(spanId);
|
||||
builder.setTraceId(traceId);
|
||||
verify(delegate).setTraceId(traceId);
|
||||
builder.emit();
|
||||
assertThat(seenLog.get()).isSameAs(logData);
|
||||
}
|
||||
|
||||
@Test
|
||||
void emitAfterShutdown() {
|
||||
LogEmitterSharedState state = mock(LogEmitterSharedState.class);
|
||||
LogDataBuilder delegate = mock(LogDataBuilder.class);
|
||||
|
||||
when(state.hasBeenShutdown()).thenReturn(true);
|
||||
|
||||
SdkLogBuilder builder = new SdkLogBuilder(state, delegate);
|
||||
builder.emit();
|
||||
verify(state, never()).getLogProcessor();
|
||||
verifyNoInteractions(delegate);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.logs;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.logs.data.LogData;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SdkLogEmitterProviderBuilderTest {
|
||||
|
||||
@Test
|
||||
void canSetClock() {
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.now()).thenReturn(13L);
|
||||
|
||||
List<LogData> seenLogs = new LinkedList<>();
|
||||
|
||||
LogProcessor processor = seenLogs::add;
|
||||
|
||||
SdkLogEmitterProviderBuilder builder =
|
||||
new SdkLogEmitterProviderBuilder()
|
||||
.setResource(Resource.getDefault())
|
||||
.addLogProcessor(processor)
|
||||
.setClock(clock);
|
||||
|
||||
SdkLogEmitterProvider provider = builder.build();
|
||||
provider.logEmitterBuilder("inst").build().logBuilder().emit();
|
||||
assertThat(seenLogs.size()).isEqualTo(1);
|
||||
assertThat(seenLogs.get(0).getEpochNanos()).isEqualTo(13L);
|
||||
}
|
||||
}
|
|
@ -7,14 +7,20 @@ package io.opentelemetry.sdk.logs;
|
|||
|
||||
import static org.assertj.core.api.Assertions.as;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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.Clock;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
|
||||
import io.opentelemetry.sdk.logs.data.LogData;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.LinkedList;
|
||||
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;
|
||||
|
@ -179,4 +185,18 @@ class SdkLogEmitterProviderTest {
|
|||
sdkLogEmitterProvider.close();
|
||||
verify(logProcessor).shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
void canSetClock() {
|
||||
long now = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.now()).thenReturn(now);
|
||||
List<LogData> seenLogs = new LinkedList<>();
|
||||
logProcessor = seenLogs::add;
|
||||
sdkLogEmitterProvider =
|
||||
SdkLogEmitterProvider.builder().setClock(clock).addLogProcessor(logProcessor).build();
|
||||
sdkLogEmitterProvider.logEmitterBuilder(null).build().logBuilder().emit();
|
||||
assertThat(seenLogs.size()).isEqualTo(1);
|
||||
assertThat(seenLogs.get(0).getEpochNanos()).isEqualTo(now);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,75 +6,36 @@
|
|||
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.mock;
|
||||
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.resources.Resource;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
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();
|
||||
private static final String INSTRUMENTATION_LIBRARY_VERSION = "0.0.1";
|
||||
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
|
||||
.logEmitterBuilder(INSTRUMENTATION_LIBRARY_NAME)
|
||||
.setInstrumentationVersion(INSTRUMENTATION_LIBRARY_VERSION)
|
||||
.setSchemaUrl(SCHEMA_URL)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void emit() {
|
||||
long epochMillis = System.currentTimeMillis();
|
||||
Body body = Body.stringBody("message");
|
||||
sdkLogEmitter.logBuilder().setEpoch(epochMillis, TimeUnit.MILLISECONDS).setBody(body).emit();
|
||||
void logBuilder() {
|
||||
Instant now = Instant.now();
|
||||
LogEmitterSharedState state = mock(LogEmitterSharedState.class);
|
||||
InstrumentationLibraryInfo info = InstrumentationLibraryInfo.create("foo", "bar");
|
||||
AtomicReference<LogData> seenLog = new AtomicReference<>();
|
||||
LogProcessor logProcessor = seenLog::set;
|
||||
|
||||
ArgumentCaptor<LogData> captor = ArgumentCaptor.forClass(LogData.class);
|
||||
verify(logProcessor).emit(captor.capture());
|
||||
when(state.getResource()).thenReturn(Resource.getDefault());
|
||||
when(state.getLogProcessor()).thenReturn(logProcessor);
|
||||
|
||||
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(TimeUnit.MILLISECONDS.toNanos(epochMillis));
|
||||
assertThat(logData.getBody()).isEqualTo(body);
|
||||
}
|
||||
SdkLogEmitter emitter = new SdkLogEmitter(state, info);
|
||||
LogBuilder logBuilder = emitter.logBuilder();
|
||||
logBuilder.setEpoch(now);
|
||||
logBuilder.setBody("foo");
|
||||
|
||||
@Test
|
||||
void emit_AfterShutdown() {
|
||||
sdkLogEmitterProvider.shutdown().join(10, TimeUnit.SECONDS);
|
||||
|
||||
sdkLogEmitter.logBuilder().setEpoch(Instant.now()).setBody("message").emit();
|
||||
verify(logProcessor, never()).emit(any());
|
||||
// Have to test through the builder
|
||||
logBuilder.emit();
|
||||
assertThat(seenLog.get().getBody().asString()).isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.logs.data;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.sdk.common.Clock;
|
||||
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LogDataBuilderTest {
|
||||
|
||||
@Test
|
||||
void canSetClock() {
|
||||
Resource resource = Resource.getDefault();
|
||||
InstrumentationLibraryInfo libraryInfo = InstrumentationLibraryInfo.empty();
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.now()).thenReturn(12L);
|
||||
LogDataBuilder builder = LogDataBuilder.create(resource, libraryInfo, clock);
|
||||
|
||||
LogData result = builder.build();
|
||||
assertEquals(12L, result.getEpochNanos());
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import io.opentelemetry.api.trace.TraceFlags;
|
|||
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.LogDataBuilder;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -18,7 +19,7 @@ import java.util.concurrent.TimeUnit;
|
|||
public final class TestUtil {
|
||||
|
||||
public static LogData createLogData(Severity severity, String message) {
|
||||
return LogData.builder(
|
||||
return LogDataBuilder.create(
|
||||
Resource.create(Attributes.builder().put("testKey", "testValue").build()),
|
||||
InstrumentationLibraryInfo.create("instrumentation", "1"))
|
||||
.setEpoch(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mock-maker-inline
|
Loading…
Reference in New Issue