Auto-configure OtlpMetricsSender if available

Update `OtlpMetricsExportAutoConfiguration` to use the new
`OtlpMetricsSender`interface that allows users to customize the
sending of OTLP metrics using the `OtlpMeterRegistry`.

See gh-45204
This commit is contained in:
Tommy Ludwig
2025-04-15 18:28:46 +09:00
committed by Phillip Webb
parent 752842a4ee
commit 776d233c1c
3 changed files with 57 additions and 4 deletions

View File

@@ -19,7 +19,10 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.otlp;
import io.micrometer.core.instrument.Clock;
import io.micrometer.registry.otlp.OtlpConfig;
import io.micrometer.registry.otlp.OtlpMeterRegistry;
import io.micrometer.registry.otlp.OtlpMeterRegistry.Builder;
import io.micrometer.registry.otlp.OtlpMetricsSender;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport;
@@ -76,16 +79,24 @@ public class OtlpMetricsExportAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnThreading(Threading.PLATFORM)
public OtlpMeterRegistry otlpMeterRegistry(OtlpConfig otlpConfig, Clock clock) {
return new OtlpMeterRegistry(otlpConfig, clock);
public OtlpMeterRegistry otlpMeterRegistry(OtlpConfig otlpConfig, Clock clock,
ObjectProvider<OtlpMetricsSender> metricsSender) {
Builder builder = OtlpMeterRegistry.builder(otlpConfig).clock(clock);
metricsSender.ifAvailable(builder::metricsSender);
return builder.build();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnThreading(Threading.VIRTUAL)
public OtlpMeterRegistry otlpMeterRegistryVirtualThreads(OtlpConfig otlpConfig, Clock clock) {
public OtlpMeterRegistry otlpMeterRegistryVirtualThreads(OtlpConfig otlpConfig, Clock clock,
ObjectProvider<OtlpMetricsSender> metricsSender) {
VirtualThreadTaskExecutor taskExecutor = new VirtualThreadTaskExecutor("otlp-meter-registry-");
return new OtlpMeterRegistry(otlpConfig, clock, taskExecutor.getVirtualThreadFactory());
Builder builder = OtlpMeterRegistry.builder(otlpConfig)
.clock(clock)
.threadFactory(taskExecutor.getVirtualThreadFactory());
metricsSender.ifAvailable(builder::metricsSender);
return builder.build();
}
/**

View File

@@ -21,6 +21,7 @@ import java.util.concurrent.ScheduledExecutorService;
import io.micrometer.core.instrument.Clock;
import io.micrometer.registry.otlp.OtlpConfig;
import io.micrometer.registry.otlp.OtlpMeterRegistry;
import io.micrometer.registry.otlp.OtlpMetricsSender;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
@@ -132,6 +133,32 @@ class OtlpMetricsExportAutoConfigurationTests {
});
}
@Test
void allowsCustomMetricsSenderToBeUsed() {
this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(OtlpMeterRegistry.class);
OtlpMeterRegistry registry = context.getBean(OtlpMeterRegistry.class);
assertThat(registry).extracting("metricsSender")
.satisfies((sender) -> assertThat(sender)
.isSameAs(CustomMetricsSenderConfiguration.customMetricsSender));
});
}
@Test
@EnabledForJreRange(min = JRE.JAVA_21)
void allowsCustomMetricsSenderToBeUsedWithVirtualThreads() {
this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class)
.withPropertyValues("spring.threads.virtual.enabled=true")
.run((context) -> {
assertThat(context).hasSingleBean(OtlpMeterRegistry.class);
OtlpMeterRegistry registry = context.getBean(OtlpMeterRegistry.class);
assertThat(registry).extracting("metricsSender")
.satisfies((sender) -> assertThat(sender)
.isSameAs(CustomMetricsSenderConfiguration.customMetricsSender));
});
}
@Configuration(proxyBeanMethods = false)
static class BaseConfiguration {
@@ -174,4 +201,17 @@ class OtlpMetricsExportAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
static class CustomMetricsSenderConfiguration {
static OtlpMetricsSender customMetricsSender = (request) -> {
};
@Bean
OtlpMetricsSender customMetricsSender() {
return customMetricsSender;
}
}
}

View File

@@ -522,6 +522,8 @@ management:
Custom headers, for example for authentication, can also be provided using configprop:management.otlp.metrics.export.headers.*[] properties.
If an `OtlpMetricsSender` bean is available, it will be configured on the `OtlpMeterRegistry` that Spring Boot auto-configures.
[[actuator.metrics.export.prometheus]]