diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
index df26146497b..c464bbdd2e2 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt
@@ -1,2 +1,4 @@
Comparing source compatibility of against
-No changes.
\ No newline at end of file
+*** 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 addMetricReaderCustomizer(java.util.function.BiFunction super io.opentelemetry.sdk.metrics.export.MetricReader,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.metrics.export.MetricReader>)
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
index df26146497b..04f3e512be6 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt
@@ -1,2 +1,4 @@
Comparing source compatibility of against
-No changes.
\ No newline at end of file
+*** 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.AutoConfiguredOpenTelemetrySdkBuilder addMetricReaderCustomizer(java.util.function.BiFunction super io.opentelemetry.sdk.metrics.export.MetricReader,io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties,? extends io.opentelemetry.sdk.metrics.export.MetricReader>)
diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java
index 03edca120bc..d64ec24f49d 100644
--- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java
+++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/AutoConfigurationCustomizer.java
@@ -11,6 +11,7 @@
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
+import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
import io.opentelemetry.sdk.trace.SpanProcessor;
@@ -150,12 +151,25 @@ default AutoConfigurationCustomizer addMeterProviderCustomizer(
*
*
Multiple calls will execute the customizers in order.
*/
+ @SuppressWarnings("UnusedReturnValue")
default AutoConfigurationCustomizer addMetricExporterCustomizer(
BiFunction super MetricExporter, ConfigProperties, ? extends MetricExporter>
exporterCustomizer) {
return this;
}
+ /**
+ * Adds a {@link BiFunction} to invoke with the autoconfigured {@link MetricReader} to allow
+ * customization. The return value of the {@link BiFunction} will replace the passed-in argument.
+ *
+ *
Multiple calls will execute the customizers in order.
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ default AutoConfigurationCustomizer addMetricReaderCustomizer(
+ BiFunction super MetricReader, ConfigProperties, ? extends MetricReader> readerCustomizer) {
+ return this;
+ }
+
/**
* Adds a {@link BiFunction} to invoke the with the {@link SdkLoggerProviderBuilder} to allow
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts
index 62fcd639c79..04fbde232fc 100644
--- a/sdk-extensions/autoconfigure/build.gradle.kts
+++ b/sdk-extensions/autoconfigure/build.gradle.kts
@@ -53,6 +53,7 @@ testing {
implementation(project(":exporters:logging-otlp"))
implementation(project(":exporters:otlp:all"))
implementation(project(":exporters:prometheus"))
+ implementation("io.prometheus:prometheus-metrics-exporter-httpserver")
implementation(project(":exporters:zipkin"))
implementation(project(":sdk:testing"))
implementation(project(":sdk:trace-shaded-deps"))
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
index 8e332c2a2b7..ac9d39a2a71 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkBuilder.java
@@ -28,6 +28,7 @@
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
+import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder;
@@ -83,6 +84,8 @@ public final class AutoConfiguredOpenTelemetrySdkBuilder implements AutoConfigur
meterProviderCustomizer = (a, unused) -> a;
private BiFunction super MetricExporter, ConfigProperties, ? extends MetricExporter>
metricExporterCustomizer = (a, unused) -> a;
+ private BiFunction super MetricReader, ConfigProperties, ? extends MetricReader>
+ metricReaderCustomizer = (a, unused) -> a;
private BiFunction
loggerProviderCustomizer = (a, unused) -> a;
@@ -283,6 +286,20 @@ public AutoConfiguredOpenTelemetrySdkBuilder addMetricExporterCustomizer(
return this;
}
+ /**
+ * Adds a {@link BiFunction} to invoke with the autoconfigured {@link MetricReader} to allow
+ * customization. The return value of the {@link BiFunction} will replace the passed-in argument.
+ *
+ * Multiple calls will execute the customizers in order.
+ */
+ @Override
+ public AutoConfiguredOpenTelemetrySdkBuilder addMetricReaderCustomizer(
+ BiFunction super MetricReader, ConfigProperties, ? extends MetricReader> readerCustomizer) {
+ requireNonNull(readerCustomizer, "readerCustomizer");
+ this.metricReaderCustomizer = mergeCustomizer(this.metricReaderCustomizer, readerCustomizer);
+ return this;
+ }
+
/**
* Adds a {@link BiFunction} to invoke the with the {@link SdkLoggerProviderBuilder} to allow
* customization. The return value of the {@link BiFunction} will replace the passed-in argument.
@@ -406,7 +423,12 @@ public AutoConfiguredOpenTelemetrySdk build() {
SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder();
meterProviderBuilder.setResource(resource);
MeterProviderConfiguration.configureMeterProvider(
- meterProviderBuilder, config, spiHelper, metricExporterCustomizer, closeables);
+ meterProviderBuilder,
+ config,
+ spiHelper,
+ metricReaderCustomizer,
+ metricExporterCustomizer,
+ closeables);
meterProviderBuilder = meterProviderCustomizer.apply(meterProviderBuilder, config);
SdkMeterProvider meterProvider = meterProviderBuilder.build();
closeables.add(meterProvider);
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java
index 525dc54974a..3689161b906 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfiguration.java
@@ -29,6 +29,8 @@ static void configureMeterProvider(
SdkMeterProviderBuilder meterProviderBuilder,
ConfigProperties config,
SpiHelper spiHelper,
+ BiFunction super MetricReader, ConfigProperties, ? extends MetricReader>
+ metricReaderCustomizer,
BiFunction super MetricExporter, ConfigProperties, ? extends MetricExporter>
metricExporterCustomizer,
List closeables) {
@@ -56,7 +58,8 @@ static void configureMeterProvider(
throw new ConfigurationException("otel.experimental.metrics.cardinality.limit must be >= 1");
}
- configureMetricReaders(config, spiHelper, metricExporterCustomizer, closeables)
+ configureMetricReaders(
+ config, spiHelper, metricReaderCustomizer, metricExporterCustomizer, closeables)
.forEach(
reader ->
SdkMeterProviderUtil.registerMetricReaderWithCardinalitySelector(
@@ -66,6 +69,8 @@ static void configureMeterProvider(
static List configureMetricReaders(
ConfigProperties config,
SpiHelper spiHelper,
+ BiFunction super MetricReader, ConfigProperties, ? extends MetricReader>
+ metricReaderCustomizer,
BiFunction super MetricExporter, ConfigProperties, ? extends MetricExporter>
metricExporterCustomizer,
List closeables) {
@@ -85,7 +90,12 @@ static List configureMetricReaders(
.map(
exporterName ->
MetricExporterConfiguration.configureReader(
- exporterName, config, spiHelper, metricExporterCustomizer, closeables))
+ exporterName,
+ config,
+ spiHelper,
+ metricReaderCustomizer,
+ metricExporterCustomizer,
+ closeables))
.collect(Collectors.toList());
}
diff --git a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java
index 2aa968a82bb..3b4a1da1658 100644
--- a/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java
+++ b/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfiguration.java
@@ -42,6 +42,8 @@ static MetricReader configureReader(
String name,
ConfigProperties config,
SpiHelper spiHelper,
+ BiFunction super MetricReader, ConfigProperties, ? extends MetricReader>
+ metricReaderCustomizer,
BiFunction super MetricExporter, ConfigProperties, ? extends MetricExporter>
metricExporterCustomizer,
List closeables) {
@@ -56,7 +58,14 @@ static MetricReader configureReader(
MetricReader metricReader = configureMetricReader(name, spiMetricReadersManager);
if (metricReader != null) {
closeables.add(metricReader);
- return metricReader;
+
+ // Customize metric reader
+ MetricReader customizedMetricReader = metricReaderCustomizer.apply(metricReader, config);
+ if (customizedMetricReader != metricReader) {
+ closeables.add(customizedMetricReader);
+ }
+
+ return customizedMetricReader;
}
// No exporter or reader with the name
throw new ConfigurationException("Unrecognized value for otel.metrics.exporter: " + name);
@@ -74,7 +83,11 @@ static MetricReader configureReader(
.setInterval(config.getDuration("otel.metric.export.interval", DEFAULT_EXPORT_INTERVAL))
.build();
closeables.add(reader);
- return reader;
+ MetricReader customizedMetricReader = metricReaderCustomizer.apply(reader, config);
+ if (customizedMetricReader != reader) {
+ closeables.add(customizedMetricReader);
+ }
+ return customizedMetricReader;
}
// Visible for testing
diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
index c501d28e3cb..900ba509d71 100644
--- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
+++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
@@ -54,6 +54,7 @@ private static ObjectAssert assertExemplarFilter(Map a,
+ (a, b) -> a,
new ArrayList<>());
return assertThat(builder)
.extracting("exemplarFilter", as(InstanceOfAssertFactories.type(ExemplarFilter.class)));
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java
index 6bf5c74ccc5..f1f880441e6 100644
--- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/AutoConfiguredOpenTelemetrySdkTest.java
@@ -5,12 +5,16 @@
package io.opentelemetry.sdk.autoconfigure;
+import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import com.linecorp.armeria.client.WebClient;
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.events.GlobalEventEmitterProvider;
+import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import java.lang.reflect.Field;
import org.junit.jupiter.api.BeforeEach;
@@ -31,6 +35,25 @@ void setUp() {
GlobalEventEmitterProvider.resetForTest();
}
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @Test
+ void build_addMetricReaderCustomizerPrometheus() {
+ AutoConfiguredOpenTelemetrySdkBuilder builder = AutoConfiguredOpenTelemetrySdk.builder();
+ builder.addPropertiesSupplier(() -> singletonMap("otel.metrics.exporter", "prometheus"));
+
+ int port = FreePortFinder.getFreePort();
+ builder.addMetricReaderCustomizer(
+ (reader, config) -> {
+ assertThat(reader).isInstanceOf(PrometheusHttpServer.class);
+ return PrometheusHttpServer.builder().setPort(port).build();
+ });
+
+ try (OpenTelemetrySdk ignored = builder.build().getOpenTelemetrySdk()) {
+ WebClient client = WebClient.builder("http://localhost:" + port).build();
+ assertThatCode(() -> client.get("/metrics")).doesNotThrowAnyException();
+ }
+ }
+
@Test
void initializeAndGet() {
try (OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk()) {
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java
index 18797f0058b..bc32ebc84a4 100644
--- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/ConfigurableMetricExporterTest.java
@@ -87,7 +87,7 @@ void configureMetricReaders_multipleWithNone() {
assertThatThrownBy(
() ->
MeterProviderConfiguration.configureMetricReaders(
- config, spiHelper, (a, unused) -> a, closeables))
+ config, spiHelper, (a, unused) -> a, (a, unused) -> a, closeables))
.isInstanceOf(ConfigurationException.class)
.hasMessageContaining("otel.metrics.exporter contains none along with other exporters");
cleanup.addCloseables(closeables);
@@ -102,7 +102,11 @@ void configureMetricReaders_defaultExporter() {
List metricReaders =
MeterProviderConfiguration.configureMetricReaders(
- config, spiHelper, (metricExporter, unused) -> metricExporter, closeables);
+ config,
+ spiHelper,
+ (a, unused) -> a,
+ (metricExporter, unused) -> metricExporter,
+ closeables);
cleanup.addCloseables(closeables);
assertThat(metricReaders)
@@ -125,7 +129,11 @@ void configureMetricReaders_multipleExporters() {
List metricReaders =
MeterProviderConfiguration.configureMetricReaders(
- config, spiHelper, (metricExporter, unused) -> metricExporter, closeables);
+ config,
+ spiHelper,
+ (a, unused) -> a,
+ (metricExporter, unused) -> metricExporter,
+ closeables);
cleanup.addCloseables(closeables);
assertThat(metricReaders).hasSize(2).hasOnlyElementsOfType(PeriodicMetricReader.class);
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FreePortFinder.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FreePortFinder.java
new file mode 100644
index 00000000000..92c2b7640c7
--- /dev/null
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/FreePortFinder.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.sdk.autoconfigure;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+final class FreePortFinder {
+
+ static int getFreePort() {
+ try (ServerSocket socket = new ServerSocket(0)) {
+ return socket.getLocalPort();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private FreePortFinder() {}
+}
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
index c5df15c73bb..b2062c20dd5 100644
--- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MeterProviderConfigurationTest.java
@@ -50,6 +50,7 @@ void configureMeterProvider_InvalidCardinalityLimit() {
"0")),
spiHelper,
(a, b) -> a,
+ (a, b) -> a,
closeables);
})
.isInstanceOf(ConfigurationException.class)
@@ -69,6 +70,7 @@ void configureMeterProvider_ConfiguresCardinalityLimit() {
Collections.singletonMap("otel.metrics.exporter", "logging")),
spiHelper,
(a, b) -> a,
+ (a, b) -> a,
closeables);
cleanup.addCloseables(closeables);
assertCardinalityLimit(builder, 2000);
@@ -85,6 +87,7 @@ void configureMeterProvider_ConfiguresCardinalityLimit() {
"100")),
spiHelper,
(a, b) -> a,
+ (a, b) -> a,
closeables);
cleanup.addCloseables(closeables);
assertCardinalityLimit(builder, 100);
diff --git a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java
index 6db4b23f82e..c8bd0937e63 100644
--- a/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java
+++ b/sdk-extensions/autoconfigure/src/testFullConfig/java/io/opentelemetry/sdk/autoconfigure/MetricExporterConfigurationTest.java
@@ -5,6 +5,7 @@
package io.opentelemetry.sdk.autoconfigure;
+import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -21,11 +22,16 @@
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.MetricReader;
+import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
+import io.prometheus.metrics.exporter.httpserver.HTTPServer;
import java.io.Closeable;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.function.BiFunction;
import java.util.stream.Stream;
+import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
@@ -49,13 +55,55 @@ void configureReader_PrometheusOnClasspath() {
MetricReader reader =
MetricExporterConfiguration.configureReader(
- "prometheus", CONFIG_PROPERTIES, spiHelper, (a, b) -> a, closeables);
+ "prometheus", CONFIG_PROPERTIES, spiHelper, (a, b) -> a, (a, b) -> a, closeables);
cleanup.addCloseables(closeables);
assertThat(reader).isInstanceOf(PrometheusHttpServer.class);
assertThat(closeables).hasSize(1);
}
+ @Test
+ void configureReader_customizeReader_prometheus() {
+ List closeables = new ArrayList<>();
+
+ int port = FreePortFinder.getFreePort();
+ BiFunction readerCustomizer =
+ (existingReader, config) -> PrometheusHttpServer.builder().setPort(port).build();
+ MetricReader reader =
+ MetricExporterConfiguration.configureReader(
+ "prometheus", CONFIG_PROPERTIES, spiHelper, readerCustomizer, (a, b) -> a, closeables);
+ cleanup.addCloseables(closeables);
+
+ assertThat(reader).isInstanceOf(PrometheusHttpServer.class);
+ assertThat(closeables).hasSize(2);
+ PrometheusHttpServer prometheusHttpServer = (PrometheusHttpServer) reader;
+ assertThat(prometheusHttpServer)
+ .extracting("httpServer", as(InstanceOfAssertFactories.type(HTTPServer.class)))
+ .satisfies(httpServer -> assertThat(httpServer.getPort()).isEqualTo(port));
+ }
+
+ @Test
+ void configureReader_customizeReader_otlp() {
+ List closeables = new ArrayList<>();
+
+ BiFunction readerCustomizer =
+ (existingReader, config) ->
+ PeriodicMetricReader.builder(OtlpGrpcMetricExporter.builder().build())
+ .setInterval(Duration.ofSeconds(123))
+ .build();
+ MetricReader reader =
+ MetricExporterConfiguration.configureReader(
+ "otlp", CONFIG_PROPERTIES, spiHelper, readerCustomizer, (a, b) -> a, closeables);
+ cleanup.addCloseables(closeables);
+
+ assertThat(reader).isInstanceOf(PeriodicMetricReader.class);
+ assertThat(closeables).hasSize(3);
+ PeriodicMetricReader periodicMetricReader = (PeriodicMetricReader) reader;
+ assertThat(periodicMetricReader)
+ .extracting("intervalNanos")
+ .isEqualTo(Duration.ofSeconds(123).toNanos());
+ }
+
@ParameterizedTest
@MethodSource("knownExporters")
void configureExporter_KnownSpiExportersOnClasspath(