Logs customizer (#4148)
This commit is contained in:
parent
5d2c59f839
commit
eb92539f94
|
@ -1,6 +1,8 @@
|
|||
Comparing source compatibility of against
|
||||
***! MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addLogEmitterProviderCustomizer(java.util.function.BiFunction)
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addLogExporterCustomizer(java.util.function.BiFunction)
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addMeterProviderCustomizer(java.util.function.BiFunction)
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addMetricExporterCustomizer(java.util.function.BiFunction)
|
||||
+++! NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addTracerProviderCustomizer(java.util.function.BiFunction)
|
||||
|
|
|
@ -12,4 +12,7 @@ dependencies {
|
|||
// implementation dependency to require users to add the artifact directly to their build to use
|
||||
// SdkMeterProviderBuilder.
|
||||
implementation(project(":sdk:metrics"))
|
||||
// implementation dependency to require users to add the artifact directly to their build to use
|
||||
// SdkLogEmitterProviderBuilder.
|
||||
implementation(project(":sdk:logs"))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
package io.opentelemetry.sdk.autoconfigure.spi;
|
||||
|
||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricExporter;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
@ -106,4 +108,28 @@ public interface AutoConfigurationCustomizer {
|
|||
exporterCustomizer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke the with the {@link SdkLogEmitterProviderBuilder} to allow
|
||||
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
|
||||
*
|
||||
* <p>Multiple calls will execute the customizers in order.
|
||||
*/
|
||||
default AutoConfigurationCustomizer addLogEmitterProviderCustomizer(
|
||||
BiFunction<SdkLogEmitterProviderBuilder, ConfigProperties, SdkLogEmitterProviderBuilder>
|
||||
meterProviderCustomizer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke with the default autoconfigured {@link LogExporter} to
|
||||
* allow customization. The return value of the {@link BiFunction} will replace the passed-in
|
||||
* argument.
|
||||
*
|
||||
* <p>Multiple calls will execute the customizers in order.
|
||||
*/
|
||||
default AutoConfigurationCustomizer addLogExporterCustomizer(
|
||||
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter> exporterCustomizer) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvide
|
|||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricExporter;
|
||||
|
@ -64,6 +66,11 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
private BiFunction<? super MetricExporter, ConfigProperties, ? extends MetricExporter>
|
||||
metricExporterCustomizer = (a, unused) -> a;
|
||||
|
||||
private BiFunction<SdkLogEmitterProviderBuilder, ConfigProperties, SdkLogEmitterProviderBuilder>
|
||||
logEmitterProviderCustomizer = (a, unused) -> a;
|
||||
private BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
|
||||
logExporterCustomizer = (a, unused) -> a;
|
||||
|
||||
private BiFunction<? super Resource, ConfigProperties, ? extends Resource> resourceCustomizer =
|
||||
(a, unused) -> a;
|
||||
|
||||
|
@ -216,6 +223,38 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke the with the {@link SdkLogEmitterProviderBuilder} to allow
|
||||
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
|
||||
*
|
||||
* <p>Multiple calls will execute the customizers in order.
|
||||
*/
|
||||
@Override
|
||||
public AutoConfiguredOpenTelemetrySdkBuilder addLogEmitterProviderCustomizer(
|
||||
BiFunction<SdkLogEmitterProviderBuilder, ConfigProperties, SdkLogEmitterProviderBuilder>
|
||||
logEmitterProviderCustomizer) {
|
||||
requireNonNull(logEmitterProviderCustomizer, "logEmitterProviderCustomizer");
|
||||
this.logEmitterProviderCustomizer =
|
||||
mergeCustomizer(this.logEmitterProviderCustomizer, logEmitterProviderCustomizer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link BiFunction} to invoke with the default autoconfigured {@link LogExporter} to
|
||||
* allow customization. The return value of the {@link BiFunction} will replace the passed-in
|
||||
* argument.
|
||||
*
|
||||
* <p>Multiple calls will execute the customizers in order.
|
||||
*/
|
||||
@Override
|
||||
public AutoConfiguredOpenTelemetrySdkBuilder addLogExporterCustomizer(
|
||||
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
|
||||
logExporterCustomizer) {
|
||||
requireNonNull(logExporterCustomizer, "logExporterCustomizer");
|
||||
this.logExporterCustomizer = mergeCustomizer(this.logExporterCustomizer, logExporterCustomizer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the registration of a shutdown hook to shut down the SDK when appropriate. By default,
|
||||
* the shutdown hook is registered.
|
||||
|
@ -288,9 +327,13 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
|
|||
tracerProviderBuilder = tracerProviderCustomizer.apply(tracerProviderBuilder, config);
|
||||
SdkTracerProvider tracerProvider = tracerProviderBuilder.build();
|
||||
|
||||
SdkLogEmitterProvider logEmitterProvider =
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
resource, config, meterProvider);
|
||||
SdkLogEmitterProviderBuilder logEmitterProviderBuilder = SdkLogEmitterProvider.builder();
|
||||
logEmitterProviderBuilder.setResource(resource);
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
logEmitterProviderBuilder, config, meterProvider, logExporterCustomizer);
|
||||
logEmitterProviderBuilder =
|
||||
logEmitterProviderCustomizer.apply(logEmitterProviderBuilder, config);
|
||||
SdkLogEmitterProvider logEmitterProvider = logEmitterProviderBuilder.build();
|
||||
|
||||
if (registerShutdownHook) {
|
||||
Runtime.getRuntime()
|
||||
|
|
|
@ -10,28 +10,29 @@ import static io.opentelemetry.sdk.autoconfigure.LogExporterConfiguration.config
|
|||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.logs.LogProcessor;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
|
||||
import io.opentelemetry.sdk.logs.export.BatchLogProcessor;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.logs.export.SimpleLogProcessor;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
final class LogEmitterProviderConfiguration {
|
||||
|
||||
static SdkLogEmitterProvider configureLogEmitterProvider(
|
||||
Resource resource, ConfigProperties config, MeterProvider meterProvider) {
|
||||
SdkLogEmitterProviderBuilder builder = SdkLogEmitterProvider.builder().setResource(resource);
|
||||
static void configureLogEmitterProvider(
|
||||
SdkLogEmitterProviderBuilder logEmitterProviderBuilder,
|
||||
ConfigProperties config,
|
||||
MeterProvider meterProvider,
|
||||
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
|
||||
logExporterCustomizer) {
|
||||
Map<String, LogExporter> exportersByName =
|
||||
configureLogExporters(config, meterProvider, logExporterCustomizer);
|
||||
|
||||
Map<String, LogExporter> exportersByName = configureLogExporters(config, meterProvider);
|
||||
|
||||
configureLogProcessors(exportersByName, meterProvider).forEach(builder::addLogProcessor);
|
||||
|
||||
return builder.build();
|
||||
configureLogProcessors(exportersByName, meterProvider)
|
||||
.forEach(logEmitterProviderBuilder::addLogProcessor);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class LogExporterConfiguration {
|
||||
|
@ -31,7 +32,10 @@ class LogExporterConfiguration {
|
|||
|
||||
// Visible for test
|
||||
static Map<String, LogExporter> configureLogExporters(
|
||||
ConfigProperties config, MeterProvider meterProvider) {
|
||||
ConfigProperties config,
|
||||
MeterProvider meterProvider,
|
||||
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
|
||||
logExporterCustomizer) {
|
||||
Set<String> exporterNames = DefaultConfigProperties.getSet(config, "otel.logs.exporter");
|
||||
|
||||
// Default to no exporter
|
||||
|
@ -51,7 +55,8 @@ class LogExporterConfiguration {
|
|||
for (String name : exporterNames) {
|
||||
LogExporter logExporter = configureExporter(name, config, meterProvider);
|
||||
if (logExporter != null) {
|
||||
exportersByName.put(name, logExporter);
|
||||
LogExporter customizedLogExporter = logExporterCustomizer.apply(logExporter, config);
|
||||
exportersByName.put(name, customizedLogExporter);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ import io.opentelemetry.context.propagation.TextMapGetter;
|
|||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.logs.LogProcessor;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricReader;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricReaderFactory;
|
||||
|
@ -61,6 +63,7 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
@Mock private SpanExporter spanExporter2;
|
||||
@Mock private MetricReaderFactory metricReaderFactory;
|
||||
@Mock private MetricReader metricReader;
|
||||
@Mock private LogProcessor logProcessor;
|
||||
|
||||
private AutoConfiguredOpenTelemetrySdkBuilder builder;
|
||||
|
||||
|
@ -229,6 +232,26 @@ class AutoConfiguredOpenTelemetrySdkTest {
|
|||
|
||||
// TODO: add test for addMetricExporterCustomizer once OTLP export is enabled by default
|
||||
|
||||
@Test
|
||||
void builder_addLogEmitterProviderCustomizer() {
|
||||
Mockito.lenient().when(logProcessor.shutdown()).thenReturn(CompletableResultCode.ofSuccess());
|
||||
when(logProcessor.forceFlush()).thenReturn(CompletableResultCode.ofSuccess());
|
||||
|
||||
SdkLogEmitterProvider sdkLogEmitterProvider =
|
||||
builder
|
||||
.addLogEmitterProviderCustomizer(
|
||||
(logEmitterProviderBuilder, configProperties) ->
|
||||
logEmitterProviderBuilder.addLogProcessor(logProcessor))
|
||||
.build()
|
||||
.getOpenTelemetrySdk()
|
||||
.getSdkLogEmitterProvider();
|
||||
sdkLogEmitterProvider.forceFlush().join(10, TimeUnit.SECONDS);
|
||||
|
||||
verify(logProcessor).forceFlush();
|
||||
}
|
||||
|
||||
// TODO: add test for addLogExporterCustomizer once OTLP export is enabled by default
|
||||
|
||||
@Test
|
||||
void builder_setResultAsGlobalFalse() {
|
||||
GlobalOpenTelemetry.set(OpenTelemetry.noop());
|
||||
|
|
|
@ -7,11 +7,10 @@ package io.opentelemetry.sdk.autoconfigure;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.sdk.logs.LogProcessor;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -22,22 +21,24 @@ class LogEmitterProviderConfigurationTest {
|
|||
void configureLogEmitterProvider() {
|
||||
Map<String, String> properties = Collections.singletonMap("otel.logs.exporter", "none");
|
||||
|
||||
Resource resource = Resource.create(Attributes.builder().put("cat", "meow").build());
|
||||
// We don't have any exporters on classpath for this test so check no-op case. Exporter cases
|
||||
// are verified in other test sets like testFullConfig.
|
||||
SdkLogEmitterProvider logEmitterProvider =
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
resource, DefaultConfigProperties.createForTest(properties), MeterProvider.noop());
|
||||
SdkLogEmitterProviderBuilder builder = SdkLogEmitterProvider.builder();
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
builder,
|
||||
DefaultConfigProperties.createForTest(properties),
|
||||
MeterProvider.noop(),
|
||||
(a, unused) -> a);
|
||||
SdkLogEmitterProvider logEmitterProvider = builder.build();
|
||||
|
||||
try {
|
||||
assertThat(logEmitterProvider)
|
||||
.extracting("sharedState")
|
||||
.satisfies(
|
||||
sharedState -> {
|
||||
assertThat(sharedState).extracting("resource").isEqualTo(resource);
|
||||
assertThat(sharedState)
|
||||
.extracting("logProcessor")
|
||||
.isEqualTo(LogProcessor.composite());
|
||||
});
|
||||
sharedState ->
|
||||
assertThat(sharedState)
|
||||
.extracting("logProcessor")
|
||||
.isEqualTo(LogProcessor.composite()));
|
||||
} finally {
|
||||
logEmitterProvider.shutdown();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ class LogExporterConfigurationTest {
|
|||
DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "otlp,otlp"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> LogExporterConfiguration.configureLogExporters(config, MeterProvider.noop()))
|
||||
() ->
|
||||
LogExporterConfiguration.configureLogExporters(
|
||||
config, MeterProvider.noop(), (a, unused) -> a))
|
||||
.isInstanceOf(ConfigurationException.class)
|
||||
.hasMessageContaining("otel.logs.exporter contains duplicates: [otlp]");
|
||||
}
|
||||
|
@ -32,7 +34,9 @@ class LogExporterConfigurationTest {
|
|||
DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "foo"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> LogExporterConfiguration.configureLogExporters(config, MeterProvider.noop()))
|
||||
() ->
|
||||
LogExporterConfiguration.configureLogExporters(
|
||||
config, MeterProvider.noop(), (a, unused) -> a))
|
||||
.isInstanceOf(ConfigurationException.class)
|
||||
.hasMessageContaining("Unrecognized value for otel.logs.exporter: foo");
|
||||
}
|
||||
|
@ -43,7 +47,9 @@ class LogExporterConfigurationTest {
|
|||
DefaultConfigProperties.createForTest(ImmutableMap.of("otel.logs.exporter", "otlp,none"));
|
||||
|
||||
assertThatThrownBy(
|
||||
() -> LogExporterConfiguration.configureLogExporters(config, MeterProvider.noop()))
|
||||
() ->
|
||||
LogExporterConfiguration.configureLogExporters(
|
||||
config, MeterProvider.noop(), (a, unused) -> a))
|
||||
.isInstanceOf(ConfigurationException.class)
|
||||
.hasMessageContaining("otel.logs.exporter contains none along with other exporters");
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ import io.opentelemetry.extension.aws.AwsXrayPropagator;
|
|||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||
import io.opentelemetry.extension.trace.propagation.JaegerPropagator;
|
||||
import io.opentelemetry.extension.trace.propagation.OtTracePropagator;
|
||||
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest;
|
||||
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
|
||||
import io.opentelemetry.proto.collector.logs.v1.LogsServiceGrpc;
|
||||
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
|
||||
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse;
|
||||
import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc;
|
||||
|
@ -31,9 +34,13 @@ import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
|||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
import io.opentelemetry.proto.common.v1.AnyValue;
|
||||
import io.opentelemetry.proto.common.v1.KeyValue;
|
||||
import io.opentelemetry.proto.logs.v1.LogRecord;
|
||||
import io.opentelemetry.proto.metrics.v1.InstrumentationLibraryMetrics;
|
||||
import io.opentelemetry.proto.metrics.v1.Metric;
|
||||
import io.opentelemetry.proto.metrics.v1.ResourceMetrics;
|
||||
import io.opentelemetry.sdk.logs.LogEmitter;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.logs.data.Severity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -50,6 +57,8 @@ class FullConfigTest {
|
|||
new LinkedBlockingDeque<>();
|
||||
private static final BlockingQueue<ExportMetricsServiceRequest> otlpMetricsRequests =
|
||||
new LinkedBlockingDeque<>();
|
||||
private static final BlockingQueue<ExportLogsServiceRequest> otlpLogsRequests =
|
||||
new LinkedBlockingDeque<>();
|
||||
|
||||
@RegisterExtension
|
||||
public static final ServerExtension server =
|
||||
|
@ -103,24 +112,56 @@ class FullConfigTest {
|
|||
responseObserver.onCompleted();
|
||||
}
|
||||
})
|
||||
// OTLP logs
|
||||
.addService(
|
||||
new LogsServiceGrpc.LogsServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportLogsServiceRequest request,
|
||||
StreamObserver<ExportLogsServiceResponse> responseObserver) {
|
||||
try {
|
||||
RequestHeaders headers =
|
||||
ServiceRequestContext.current().request().headers();
|
||||
assertThat(headers.get("cat")).isEqualTo("meow");
|
||||
assertThat(headers.get("dog")).isEqualTo("bark");
|
||||
} catch (Throwable t) {
|
||||
responseObserver.onError(t);
|
||||
return;
|
||||
}
|
||||
if (request.getResourceLogsCount() > 0) {
|
||||
otlpLogsRequests.add(request);
|
||||
}
|
||||
responseObserver.onNext(ExportLogsServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
})
|
||||
.useBlockingTaskExecutor(true)
|
||||
.build());
|
||||
sb.decorator(LoggingService.newDecorator());
|
||||
}
|
||||
};
|
||||
|
||||
private SdkLogEmitterProvider logEmitterProvider;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
otlpTraceRequests.clear();
|
||||
otlpMetricsRequests.clear();
|
||||
}
|
||||
otlpLogsRequests.clear();
|
||||
|
||||
@Test
|
||||
void configures() throws Exception {
|
||||
String endpoint = "http://localhost:" + server.httpPort();
|
||||
System.setProperty("otel.exporter.otlp.endpoint", endpoint);
|
||||
System.setProperty("otel.exporter.otlp.timeout", "10000");
|
||||
|
||||
// SdkLogEmitterProvider isn't globally accessible so we initialize here to get a reference
|
||||
logEmitterProvider =
|
||||
AutoConfiguredOpenTelemetrySdk.initialize()
|
||||
.getOpenTelemetrySdk()
|
||||
.getSdkLogEmitterProvider();
|
||||
}
|
||||
|
||||
@Test
|
||||
void configures() throws Exception {
|
||||
Collection<String> fields =
|
||||
GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator().fields();
|
||||
List<String> keys = new ArrayList<>();
|
||||
|
@ -149,6 +190,10 @@ class FullConfigTest {
|
|||
meter.counterBuilder("my-metric").build().add(1);
|
||||
meter.counterBuilder("my-other-metric").build().add(1);
|
||||
|
||||
LogEmitter logEmitter = logEmitterProvider.get("test");
|
||||
logEmitter.logBuilder().setBody("debug log message").setSeverity(Severity.DEBUG).emit();
|
||||
logEmitter.logBuilder().setBody("info log message").setSeverity(Severity.INFO).emit();
|
||||
|
||||
await().untilAsserted(() -> assertThat(otlpTraceRequests).hasSize(1));
|
||||
|
||||
ExportTraceServiceRequest traceRequest = otlpTraceRequests.take();
|
||||
|
@ -222,6 +267,23 @@ class FullConfigTest {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
await().untilAsserted(() -> assertThat(otlpLogsRequests).hasSize(1));
|
||||
ExportLogsServiceRequest logRequest = otlpLogsRequests.take();
|
||||
assertThat(logRequest.getResourceLogs(0).getResource().getAttributesList())
|
||||
.contains(
|
||||
KeyValue.newBuilder()
|
||||
.setKey("service.name")
|
||||
.setValue(AnyValue.newBuilder().setStringValue("test").build())
|
||||
.build(),
|
||||
KeyValue.newBuilder()
|
||||
.setKey("cat")
|
||||
.setValue(AnyValue.newBuilder().setStringValue("meow").build())
|
||||
.build());
|
||||
// MetricExporterCustomizer filters logs not whose level is less than Severity.INFO
|
||||
LogRecord log = logRequest.getResourceLogs(0).getInstrumentationLibraryLogs(0).getLogs(0);
|
||||
assertThat(log.getBody().getStringValue()).isEqualTo("info log message");
|
||||
assertThat(log.getSeverityNumberValue()).isEqualTo(Severity.INFO.getSeverityNumber());
|
||||
}
|
||||
|
||||
private static List<KeyValue> getFirstDataPointLabels(Metric metric) {
|
||||
|
|
|
@ -8,15 +8,14 @@ package io.opentelemetry.sdk.autoconfigure;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.exporter.logging.SystemOutLogExporter;
|
||||
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogExporter;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
|
||||
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
|
||||
import io.opentelemetry.sdk.logs.export.BatchLogProcessor;
|
||||
import io.opentelemetry.sdk.logs.export.LogExporter;
|
||||
import io.opentelemetry.sdk.logs.export.SimpleLogProcessor;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
@ -29,36 +28,38 @@ class LogEmitterProviderConfigurationTest {
|
|||
void configureLogEmitterProvider() {
|
||||
Map<String, String> properties = Collections.singletonMap("otel.logs.exporter", "otlp");
|
||||
|
||||
Resource resource = Resource.create(Attributes.builder().put("cat", "meow").build());
|
||||
SdkLogEmitterProvider logEmitterProvider =
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
resource, DefaultConfigProperties.createForTest(properties), MeterProvider.noop());
|
||||
SdkLogEmitterProviderBuilder builder = SdkLogEmitterProvider.builder();
|
||||
LogEmitterProviderConfiguration.configureLogEmitterProvider(
|
||||
builder,
|
||||
DefaultConfigProperties.createForTest(properties),
|
||||
MeterProvider.noop(),
|
||||
(a, unused) -> a);
|
||||
SdkLogEmitterProvider logEmitterProvider = builder.build();
|
||||
|
||||
try {
|
||||
assertThat(logEmitterProvider)
|
||||
.extracting("sharedState")
|
||||
.satisfies(
|
||||
sharedState -> {
|
||||
assertThat(sharedState).extracting("resource").isEqualTo(resource);
|
||||
assertThat(sharedState)
|
||||
.extracting("logProcessor")
|
||||
.isInstanceOf(BatchLogProcessor.class)
|
||||
.extracting("worker")
|
||||
.satisfies(
|
||||
worker -> {
|
||||
assertThat(worker)
|
||||
.extracting("scheduleDelayNanos")
|
||||
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(200));
|
||||
assertThat(worker)
|
||||
.extracting("exporterTimeoutNanos")
|
||||
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(30000));
|
||||
assertThat(worker).extracting("maxExportBatchSize").isEqualTo(512);
|
||||
assertThat(worker)
|
||||
.extracting("queue")
|
||||
.isInstanceOfSatisfying(
|
||||
ArrayBlockingQueue.class,
|
||||
queue -> assertThat(queue.remainingCapacity()).isEqualTo(2048));
|
||||
});
|
||||
});
|
||||
sharedState ->
|
||||
assertThat(sharedState)
|
||||
.extracting("logProcessor")
|
||||
.isInstanceOf(BatchLogProcessor.class)
|
||||
.extracting("worker")
|
||||
.satisfies(
|
||||
worker -> {
|
||||
assertThat(worker)
|
||||
.extracting("scheduleDelayNanos")
|
||||
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(200));
|
||||
assertThat(worker)
|
||||
.extracting("exporterTimeoutNanos")
|
||||
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(30000));
|
||||
assertThat(worker).extracting("maxExportBatchSize").isEqualTo(512);
|
||||
assertThat(worker)
|
||||
.extracting("queue")
|
||||
.isInstanceOfSatisfying(
|
||||
ArrayBlockingQueue.class,
|
||||
queue -> assertThat(queue.remainingCapacity()).isEqualTo(2048));
|
||||
}));
|
||||
} finally {
|
||||
logEmitterProvider.shutdown();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.autoconfigure;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
|
||||
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.export.LogExporter;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogExporterCustomizer implements AutoConfigurationCustomizerProvider {
|
||||
@Override
|
||||
public void customize(AutoConfigurationCustomizer autoConfiguration) {
|
||||
autoConfiguration.addLogExporterCustomizer(
|
||||
(delegate, config) ->
|
||||
new LogExporter() {
|
||||
@Override
|
||||
public CompletableResultCode export(Collection<LogData> logs) {
|
||||
Collection<LogData> filtered =
|
||||
logs.stream()
|
||||
.filter(
|
||||
log ->
|
||||
log.getSeverity().getSeverityNumber()
|
||||
>= Severity.INFO.getSeverityNumber())
|
||||
.collect(Collectors.toList());
|
||||
return delegate.export(filtered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableResultCode flush() {
|
||||
return delegate.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableResultCode shutdown() {
|
||||
return delegate.shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
io.opentelemetry.sdk.autoconfigure.SpanExporterCustomizer
|
||||
io.opentelemetry.sdk.autoconfigure.MetricExporterCustomizer
|
||||
io.opentelemetry.sdk.autoconfigure.MetricExporterCustomizer
|
||||
io.opentelemetry.sdk.autoconfigure.LogExporterCustomizer
|
Loading…
Reference in New Issue