Autoconfigure listener (#5931)

This commit is contained in:
jack-berg 2023-11-09 08:49:21 -06:00 committed by GitHub
parent f99e4961cb
commit f2f3ab33b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 295 additions and 62 deletions

View File

@ -1,2 +1,13 @@
Comparing source compatibility of against
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder setMeterProvider(java.util.function.Supplier<io.opentelemetry.api.metrics.MeterProvider>)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder setMeterProvider(java.util.function.Supplier<io.opentelemetry.api.metrics.MeterProvider>)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder setMeterProvider(java.util.function.Supplier<io.opentelemetry.api.metrics.MeterProvider>)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder setMeterProvider(java.util.function.Supplier<io.opentelemetry.api.metrics.MeterProvider>)

View File

@ -123,8 +123,8 @@ public class GrpcExporterBuilder<T extends Marshaler> {
return this;
}
public GrpcExporterBuilder<T> setMeterProvider(MeterProvider meterProvider) {
this.meterProviderSupplier = () -> meterProvider;
public GrpcExporterBuilder<T> setMeterProvider(Supplier<MeterProvider> meterProviderSupplier) {
this.meterProviderSupplier = meterProviderSupplier;
return this;
}

View File

@ -112,8 +112,8 @@ public final class HttpExporterBuilder<T extends Marshaler> {
return this;
}
public HttpExporterBuilder<T> setMeterProvider(MeterProvider meterProvider) {
this.meterProviderSupplier = () -> meterProvider;
public HttpExporterBuilder<T> setMeterProvider(Supplier<MeterProvider> meterProviderSupplier) {
this.meterProviderSupplier = meterProviderSupplier;
return this;
}

View File

@ -145,7 +145,7 @@ public final class JaegerGrpcSpanExporterBuilder {
*/
public JaegerGrpcSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(meterProvider);
delegate.setMeterProvider(() -> meterProvider);
return this;
}

View File

@ -16,6 +16,7 @@ import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
import io.opentelemetry.sdk.common.export.RetryPolicy;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
@ -135,7 +136,18 @@ public final class OtlpHttpLogRecordExporterBuilder {
*/
public OtlpHttpLogRecordExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(meterProvider);
setMeterProvider(() -> meterProvider);
return this;
}
/**
* Sets the {@link MeterProvider} supplier used to collect metrics related to export. If not set,
* uses {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpHttpLogRecordExporterBuilder setMeterProvider(
Supplier<MeterProvider> meterProviderSupplier) {
requireNonNull(meterProviderSupplier, "meterProviderSupplier");
delegate.setMeterProvider(meterProviderSupplier);
return this;
}

View File

@ -43,7 +43,7 @@ public final class OtlpHttpMetricExporterBuilder {
OtlpHttpMetricExporterBuilder(HttpExporterBuilder<MetricsRequestMarshaler> delegate) {
this.delegate = delegate;
delegate.setMeterProvider(MeterProvider.noop());
delegate.setMeterProvider(MeterProvider::noop);
OtlpUserAgent.addUserAgentHeader(delegate::addHeader);
}

View File

@ -16,6 +16,7 @@ import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
import io.opentelemetry.sdk.common.export.RetryPolicy;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
@ -136,7 +137,18 @@ public final class OtlpHttpSpanExporterBuilder {
*/
public OtlpHttpSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(meterProvider);
setMeterProvider(() -> meterProvider);
return this;
}
/**
* Sets the {@link MeterProvider} supplier to use to collect metrics related to export. If not
* set, uses {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpHttpSpanExporterBuilder setMeterProvider(
Supplier<MeterProvider> meterProviderSupplier) {
requireNonNull(meterProviderSupplier, "meterProviderSupplier");
delegate.setMeterProvider(meterProviderSupplier);
return this;
}

View File

@ -9,14 +9,18 @@ import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.DATA_TYPE_L
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_GRPC;
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder;
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import java.util.concurrent.atomic.AtomicReference;
/**
* {@link LogRecordExporter} SPI implementation for {@link OtlpGrpcLogRecordExporter} and {@link
@ -25,7 +29,12 @@ import io.opentelemetry.sdk.logs.export.LogRecordExporter;
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public class OtlpLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider {
public class OtlpLogRecordExporterProvider
implements ConfigurableLogRecordExporterProvider, AutoConfigureListener {
private final AtomicReference<MeterProvider> meterProviderRef =
new AtomicReference<>(MeterProvider.noop());
@Override
public LogRecordExporter createExporter(ConfigProperties config) {
String protocol = OtlpConfigUtil.getOtlpProtocol(DATA_TYPE_LOGS, config);
@ -43,6 +52,7 @@ public class OtlpLogRecordExporterProvider implements ConfigurableLogRecordExpor
builder::setTrustedCertificates,
builder::setClientTls,
builder::setRetryPolicy);
builder.setMeterProvider(meterProviderRef::get);
return builder.build();
} else if (protocol.equals(PROTOCOL_GRPC)) {
@ -58,6 +68,7 @@ public class OtlpLogRecordExporterProvider implements ConfigurableLogRecordExpor
builder::setTrustedCertificates,
builder::setClientTls,
builder::setRetryPolicy);
builder.setMeterProvider(meterProviderRef::get);
return builder.build();
}
@ -78,4 +89,9 @@ public class OtlpLogRecordExporterProvider implements ConfigurableLogRecordExpor
OtlpGrpcLogRecordExporterBuilder grpcBuilder() {
return OtlpGrpcLogRecordExporter.builder();
}
@Override
public void afterAutoConfigure(OpenTelemetrySdk sdk) {
meterProviderRef.set(sdk.getMeterProvider());
}
}

View File

@ -26,6 +26,7 @@ import io.opentelemetry.sdk.metrics.export.MetricExporter;
* at any time.
*/
public class OtlpMetricExporterProvider implements ConfigurableMetricExporterProvider {
@Override
public MetricExporter createExporter(ConfigProperties config) {
String protocol = OtlpConfigUtil.getOtlpProtocol(DATA_TYPE_METRICS, config);

View File

@ -9,14 +9,18 @@ import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.DATA_TYPE_T
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_GRPC;
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.concurrent.atomic.AtomicReference;
/**
* {@link SpanExporter} SPI implementation for {@link OtlpGrpcSpanExporter} and {@link
@ -25,7 +29,12 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public class OtlpSpanExporterProvider implements ConfigurableSpanExporterProvider {
public class OtlpSpanExporterProvider
implements ConfigurableSpanExporterProvider, AutoConfigureListener {
private final AtomicReference<MeterProvider> meterProviderRef =
new AtomicReference<>(MeterProvider.noop());
@Override
public SpanExporter createExporter(ConfigProperties config) {
String protocol = OtlpConfigUtil.getOtlpProtocol(DATA_TYPE_TRACES, config);
@ -42,6 +51,7 @@ public class OtlpSpanExporterProvider implements ConfigurableSpanExporterProvide
builder::setTrustedCertificates,
builder::setClientTls,
builder::setRetryPolicy);
builder.setMeterProvider(meterProviderRef::get);
return builder.build();
} else if (protocol.equals(PROTOCOL_GRPC)) {
@ -57,6 +67,7 @@ public class OtlpSpanExporterProvider implements ConfigurableSpanExporterProvide
builder::setTrustedCertificates,
builder::setClientTls,
builder::setRetryPolicy);
builder.setMeterProvider(meterProviderRef::get);
return builder.build();
}
@ -77,4 +88,9 @@ public class OtlpSpanExporterProvider implements ConfigurableSpanExporterProvide
OtlpGrpcSpanExporterBuilder grpcBuilder() {
return OtlpGrpcSpanExporter.builder();
}
@Override
public void afterAutoConfigure(OpenTelemetrySdk sdk) {
meterProviderRef.set(sdk.getMeterProvider());
}
}

View File

@ -18,6 +18,7 @@ import io.opentelemetry.sdk.common.export.RetryPolicy;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
@ -179,7 +180,18 @@ public final class OtlpGrpcLogRecordExporterBuilder {
*/
public OtlpGrpcLogRecordExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(meterProvider);
setMeterProvider(() -> meterProvider);
return this;
}
/**
* Sets the {@link MeterProvider} supplier used to collect metrics related to export. If not set,
* uses {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpGrpcLogRecordExporterBuilder setMeterProvider(
Supplier<MeterProvider> meterProviderSupplier) {
requireNonNull(meterProviderSupplier, "meterProviderSupplier");
delegate.setMeterProvider(meterProviderSupplier);
return this;
}

View File

@ -53,7 +53,7 @@ public final class OtlpGrpcMetricExporterBuilder {
OtlpGrpcMetricExporterBuilder(GrpcExporterBuilder<MetricsRequestMarshaler> delegate) {
this.delegate = delegate;
delegate.setMeterProvider(MeterProvider.noop());
delegate.setMeterProvider(MeterProvider::noop);
OtlpUserAgent.addUserAgentHeader(delegate::addHeader);
}

View File

@ -18,6 +18,7 @@ import io.opentelemetry.sdk.common.export.RetryPolicy;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
@ -176,7 +177,18 @@ public final class OtlpGrpcSpanExporterBuilder {
*/
public OtlpGrpcSpanExporterBuilder setMeterProvider(MeterProvider meterProvider) {
requireNonNull(meterProvider, "meterProvider");
delegate.setMeterProvider(meterProvider);
setMeterProvider(() -> meterProvider);
return this;
}
/**
* Sets the {@link MeterProvider} supplier used to collect metrics related to export. If not set,
* uses {@link GlobalOpenTelemetry#getMeterProvider()}.
*/
public OtlpGrpcSpanExporterBuilder setMeterProvider(
Supplier<MeterProvider> meterProviderSupplier) {
requireNonNull(meterProviderSupplier, "meterProviderSupplier");
delegate.setMeterProvider(meterProviderSupplier);
return this;
}

View File

@ -259,7 +259,7 @@ public class OtlpPipelineStressTest {
// set up the span exporter and wire it into the SDK
OtlpGrpcSpanExporter spanExporter =
OtlpGrpcSpanExporter.builder()
.setMeterProvider(meterProvider)
.setMeterProvider(() -> meterProvider)
.setEndpoint(
"http://"
+ toxiproxyContainer.getHost()

View File

@ -0,0 +1,20 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.autoconfigure.spi.internal;
import io.opentelemetry.sdk.OpenTelemetrySdk;
/**
* Interface to be extended by SPIs that require access to the autoconfigured {@link
* OpenTelemetrySdk} instance.
*
* <p>This is not a standalone SPI. Instead, implementations of other SPIs can also implement this
* interface to receive a callback with the configured SDK.
*/
public interface AutoConfigureListener {
void afterAutoConfigure(OpenTelemetrySdk sdk);
}

View File

@ -18,6 +18,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
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.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
@ -405,6 +406,7 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
maybeRegisterShutdownHook(openTelemetrySdk);
maybeSetAsGlobal(openTelemetrySdk);
callAutoConfigureListeners(spiHelper, openTelemetrySdk);
return AutoConfiguredOpenTelemetrySdk.create(openTelemetrySdk, resource, config);
} catch (RuntimeException e) {
@ -478,6 +480,18 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
Level.FINE, "Global OpenTelemetry set to {0} by autoconfiguration", openTelemetrySdk);
}
// Visible for testing
void callAutoConfigureListeners(SpiHelper spiHelper, OpenTelemetrySdk openTelemetrySdk) {
for (AutoConfigureListener listener : spiHelper.getListeners()) {
try {
listener.afterAutoConfigure(openTelemetrySdk);
} catch (Throwable throwable) {
logger.log(
Level.WARNING, "Error invoking listener " + listener.getClass().getName(), throwable);
}
}
}
@SuppressWarnings("deprecation") // Support deprecated SdkTracerProviderConfigurer
private void mergeSdkTracerProviderConfigurer() {
for (io.opentelemetry.sdk.autoconfigure.spi.traces.SdkTracerProviderConfigurer configurer :

View File

@ -7,12 +7,16 @@ package io.opentelemetry.sdk.autoconfigure.internal;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
@ -25,6 +29,8 @@ public final class SpiHelper {
private final ClassLoader classLoader;
private final SpiFinder spiFinder;
private final Set<AutoConfigureListener> listeners =
Collections.newSetFromMap(new IdentityHashMap<>());
// Visible for testing
SpiHelper(ClassLoader classLoader, SpiFinder spiFinder) {
@ -57,7 +63,13 @@ public final class SpiHelper {
Map<String, Supplier<T>> nameToProvider = new HashMap<>();
for (S provider : load(spiClass)) {
String name = getName.apply(provider);
nameToProvider.put(name, () -> getConfigurable.apply(provider, config));
nameToProvider.put(
name,
() -> {
T result = getConfigurable.apply(provider, config);
maybeAddListener(result);
return result;
});
}
return NamedSpiManager.create(nameToProvider);
}
@ -85,11 +97,23 @@ public final class SpiHelper {
public <T> List<T> load(Class<T> spiClass) {
List<T> result = new ArrayList<>();
for (T service : spiFinder.load(spiClass, classLoader)) {
maybeAddListener(service);
result.add(service);
}
return result;
}
private void maybeAddListener(Object object) {
if (object instanceof AutoConfigureListener) {
listeners.add((AutoConfigureListener) object);
}
}
/** Return the set of SPIs loaded which implement {@link AutoConfigureListener}. */
public Set<AutoConfigureListener> getListeners() {
return Collections.unmodifiableSet(listeners);
}
// Visible for testing
interface SpiFinder {
<T> Iterable<T> load(Class<T> spiClass, ClassLoader classLoader);

View File

@ -8,6 +8,7 @@ package io.opentelemetry.sdk.autoconfigure;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
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.Mockito.doReturn;
@ -33,8 +34,10 @@ import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
@ -393,6 +396,27 @@ class AutoConfiguredOpenTelemetrySdkTest {
verify(sdk).close();
}
@Test
void builder_CallAutoConfigureListeners() {
builder = spy(builder);
assertThatCode(() -> builder.build()).doesNotThrowAnyException();
verify(builder, times(1)).callAutoConfigureListeners(any(), any());
}
@Test
void callAutoConfigureListeners() {
AutoConfigureListener listener = mock(AutoConfigureListener.class);
SpiHelper spiHelper = mock(SpiHelper.class);
when(spiHelper.getListeners()).thenReturn(Collections.singleton(listener));
OpenTelemetrySdk sdk = mock(OpenTelemetrySdk.class);
builder.callAutoConfigureListeners(spiHelper, sdk);
verify(listener).afterAutoConfigure(sdk);
}
private static Supplier<Map<String, String>> disableExportPropertySupplier() {
Map<String, String> props = new HashMap<>();
props.put("otel.metrics.exporter", "none");

View File

@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.exporter.otlp.internal.OtlpLogRecordExporterProvider;
import io.opentelemetry.internal.testing.CleanupExtension;
import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
@ -37,12 +38,10 @@ class ConfigurableLogRecordExporterTest {
ImmutableMap.of("test.option", "true", "otel.logs.exporter", "testExporter"));
List<Closeable> closeables = new ArrayList<>();
SpiHelper spiHelper = SpiHelper.create(LogRecordExporterConfiguration.class.getClassLoader());
Map<String, LogRecordExporter> exportersByName =
LogRecordExporterConfiguration.configureLogRecordExporters(
config,
SpiHelper.create(LogRecordExporterConfiguration.class.getClassLoader()),
(a, unused) -> a,
closeables);
config, spiHelper, (a, unused) -> a, closeables);
cleanup.addCloseables(closeables);
assertThat(exportersByName)
@ -55,6 +54,11 @@ class ConfigurableLogRecordExporterTest {
assertThat(closeables)
.hasExactlyElementsOfTypes(
TestConfigurableLogRecordExporterProvider.TestLogRecordExporter.class);
assertThat(spiHelper.getListeners())
.satisfiesExactlyInAnyOrder(
listener ->
assertThat(listener).isInstanceOf(TestConfigurableLogRecordExporterProvider.class),
listener -> assertThat(listener).isInstanceOf(OtlpLogRecordExporterProvider.class));
}
@Test
@ -64,17 +68,16 @@ class ConfigurableLogRecordExporterTest {
ImmutableMap.of("test.option", "true", "otel.logs.exporter", "testExporter"));
List<Closeable> closeables = new ArrayList<>();
SpiHelper spiHelper = SpiHelper.create(new URLClassLoader(new URL[0], null));
assertThatThrownBy(
() ->
LogRecordExporterConfiguration.configureLogRecordExporters(
config,
SpiHelper.create(new URLClassLoader(new URL[0], null)),
(a, unused) -> a,
closeables))
config, spiHelper, (a, unused) -> a, closeables))
.isInstanceOf(ConfigurationException.class)
.hasMessageContaining("testExporter");
cleanup.addCloseables(closeables);
assertThat(closeables).isEmpty();
assertThat(spiHelper.getListeners()).isEmpty();
}
@Test

View File

@ -49,6 +49,10 @@ class ConfigurableMetricExporterTest {
.isInstanceOf(TestConfigurableMetricExporterProvider.TestMetricExporter.class)
.extracting("config")
.isSameAs(config);
assertThat(spiHelper.getListeners())
.satisfiesExactlyInAnyOrder(
listener ->
assertThat(listener).isInstanceOf(TestConfigurableMetricExporterProvider.class));
}
}
@ -88,6 +92,7 @@ class ConfigurableMetricExporterTest {
.hasMessageContaining("otel.metrics.exporter contains none along with other exporters");
cleanup.addCloseables(closeables);
assertThat(closeables).isEmpty();
assertThat(spiHelper.getListeners()).isEmpty();
}
@Test

View File

@ -11,6 +11,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
import io.opentelemetry.exporter.otlp.internal.OtlpSpanExporterProvider;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter;
import io.opentelemetry.internal.testing.CleanupExtension;
@ -63,6 +64,11 @@ class ConfigurableSpanExporterTest {
.isSameAs(config);
assertThat(closeables)
.hasExactlyElementsOfTypes(TestConfigurableSpanExporterProvider.TestSpanExporter.class);
assertThat(spiHelper.getListeners())
.satisfiesExactlyInAnyOrder(
listener ->
assertThat(listener).isInstanceOf(TestConfigurableSpanExporterProvider.class),
listener -> assertThat(listener).isInstanceOf(OtlpSpanExporterProvider.class));
}
@Test
@ -83,6 +89,7 @@ class ConfigurableSpanExporterTest {
.hasMessageContaining("testExporter");
cleanup.addCloseables(closeables);
assertThat(closeables).isEmpty();
assertThat(spiHelper.getListeners()).isEmpty();
}
@Test

View File

@ -39,8 +39,6 @@ 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.metrics.v1.Metric;
import io.opentelemetry.proto.metrics.v1.ResourceMetrics;
import io.opentelemetry.proto.metrics.v1.ScopeMetrics;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import java.util.ArrayList;
import java.util.Collection;
@ -216,8 +214,8 @@ class FullConfigTest {
eventEmitter.emit("test-name", Attributes.builder().put("cow", "moo").build());
openTelemetrySdk.getSdkTracerProvider().forceFlush().join(10, TimeUnit.SECONDS);
openTelemetrySdk.getSdkMeterProvider().forceFlush().join(10, TimeUnit.SECONDS);
openTelemetrySdk.getSdkLoggerProvider().forceFlush().join(10, TimeUnit.SECONDS);
openTelemetrySdk.getSdkMeterProvider().forceFlush().join(10, TimeUnit.SECONDS);
await().untilAsserted(() -> assertThat(otlpTraceRequests).hasSize(1));
@ -257,38 +255,61 @@ class FullConfigTest {
.untilAsserted(
() -> {
ExportMetricsServiceRequest metricRequest = otlpMetricsRequests.take();
assertThat(metricRequest.getResourceMetrics(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());
for (ResourceMetrics resourceMetrics : metricRequest.getResourceMetricsList()) {
assertThat(resourceMetrics.getScopeMetricsList())
.anySatisfy(ilm -> assertThat(ilm.getScope().getName()).isEqualTo("test"));
for (ScopeMetrics instrumentationLibraryMetrics :
resourceMetrics.getScopeMetricsList()) {
for (Metric metric : instrumentationLibraryMetrics.getMetricsList()) {
// SPI was loaded
// MetricExporterCustomizer filters metrics not named my-metric
assertThat(metric.getName()).isEqualTo("my-metric");
// TestMeterProviderConfigurer configures a view that only passes on attribute
// named allowed
// configured-test
assertThat(getFirstDataPointLabels(metric))
.contains(
KeyValue.newBuilder()
.setKey("allowed")
.setValue(AnyValue.newBuilder().setStringValue("bear").build())
.build());
}
}
}
assertThat(metricRequest.getResourceMetricsList())
.satisfiesExactly(
resourceMetrics -> {
assertThat(resourceMetrics.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());
assertThat(resourceMetrics.getScopeMetricsList())
.anySatisfy(
scopeMetrics -> {
assertThat(scopeMetrics.getScope().getName()).isEqualTo("test");
assertThat(scopeMetrics.getMetricsList())
.satisfiesExactly(
metric -> {
// SPI was loaded
assertThat(metric.getName()).isEqualTo("my-metric");
// TestMeterProviderConfigurer configures a view that
// only passes on attribute
// named allowed
// configured-test
assertThat(getFirstDataPointLabels(metric))
.contains(
KeyValue.newBuilder()
.setKey("allowed")
.setValue(
AnyValue.newBuilder()
.setStringValue("bear")
.build())
.build());
});
})
// This verifies that AutoConfigureListener was invoked and the OTLP
// span / log exporters received the autoconfigured OpenTelemetrySdk
// instance
.anySatisfy(
scopeMetrics -> {
assertThat(scopeMetrics.getScope().getName())
.isEqualTo("io.opentelemetry.exporters.otlp-grpc");
assertThat(scopeMetrics.getMetricsList())
.satisfiesExactlyInAnyOrder(
metric ->
assertThat(metric.getName())
.isEqualTo("otlp.exporter.seen"),
metric ->
assertThat(metric.getName())
.isEqualTo("otlp.exporter.exported"));
});
});
});
await().untilAsserted(() -> assertThat(otlpLogsRequests).hasSize(1));

View File

@ -48,7 +48,13 @@ public class MetricCustomizer implements AutoConfigurationCustomizerProvider {
// please configure the SdkMeterProvider with the appropriate view.
Collection<MetricData> filtered =
metrics.stream()
.filter(metricData -> metricData.getName().equals("my-metric"))
.filter(
metricData ->
metricData.getName().equals("my-metric")
|| metricData
.getInstrumentationScopeInfo()
.getName()
.startsWith("io.opentelemetry.exporters"))
.collect(Collectors.toList());
return delegate.export(filtered);
}

View File

@ -5,7 +5,9 @@
package io.opentelemetry.sdk.autoconfigure.provider;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.logs.data.LogRecordData;
@ -13,7 +15,7 @@ import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import java.util.Collection;
public class TestConfigurableLogRecordExporterProvider
implements ConfigurableLogRecordExporterProvider {
implements ConfigurableLogRecordExporterProvider, AutoConfigureListener {
@Override
public LogRecordExporter createExporter(ConfigProperties config) {
@ -25,6 +27,9 @@ public class TestConfigurableLogRecordExporterProvider
return "testExporter";
}
@Override
public void afterAutoConfigure(OpenTelemetrySdk sdk) {}
public static class TestLogRecordExporter implements LogRecordExporter {
private final ConfigProperties config;

View File

@ -5,7 +5,9 @@
package io.opentelemetry.sdk.autoconfigure.provider;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.metrics.InstrumentType;
@ -14,7 +16,8 @@ import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import java.util.Collection;
public class TestConfigurableMetricExporterProvider implements ConfigurableMetricExporterProvider {
public class TestConfigurableMetricExporterProvider
implements ConfigurableMetricExporterProvider, AutoConfigureListener {
@Override
public MetricExporter createExporter(ConfigProperties config) {
@ -26,6 +29,9 @@ public class TestConfigurableMetricExporterProvider implements ConfigurableMetri
return "testExporter";
}
@Override
public void afterAutoConfigure(OpenTelemetrySdk sdk) {}
public static class TestMetricExporter implements MetricExporter {
private final ConfigProperties config;

View File

@ -5,14 +5,17 @@
package io.opentelemetry.sdk.autoconfigure.provider;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.AutoConfigureListener;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.util.Collection;
public class TestConfigurableSpanExporterProvider implements ConfigurableSpanExporterProvider {
public class TestConfigurableSpanExporterProvider
implements ConfigurableSpanExporterProvider, AutoConfigureListener {
@Override
public SpanExporter createExporter(ConfigProperties config) {
return new TestSpanExporter(config);
@ -23,6 +26,9 @@ public class TestConfigurableSpanExporterProvider implements ConfigurableSpanExp
return "testExporter";
}
@Override
public void afterAutoConfigure(OpenTelemetrySdk sdk) {}
public static class TestSpanExporter implements SpanExporter {
private final ConfigProperties config;