Skip to content

Commit

Permalink
Improve autoconfiguration capabilities for adding, delaying or droppi…
Browse files Browse the repository at this point in the history
…ng spans (#5986)
  • Loading branch information
JonasKunz authored Dec 7, 2023
1 parent f36cc92 commit c8e1e36
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Comparing source compatibility of against
No changes.
*** 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 addLogRecordProcessorCustomizer(java.util.function.BiFunction<? super io.opentelemetry.sdk.logs.LogRecordProcessor,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.logs.LogRecordProcessor>)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addSpanProcessorCustomizer(java.util.function.BiFunction<? super io.opentelemetry.sdk.trace.SpanProcessor,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.trace.SpanProcessor>)
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Comparing source compatibility of against
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer addLogRecordProcessorCustomizer(java.util.function.BiFunction<? super io.opentelemetry.sdk.logs.LogRecordProcessor,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.logs.LogRecordProcessor>)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder addSpanProcessorCustomizer(java.util.function.BiFunction<? super io.opentelemetry.sdk.trace.SpanProcessor,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.trace.SpanProcessor>)
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
package io.opentelemetry.sdk.autoconfigure.spi;

import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.util.Map;
Expand Down Expand Up @@ -62,6 +64,22 @@ AutoConfigurationCustomizer addSpanExporterCustomizer(
BiFunction<? super SpanExporter, ConfigProperties, ? extends SpanExporter>
exporterCustomizer);

/**
* Adds a {@link BiFunction} to invoke for all autoconfigured {@link
* io.opentelemetry.sdk.trace.SpanProcessor}. The return value of the {@link BiFunction} will
* replace the passed-in argument. In contrast to {@link #addSpanExporterCustomizer(BiFunction)}
* this allows modifications to happen before batching occurs. As a result, it is possible to
* efficiently filter spans, add artificial spans or delay spans for enhancing them with external,
* delayed data.
*
* <p>Multiple calls will execute the customizers in order.
*/
default AutoConfigurationCustomizer addSpanProcessorCustomizer(
BiFunction<? super SpanProcessor, ConfigProperties, ? extends SpanProcessor>
spanProcessorCustomizer) {
return this;
}

/**
* Adds a {@link Supplier} of a map of property names and values to use as defaults for the {@link
* ConfigProperties} used during auto-configuration. The order of precedence of properties is
Expand Down Expand Up @@ -164,4 +182,20 @@ default AutoConfigurationCustomizer addLogRecordExporterCustomizer(
exporterCustomizer) {
return this;
}

/**
* Adds a {@link BiFunction} to invoke for all autoconfigured {@link
* io.opentelemetry.sdk.logs.LogRecordProcessor}s. The return value of the {@link BiFunction} will
* replace the passed-in argument. In contrast to {@link
* #addLogRecordExporterCustomizer(BiFunction)} (BiFunction)} this allows modifications to happen
* before batching occurs. As a result, it is possible to efficiently filter logs, add artificial
* logs or delay logs for enhancing them with external, delayed data.
*
* <p>Multiple calls will execute the customizers in order.
*/
default AutoConfigurationCustomizer addLogRecordProcessorCustomizer(
BiFunction<? super LogRecordProcessor, ConfigProperties, ? extends LogRecordProcessor>
logRecordProcessorCustomizer) {
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
Expand All @@ -30,6 +31,7 @@
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.io.Closeable;
Expand Down Expand Up @@ -71,6 +73,9 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
propagatorCustomizer = (a, unused) -> a;
private BiFunction<? super SpanExporter, ConfigProperties, ? extends SpanExporter>
spanExporterCustomizer = (a, unused) -> a;

private BiFunction<? super SpanProcessor, ConfigProperties, ? extends SpanProcessor>
spanProcessorCustomizer = (a, unused) -> a;
private BiFunction<? super Sampler, ConfigProperties, ? extends Sampler> samplerCustomizer =
(a, unused) -> a;

Expand All @@ -83,6 +88,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
loggerProviderCustomizer = (a, unused) -> a;
private BiFunction<? super LogRecordExporter, ConfigProperties, ? extends LogRecordExporter>
logRecordExporterCustomizer = (a, unused) -> a;
private BiFunction<? super LogRecordProcessor, ConfigProperties, ? extends LogRecordProcessor>
logRecordProcessorCustomizer = (a, unused) -> a;

private BiFunction<? super Resource, ConfigProperties, ? extends Resource> resourceCustomizer =
(a, unused) -> a;
Expand Down Expand Up @@ -191,6 +198,26 @@ public AutoConfiguredOpenTelemetrySdkBuilder addSpanExporterCustomizer(
return this;
}

/**
* Adds a {@link BiFunction} to invoke for all autoconfigured {@link
* io.opentelemetry.sdk.trace.SpanProcessor}. The return value of the {@link BiFunction} will
* replace the passed-in argument. In contrast to {@link #addSpanExporterCustomizer(BiFunction)}
* this allows modifications to happen before batching occurs. As a result, it is possible to
* efficiently filter spans, add artificial spans or delay spans for enhancing them with external,
* delayed data.
*
* <p>Multiple calls will execute the customizers in order.
*/
@Override
public AutoConfiguredOpenTelemetrySdkBuilder addSpanProcessorCustomizer(
BiFunction<? super SpanProcessor, ConfigProperties, ? extends SpanProcessor>
spanProcessorCustomizer) {
requireNonNull(spanProcessorCustomizer, "spanProcessorCustomizer");
this.spanProcessorCustomizer =
mergeCustomizer(this.spanProcessorCustomizer, spanProcessorCustomizer);
return this;
}

/**
* Adds a {@link Supplier} of a map of property names and values to use as defaults for the {@link
* ConfigProperties} used during auto-configuration. The order of precedence of properties is
Expand Down Expand Up @@ -289,6 +316,26 @@ public AutoConfiguredOpenTelemetrySdkBuilder addLogRecordExporterCustomizer(
return this;
}

/**
* Adds a {@link BiFunction} to invoke for all autoconfigured {@link
* io.opentelemetry.sdk.logs.LogRecordProcessor}s. The return value of the {@link BiFunction} will
* replace the passed-in argument. In contrast to {@link
* #addLogRecordExporterCustomizer(BiFunction)} (BiFunction)} this allows modifications to happen
* before batching occurs. As a result, it is possible to efficiently filter logs, add artificial
* logs or delay logs for enhancing them with external, delayed data.
*
* <p>Multiple calls will execute the customizers in order.
*/
@Override
public AutoConfigurationCustomizer addLogRecordProcessorCustomizer(
BiFunction<? super LogRecordProcessor, ConfigProperties, ? extends LogRecordProcessor>
logRecordProcessorCustomizer) {
requireNonNull(logRecordProcessorCustomizer, "logRecordProcessorCustomizer");
this.logRecordProcessorCustomizer =
mergeCustomizer(this.logRecordProcessorCustomizer, logRecordProcessorCustomizer);
return this;
}

/**
* Disable the registration of a shutdown hook to shut down the SDK when appropriate. By default,
* the shutdown hook is registered.
Expand Down Expand Up @@ -372,6 +419,7 @@ public AutoConfiguredOpenTelemetrySdk build() {
spiHelper,
meterProvider,
spanExporterCustomizer,
spanProcessorCustomizer,
samplerCustomizer,
closeables);
tracerProviderBuilder = tracerProviderCustomizer.apply(tracerProviderBuilder, config);
Expand All @@ -386,6 +434,7 @@ public AutoConfiguredOpenTelemetrySdk build() {
spiHelper,
meterProvider,
logRecordExporterCustomizer,
logRecordProcessorCustomizer,
closeables);
loggerProviderBuilder = loggerProviderCustomizer.apply(loggerProviderBuilder, config);
SdkLoggerProvider loggerProvider = loggerProviderBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,24 @@ static void configureLoggerProvider(
MeterProvider meterProvider,
BiFunction<? super LogRecordExporter, ConfigProperties, ? extends LogRecordExporter>
logRecordExporterCustomizer,
BiFunction<? super LogRecordProcessor, ConfigProperties, ? extends LogRecordProcessor>
logRecordProcessorCustomizer,
List<Closeable> closeables) {

loggerProviderBuilder.setLogLimits(() -> configureLogLimits(config));

Map<String, LogRecordExporter> exportersByName =
configureLogRecordExporters(config, spiHelper, logRecordExporterCustomizer, closeables);

configureLogRecordProcessors(config, exportersByName, meterProvider, closeables)
.forEach(loggerProviderBuilder::addLogRecordProcessor);
List<LogRecordProcessor> processors =
configureLogRecordProcessors(config, exportersByName, meterProvider, closeables);
for (LogRecordProcessor processor : processors) {
LogRecordProcessor wrapped = logRecordProcessorCustomizer.apply(processor, config);
if (wrapped != processor) {
closeables.add(wrapped);
}
loggerProviderBuilder.addLogRecordProcessor(wrapped);
}
}

// Visible for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ static void configureTracerProvider(
MeterProvider meterProvider,
BiFunction<? super SpanExporter, ConfigProperties, ? extends SpanExporter>
spanExporterCustomizer,
BiFunction<? super SpanProcessor, ConfigProperties, ? extends SpanProcessor>
spanProcessorCustomizer,
BiFunction<? super Sampler, ConfigProperties, ? extends Sampler> samplerCustomizer,
List<Closeable> closeables) {

Expand All @@ -53,8 +55,15 @@ static void configureTracerProvider(
SpanExporterConfiguration.configureSpanExporters(
config, spiHelper, spanExporterCustomizer, closeables);

configureSpanProcessors(config, exportersByName, meterProvider, closeables)
.forEach(tracerProviderBuilder::addSpanProcessor);
List<SpanProcessor> processors =
configureSpanProcessors(config, exportersByName, meterProvider, closeables);
for (SpanProcessor processor : processors) {
SpanProcessor wrapped = spanProcessorCustomizer.apply(processor, config);
if (wrapped != processor) {
closeables.add(wrapped);
}
tracerProviderBuilder.addSpanProcessor(wrapped);
}
}

static List<SpanProcessor> configureSpanProcessors(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import io.github.netmikey.logunit.api.LogCapturer;
Expand Down Expand Up @@ -49,8 +51,11 @@
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.IdGenerator;
import io.opentelemetry.sdk.trace.ReadWriteSpan;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
Expand Down Expand Up @@ -268,6 +273,48 @@ void builder_addSpanExporterCustomizer() {
.isEqualTo(spanExporter2);
}

@Test
void builder_addSpanProcessorCustomizer() {
SpanProcessor mockProcessor1 = Mockito.mock(SpanProcessor.class);
SpanProcessor mockProcessor2 = Mockito.mock(SpanProcessor.class);
doReturn(true).when(mockProcessor2).isStartRequired();
doReturn(true).when(mockProcessor2).isEndRequired();
Mockito.lenient().doReturn(CompletableResultCode.ofSuccess()).when(mockProcessor2).shutdown();
Mockito.lenient().when(spanExporter1.shutdown()).thenReturn(CompletableResultCode.ofSuccess());

SdkTracerProvider sdkTracerProvider =
builder
.addSpanExporterCustomizer((prev, config) -> spanExporter1)
.addSpanProcessorCustomizer(
(previous, config) -> {
assertThat(previous).isNotSameAs(mockProcessor2);
return mockProcessor1;
})
.addSpanProcessorCustomizer(
(previous, config) -> {
assertThat(previous).isSameAs(mockProcessor1);
return mockProcessor2;
})
.build()
.getOpenTelemetrySdk()
.getSdkTracerProvider();

assertThat(sdkTracerProvider)
.extracting("sharedState")
.extracting("activeSpanProcessor")
.isSameAs(mockProcessor2);

Span span = sdkTracerProvider.get("dummy-scope").spanBuilder("dummy-span").startSpan();

verify(mockProcessor2).onStart(any(), same((ReadWriteSpan) span));

span.end();
verify(mockProcessor2).onEnd(same((ReadableSpan) span));

verifyNoInteractions(mockProcessor1);
verifyNoInteractions(spanExporter1);
}

@Test
void builder_addPropertiesSupplier() {
AutoConfiguredOpenTelemetrySdk autoConfigured =
Expand Down Expand Up @@ -352,6 +399,8 @@ void builder_addLoggerProviderCustomizer() {

// TODO: add test for addLogRecordExporterCustomizer once OTLP export is enabled by default

// TODO: add test for addLogRecordProcessorCustomizer once OTLP export is enabled by default

@Test
void builder_setResultAsGlobalFalse() {
GlobalOpenTelemetry.set(OpenTelemetry.noop());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void configureLoggerProvider() {
SpiHelper.create(LoggerProviderConfiguration.class.getClassLoader()),
MeterProvider.noop(),
(a, unused) -> a,
(a, unused) -> a,
closeables);
cleanup.addCloseables(closeables);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ void configureTracerProvider() {
MeterProvider.noop(),
(a, unused) -> a,
(a, unused) -> a,
(a, unused) -> a,
closeables);

try (SdkTracerProvider tracerProvider = tracerProviderBuilder.build()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void configureLoggerProvider() {
SpiHelper.create(LoggerProviderConfiguration.class.getClassLoader()),
MeterProvider.noop(),
(a, unused) -> a,
(a, unused) -> a,
closeables);
cleanup.addCloseables(closeables);

Expand Down

0 comments on commit c8e1e36

Please sign in to comment.