Close meter registries early in the shutdown process

Closes gh-38240
This commit is contained in:
Moritz Halbritter 2023-11-16 09:05:14 +01:00
parent 50bce029e2
commit d8ce901011
2 changed files with 51 additions and 0 deletions

View File

@ -16,8 +16,11 @@
package org.springframework.boot.actuate.autoconfigure.metrics;
import java.util.List;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import io.micrometer.core.instrument.config.MeterFilter;
@ -28,7 +31,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.annotation.Order;
/**
@ -36,6 +41,7 @@ import org.springframework.core.annotation.Order;
*
* @author Jon Schneider
* @author Stephane Nicoll
* @author Moritz Halbritter
* @since 2.0.0
*/
@AutoConfiguration(before = CompositeMeterRegistryAutoConfiguration.class)
@ -64,4 +70,32 @@ public class MetricsAutoConfiguration {
return new PropertiesMeterFilter(properties);
}
@Bean
MeterRegistryCloser meterRegistryCloser(ObjectProvider<MeterRegistry> meterRegistries) {
return new MeterRegistryCloser(meterRegistries.orderedStream().toList());
}
/**
* Ensures that {@link MeterRegistry meter registries} are closed early in the
* shutdown process.
*/
static class MeterRegistryCloser implements ApplicationListener<ContextClosedEvent> {
private final List<MeterRegistry> meterRegistries;
MeterRegistryCloser(List<MeterRegistry> meterRegistries) {
this.meterRegistries = meterRegistries;
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
for (MeterRegistry meterRegistry : this.meterRegistries) {
if (!meterRegistry.isClosed()) {
meterRegistry.close();
}
}
}
}
}

View File

@ -25,6 +25,7 @@ import io.micrometer.core.instrument.config.MeterFilterReply;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration.MeterRegistryCloser;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
@ -40,6 +41,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link MetricsAutoConfiguration}.
*
* @author Andy Wilkinson
* @author Moritz Halbritter
*/
class MetricsAutoConfigurationTests {
@ -72,6 +74,21 @@ class MetricsAutoConfigurationTests {
});
}
@Test
void shouldSupplyMeterRegistryCloser() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(MeterRegistryCloser.class));
}
@Test
void meterRegistryCloserShouldCloseRegistryOnShutdown() {
this.contextRunner.withUserConfiguration(MeterRegistryConfiguration.class).run((context) -> {
MeterRegistry meterRegistry = context.getBean(MeterRegistry.class);
assertThat(meterRegistry.isClosed()).isFalse();
context.close();
assertThat(meterRegistry.isClosed()).isTrue();
});
}
@Configuration(proxyBeanMethods = false)
static class CustomClockConfiguration {