Polish '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:
Phillip Webb 2025-04-15 09:55:59 -07:00
parent 776d233c1c
commit 15c54b4065
2 changed files with 21 additions and 25 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.otlp;
import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Clock;
import io.micrometer.registry.otlp.OtlpConfig; import io.micrometer.registry.otlp.OtlpConfig;
import io.micrometer.registry.otlp.OtlpMeterRegistry; import io.micrometer.registry.otlp.OtlpMeterRegistry;
import io.micrometer.registry.otlp.OtlpMeterRegistry.Builder;
import io.micrometer.registry.otlp.OtlpMetricsSender; import io.micrometer.registry.otlp.OtlpMetricsSender;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
@ -81,9 +80,7 @@ public class OtlpMetricsExportAutoConfiguration {
@ConditionalOnThreading(Threading.PLATFORM) @ConditionalOnThreading(Threading.PLATFORM)
public OtlpMeterRegistry otlpMeterRegistry(OtlpConfig otlpConfig, Clock clock, public OtlpMeterRegistry otlpMeterRegistry(OtlpConfig otlpConfig, Clock clock,
ObjectProvider<OtlpMetricsSender> metricsSender) { ObjectProvider<OtlpMetricsSender> metricsSender) {
Builder builder = OtlpMeterRegistry.builder(otlpConfig).clock(clock); return builder(otlpConfig, clock, metricsSender).build();
metricsSender.ifAvailable(builder::metricsSender);
return builder.build();
} }
@Bean @Bean
@ -91,12 +88,15 @@ public class OtlpMetricsExportAutoConfiguration {
@ConditionalOnThreading(Threading.VIRTUAL) @ConditionalOnThreading(Threading.VIRTUAL)
public OtlpMeterRegistry otlpMeterRegistryVirtualThreads(OtlpConfig otlpConfig, Clock clock, public OtlpMeterRegistry otlpMeterRegistryVirtualThreads(OtlpConfig otlpConfig, Clock clock,
ObjectProvider<OtlpMetricsSender> metricsSender) { ObjectProvider<OtlpMetricsSender> metricsSender) {
VirtualThreadTaskExecutor taskExecutor = new VirtualThreadTaskExecutor("otlp-meter-registry-"); VirtualThreadTaskExecutor executor = new VirtualThreadTaskExecutor("otlp-meter-registry-");
Builder builder = OtlpMeterRegistry.builder(otlpConfig) return builder(otlpConfig, clock, metricsSender).threadFactory(executor.getVirtualThreadFactory()).build();
.clock(clock) }
.threadFactory(taskExecutor.getVirtualThreadFactory());
private OtlpMeterRegistry.Builder builder(OtlpConfig otlpConfig, Clock clock,
ObjectProvider<OtlpMetricsSender> metricsSender) {
OtlpMeterRegistry.Builder builder = OtlpMeterRegistry.builder(otlpConfig).clock(clock);
metricsSender.ifAvailable(builder::metricsSender); metricsSender.ifAvailable(builder::metricsSender);
return builder.build(); return builder;
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.junit.jupiter.api.condition.JRE;
import org.springframework.boot.actuate.autoconfigure.metrics.export.otlp.OtlpMetricsExportAutoConfiguration.PropertiesOtlpMetricsConnectionDetails; import org.springframework.boot.actuate.autoconfigure.metrics.export.otlp.OtlpMetricsExportAutoConfiguration.PropertiesOtlpMetricsConnectionDetails;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.assertj.ScheduledExecutorServiceAssert; import org.springframework.boot.testsupport.assertj.ScheduledExecutorServiceAssert;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -136,13 +137,7 @@ class OtlpMetricsExportAutoConfigurationTests {
@Test @Test
void allowsCustomMetricsSenderToBeUsed() { void allowsCustomMetricsSenderToBeUsed() {
this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class) this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class)
.run((context) -> { .run(this::assertHasCustomMetricsSender);
assertThat(context).hasSingleBean(OtlpMeterRegistry.class);
OtlpMeterRegistry registry = context.getBean(OtlpMeterRegistry.class);
assertThat(registry).extracting("metricsSender")
.satisfies((sender) -> assertThat(sender)
.isSameAs(CustomMetricsSenderConfiguration.customMetricsSender));
});
} }
@Test @Test
@ -150,13 +145,14 @@ class OtlpMetricsExportAutoConfigurationTests {
void allowsCustomMetricsSenderToBeUsedWithVirtualThreads() { void allowsCustomMetricsSenderToBeUsedWithVirtualThreads() {
this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class) this.contextRunner.withUserConfiguration(BaseConfiguration.class, CustomMetricsSenderConfiguration.class)
.withPropertyValues("spring.threads.virtual.enabled=true") .withPropertyValues("spring.threads.virtual.enabled=true")
.run((context) -> { .run(this::assertHasCustomMetricsSender);
assertThat(context).hasSingleBean(OtlpMeterRegistry.class); }
OtlpMeterRegistry registry = context.getBean(OtlpMeterRegistry.class);
assertThat(registry).extracting("metricsSender") private void assertHasCustomMetricsSender(AssertableApplicationContext context) {
.satisfies((sender) -> assertThat(sender) assertThat(context).hasSingleBean(OtlpMeterRegistry.class);
.isSameAs(CustomMetricsSenderConfiguration.customMetricsSender)); OtlpMeterRegistry registry = context.getBean(OtlpMeterRegistry.class);
}); assertThat(registry).extracting("metricsSender")
.satisfies((sender) -> assertThat(sender).isSameAs(CustomMetricsSenderConfiguration.customMetricsSender));
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)