mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Polish "Prevent Micrometer global registry from pinning application contexts"
See gh-50886
This commit is contained in:
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.metrics;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.ContextCustomizerFactory;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ContextCustomizerFactory} to disable the use of Micrometer's
|
||||
* {@link io.micrometer.core.instrument.Metrics#globalRegistry global registry} in tests,
|
||||
* preventing {@link io.micrometer.core.instrument.MeterRegistry meter registries} from
|
||||
* pinning application contexts when many test contexts are cached.
|
||||
*/
|
||||
class DisableGlobalMeterRegistryContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
private static final String METRICS_CLASS = "io.micrometer.core.instrument.Metrics";
|
||||
|
||||
private static final String USE_GLOBAL_REGISTRY_PROPERTY = "management.metrics.use-global-registry";
|
||||
|
||||
@Override
|
||||
public @Nullable ContextCustomizer createContextCustomizer(Class<?> testClass,
|
||||
List<ContextConfigurationAttributes> configAttributes) {
|
||||
if (ClassUtils.isPresent(METRICS_CLASS, testClass.getClassLoader())) {
|
||||
return new DisableGlobalMeterRegistryContextCustomizer();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static final class DisableGlobalMeterRegistryContextCustomizer implements ContextCustomizer {
|
||||
|
||||
@Override
|
||||
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
ConfigurableEnvironment environment = context.getEnvironment();
|
||||
if (environment.getProperty(USE_GLOBAL_REGISTRY_PROPERTY) == null) {
|
||||
TestPropertyValues.of(USE_GLOBAL_REGISTRY_PROPERTY + "=false").applyTo(environment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return obj instanceof DisableGlobalMeterRegistryContextCustomizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Boot support for metrics testing.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.test.metrics;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -5,8 +5,7 @@ org.springframework.boot.test.context.PropertyMappingContextCustomizerFactory,\
|
||||
org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFactory,\
|
||||
org.springframework.boot.test.context.filter.annotation.TypeExcludeFiltersContextCustomizerFactory,\
|
||||
org.springframework.boot.test.http.client.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory,\
|
||||
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory,\
|
||||
org.springframework.boot.test.metrics.DisableGlobalMeterRegistryContextCustomizerFactory
|
||||
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory
|
||||
|
||||
# Application Context Initializers
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.metrics;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link DisableGlobalMeterRegistryContextCustomizerFactory}.
|
||||
*/
|
||||
class DisableGlobalMeterRegistryContextCustomizerFactoryTests {
|
||||
|
||||
@Test
|
||||
void disablesGlobalMeterRegistryByDefault() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.setEnvironment(new StandardEnvironment());
|
||||
new DisableGlobalMeterRegistryContextCustomizerFactory.DisableGlobalMeterRegistryContextCustomizer()
|
||||
.customizeContext(context, mock(MergedContextConfiguration.class));
|
||||
assertThat(context.getEnvironment().getProperty("management.metrics.use-global-registry"))
|
||||
.isEqualTo("false");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotOverrideExplicitProperty() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
TestPropertyValues.of("management.metrics.use-global-registry=true").applyTo(environment);
|
||||
context.setEnvironment(environment);
|
||||
new DisableGlobalMeterRegistryContextCustomizerFactory.DisableGlobalMeterRegistryContextCustomizer()
|
||||
.customizeContext(context, mock(MergedContextConfiguration.class));
|
||||
assertThat(context.getEnvironment().getProperty("management.metrics.use-global-registry"))
|
||||
.isEqualTo("true");
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.micrometer.metrics.autoconfigure;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
|
||||
/**
|
||||
* Ensures that {@link MeterRegistry meter registries} are closed early in the shutdown
|
||||
* process. Also unregisters the registries from the global registry if needed.
|
||||
*
|
||||
* @author Jon Schneider
|
||||
* @author Stephane Nicoll
|
||||
* @author Moritz Halbritter
|
||||
* @author Michael Berry
|
||||
* @author Phillip Webb
|
||||
* @author Lordwill Kandiro
|
||||
*/
|
||||
class MeterRegistryCloser implements ApplicationListener<ContextClosedEvent> {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
private final Set<MeterRegistry> registriesToClose = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final Set<MeterRegistry> registriesToRemoveFromGlobalRegistry = new CopyOnWriteArraySet<>();
|
||||
|
||||
MeterRegistryCloser(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
void track(MeterRegistry meterRegistry) {
|
||||
this.registriesToClose.add(meterRegistry);
|
||||
}
|
||||
|
||||
void trackAddedToGlobalRegistry(MeterRegistry meterRegistry) {
|
||||
this.registriesToRemoveFromGlobalRegistry.add(meterRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent event) {
|
||||
if (!this.context.equals(event.getApplicationContext())) {
|
||||
return;
|
||||
}
|
||||
for (MeterRegistry meterRegistry : this.registriesToRemoveFromGlobalRegistry) {
|
||||
Metrics.removeRegistry(meterRegistry);
|
||||
}
|
||||
for (MeterRegistry meterRegistry : this.registriesToClose) {
|
||||
if (!meterRegistry.isClosed()) {
|
||||
meterRegistry.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-7
@@ -54,17 +54,16 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
|
||||
|
||||
private final ObjectProvider<MeterBinder> binders;
|
||||
|
||||
private final ObjectProvider<MetricsAutoConfiguration.MeterRegistryCloser> meterRegistryCloser;
|
||||
private final ObjectProvider<MeterRegistryCloser> meterRegistryCloser;
|
||||
|
||||
private volatile boolean deferBinding = true;
|
||||
|
||||
private final Set<MeterRegistry> deferredBindings = new LinkedHashSet<>();
|
||||
|
||||
MeterRegistryPostProcessor(ApplicationContext applicationContext,
|
||||
ObjectProvider<MetricsProperties> metricsProperties,
|
||||
ObjectProvider<MeterRegistryCustomizer<?>> customizers, ObjectProvider<MeterFilter> filters,
|
||||
ObjectProvider<MeterBinder> binders,
|
||||
ObjectProvider<MetricsAutoConfiguration.MeterRegistryCloser> meterRegistryCloser) {
|
||||
ObjectProvider<MetricsProperties> metricsProperties, ObjectProvider<MeterRegistryCustomizer<?>> customizers,
|
||||
ObjectProvider<MeterFilter> filters, ObjectProvider<MeterBinder> binders,
|
||||
ObjectProvider<MeterRegistryCloser> meterRegistryCloser) {
|
||||
this(CompositeMeterRegistries.of(applicationContext), metricsProperties, customizers, filters, binders,
|
||||
meterRegistryCloser);
|
||||
}
|
||||
@@ -72,7 +71,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
|
||||
MeterRegistryPostProcessor(CompositeMeterRegistries compositeMeterRegistries,
|
||||
ObjectProvider<MetricsProperties> properties, ObjectProvider<MeterRegistryCustomizer<?>> customizers,
|
||||
ObjectProvider<MeterFilter> filters, ObjectProvider<MeterBinder> binders,
|
||||
ObjectProvider<MetricsAutoConfiguration.MeterRegistryCloser> meterRegistryCloser) {
|
||||
ObjectProvider<MeterRegistryCloser> meterRegistryCloser) {
|
||||
this.compositeMeterRegistries = compositeMeterRegistries;
|
||||
this.properties = properties;
|
||||
this.customizers = customizers;
|
||||
@@ -98,6 +97,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
|
||||
}
|
||||
|
||||
private void postProcessMeterRegistry(MeterRegistry meterRegistry) {
|
||||
this.meterRegistryCloser.getObject().track(meterRegistry);
|
||||
// Customizers must be applied before binders, as they may add custom tags or
|
||||
// alter timer or summary configuration.
|
||||
applyCustomizers(meterRegistry);
|
||||
@@ -129,7 +129,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
|
||||
private void addToGlobalRegistryIfNecessary(MeterRegistry meterRegistry) {
|
||||
if (this.properties.getObject().isUseGlobalRegistry() && !isGlobalRegistry(meterRegistry)) {
|
||||
Metrics.addRegistry(meterRegistry);
|
||||
this.meterRegistryCloser.getObject().track(meterRegistry);
|
||||
this.meterRegistryCloser.getObject().trackAddedToGlobalRegistry(meterRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-47
@@ -16,13 +16,9 @@
|
||||
|
||||
package org.springframework.boot.micrometer.metrics.autoconfigure;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.binder.MeterBinder;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
@@ -38,9 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationHandlerGroup;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -81,8 +75,8 @@ public final class MetricsAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
MeterRegistryCloser meterRegistryCloser(ApplicationContext context, MetricsProperties properties) {
|
||||
return new MeterRegistryCloser(context, properties.isUseGlobalRegistry());
|
||||
MeterRegistryCloser meterRegistryCloser(ApplicationContext context) {
|
||||
return new MeterRegistryCloser(context);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -98,43 +92,4 @@ public final class MetricsAutoConfiguration {
|
||||
properties.getObservations().getIgnoredMeters().toArray(IgnoredMeters[]::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that {@link MeterRegistry meter registries} are closed early in the
|
||||
* shutdown process.
|
||||
*/
|
||||
static class MeterRegistryCloser implements ApplicationListener<ContextClosedEvent> {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
private final boolean useGlobalRegistry;
|
||||
|
||||
private final Set<MeterRegistry> trackedRegistries = new LinkedHashSet<>();
|
||||
|
||||
MeterRegistryCloser(ApplicationContext context, boolean useGlobalRegistry) {
|
||||
this.context = context;
|
||||
this.useGlobalRegistry = useGlobalRegistry;
|
||||
}
|
||||
|
||||
void track(MeterRegistry meterRegistry) {
|
||||
this.trackedRegistries.add(meterRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent event) {
|
||||
if (this.context.equals(event.getApplicationContext())) {
|
||||
Set<MeterRegistry> meterRegistries = new LinkedHashSet<>(this.trackedRegistries);
|
||||
meterRegistries.addAll(this.context.getBeansOfType(MeterRegistry.class).values());
|
||||
for (MeterRegistry meterRegistry : meterRegistries) {
|
||||
if (this.useGlobalRegistry) {
|
||||
Metrics.globalRegistry.remove(meterRegistry);
|
||||
}
|
||||
if (!meterRegistry.isClosed()) {
|
||||
meterRegistry.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.micrometer.metrics.autoconfigure;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
||||
/**
|
||||
* Tests for {@link MeterRegistryCloser}.
|
||||
*
|
||||
* @author Lordwill Kandiro
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class MeterRegistryCloserTests {
|
||||
|
||||
private final ApplicationContext context = mock(ApplicationContext.class);
|
||||
|
||||
@Test
|
||||
void trackedRegistryIsRemovedFromGlobalRegistryOnContextClosedEvent() {
|
||||
MeterRegistry meterRegistry = new SimpleMeterRegistry();
|
||||
MeterRegistryCloser closer = new MeterRegistryCloser(this.context);
|
||||
try {
|
||||
Metrics.addRegistry(meterRegistry);
|
||||
closer.trackAddedToGlobalRegistry(meterRegistry);
|
||||
closer.onApplicationEvent(new ContextClosedEvent(this.context));
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(meterRegistry);
|
||||
}
|
||||
finally {
|
||||
Metrics.removeRegistry(meterRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void trackedRegistryIsClosedOnContextClosedEvent() {
|
||||
MeterRegistry meterRegistry = new SimpleMeterRegistry();
|
||||
MeterRegistryCloser closer = new MeterRegistryCloser(this.context);
|
||||
closer.track(meterRegistry);
|
||||
closer.onApplicationEvent(new ContextClosedEvent(this.context));
|
||||
assertThat(meterRegistry.isClosed()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void trackedRegistriesAreClosedInTheOrderThatTheyWereTracked() {
|
||||
MeterRegistry first = mock(MeterRegistry.class);
|
||||
MeterRegistry second = mock(MeterRegistry.class);
|
||||
MeterRegistry third = mock(MeterRegistry.class);
|
||||
MeterRegistryCloser closer = new MeterRegistryCloser(this.context);
|
||||
closer.track(first);
|
||||
closer.track(second);
|
||||
closer.track(third);
|
||||
closer.onApplicationEvent(new ContextClosedEvent(this.context));
|
||||
InOrder ordered = inOrder(first, second, third);
|
||||
then(first).should(ordered).close();
|
||||
then(second).should(ordered).close();
|
||||
then(third).should(ordered).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void alreadyClosedRegistryIsNotClosedAgain() {
|
||||
MeterRegistry meterRegistry = mock(MeterRegistry.class);
|
||||
given(meterRegistry.isClosed()).willReturn(true);
|
||||
MeterRegistryCloser closer = new MeterRegistryCloser(this.context);
|
||||
closer.track(meterRegistry);
|
||||
closer.onApplicationEvent(new ContextClosedEvent(this.context));
|
||||
then(meterRegistry).should(never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void onApplicationEventIgnoresEventsFromOtherContexts() {
|
||||
MeterRegistry meterRegistry = new SimpleMeterRegistry();
|
||||
MeterRegistryCloser closer = new MeterRegistryCloser(this.context);
|
||||
try {
|
||||
Metrics.addRegistry(meterRegistry);
|
||||
closer.track(meterRegistry);
|
||||
closer.trackAddedToGlobalRegistry(meterRegistry);
|
||||
ApplicationContext otherContext = mock(ApplicationContext.class);
|
||||
closer.onApplicationEvent(new ContextClosedEvent(otherContext));
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).contains(meterRegistry);
|
||||
assertThat(meterRegistry.isClosed()).isFalse();
|
||||
}
|
||||
finally {
|
||||
Metrics.removeRegistry(meterRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+55
-28
@@ -39,9 +39,9 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.micrometer.metrics.MaximumAllowableTagsMeterFilter;
|
||||
import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration.MeterRegistryCloser;
|
||||
import org.springframework.boot.micrometer.metrics.autoconfigure.MeterRegistryPostProcessor.CompositeMeterRegistries;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -86,12 +86,13 @@ class MeterRegistryPostProcessorTests {
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private Config mockConfig;
|
||||
|
||||
private final MetricsAutoConfiguration.MeterRegistryCloser meterRegistryCloser;
|
||||
private final ApplicationContext meterRegistryCloserContext = mock(ApplicationContext.class);
|
||||
|
||||
private final MeterRegistryCloser meterRegistryCloser;
|
||||
|
||||
MeterRegistryPostProcessorTests() {
|
||||
this.properties.setUseGlobalRegistry(false);
|
||||
this.meterRegistryCloser = new MetricsAutoConfiguration.MeterRegistryCloser(
|
||||
mock(ApplicationContext.class), true);
|
||||
this.meterRegistryCloser = new MeterRegistryCloser(this.meterRegistryCloserContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -111,7 +112,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.customizers.add(this.mockCustomizer);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.AUTO_CONFIGURED,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createEmptyObjectProvider(), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createEmptyObjectProvider(), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
AutoConfiguredCompositeMeterRegistry composite = new AutoConfiguredCompositeMeterRegistry(Clock.SYSTEM,
|
||||
Collections.emptyList());
|
||||
postProcessAndInitialize(processor, composite);
|
||||
@@ -124,7 +126,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.customizers.add(this.mockCustomizer);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
then(this.mockCustomizer).should().customize(this.mockRegistry);
|
||||
}
|
||||
@@ -135,7 +138,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.filters.add(this.mockFilter);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
then(this.mockConfig).should().meterFilter(this.mockFilter);
|
||||
}
|
||||
@@ -147,7 +151,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.filters.add(onlyOnceFilter);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.AUTO_CONFIGURED,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
AutoConfiguredCompositeMeterRegistry composite = new AutoConfiguredCompositeMeterRegistry(Clock.SYSTEM,
|
||||
Collections.emptyList());
|
||||
postProcessAndInitialize(processor, composite);
|
||||
@@ -162,7 +167,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.binders.add(this.mockBinder);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
then(this.mockBinder).should().bindTo(this.mockRegistry);
|
||||
}
|
||||
@@ -184,8 +190,8 @@ class MeterRegistryPostProcessorTests {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(
|
||||
CompositeMeterRegistries.ONLY_USER_DEFINED, createObjectProvider(this.properties),
|
||||
createObjectProvider(this.customizers), createObjectProvider(this.filters),
|
||||
createEmptyObjectProvider(), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.customizers), createObjectProvider(this.filters), createEmptyObjectProvider(),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
then(this.mockBinder).shouldHaveNoInteractions();
|
||||
}
|
||||
@@ -195,7 +201,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.binders.add(this.mockBinder);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.AUTO_CONFIGURED,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createEmptyObjectProvider(), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createEmptyObjectProvider(), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
AutoConfiguredCompositeMeterRegistry composite = new AutoConfiguredCompositeMeterRegistry(Clock.SYSTEM,
|
||||
Collections.emptyList());
|
||||
postProcessAndInitialize(processor, composite);
|
||||
@@ -207,7 +214,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.binders.add(this.mockBinder);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.AUTO_CONFIGURED,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createEmptyObjectProvider(), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createEmptyObjectProvider(),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
CompositeMeterRegistry composite = new CompositeMeterRegistry();
|
||||
postProcessAndInitialize(processor, composite);
|
||||
then(this.mockBinder).shouldHaveNoInteractions();
|
||||
@@ -218,7 +226,8 @@ class MeterRegistryPostProcessorTests {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.AUTO_CONFIGURED,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createEmptyObjectProvider(), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createEmptyObjectProvider(),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
then(this.mockBinder).shouldHaveNoInteractions();
|
||||
}
|
||||
@@ -231,7 +240,8 @@ class MeterRegistryPostProcessorTests {
|
||||
this.binders.add(this.mockBinder);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
InOrder ordered = inOrder(this.mockBinder, this.mockConfig, this.mockCustomizer);
|
||||
then(this.mockCustomizer).should(ordered).customize(this.mockRegistry);
|
||||
@@ -240,15 +250,16 @@ class MeterRegistryPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void trackedRegistryIsRemovedFromGlobalRegistryOnContextClosedEvent() {
|
||||
ApplicationContext applicationContext = mock(ApplicationContext.class);
|
||||
MetricsAutoConfiguration.MeterRegistryCloser closer = new MetricsAutoConfiguration.MeterRegistryCloser(
|
||||
applicationContext, true);
|
||||
void postProcessAndInitializeWhenUseGlobalRegistryTrueAddsToGlobalRegistry() {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
this.properties.setUseGlobalRegistry(true);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
try {
|
||||
Metrics.addRegistry(this.mockRegistry);
|
||||
closer.track(this.mockRegistry);
|
||||
closer.onApplicationEvent(new org.springframework.context.event.ContextClosedEvent(applicationContext));
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(this.mockRegistry);
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).contains(this.mockRegistry);
|
||||
}
|
||||
finally {
|
||||
Metrics.removeRegistry(this.mockRegistry);
|
||||
@@ -256,15 +267,17 @@ class MeterRegistryPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessAndInitializeWhenUseGlobalRegistryTrueAddsToGlobalRegistry() {
|
||||
void addToGlobalRegistryIfNecessaryTracksRegistryWithMeterRegistryCloser() {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
this.properties.setUseGlobalRegistry(true);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
try {
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).contains(this.mockRegistry);
|
||||
this.meterRegistryCloser.onApplicationEvent(new ContextClosedEvent(this.meterRegistryCloserContext));
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(this.mockRegistry);
|
||||
}
|
||||
finally {
|
||||
Metrics.removeRegistry(this.mockRegistry);
|
||||
@@ -276,18 +289,32 @@ class MeterRegistryPostProcessorTests {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(this.mockRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessMeterRegistryTracksRegistryForClosingWithMeterRegistryCloser() {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
postProcessAndInitialize(processor, this.mockRegistry);
|
||||
this.meterRegistryCloser.onApplicationEvent(new ContextClosedEvent(this.meterRegistryCloserContext));
|
||||
then(this.mockRegistry).should().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void postProcessDoesNotBindToUntilSingletonsInitialized() {
|
||||
given(this.mockRegistry.config()).willReturn(this.mockConfig);
|
||||
this.binders.add(this.mockBinder);
|
||||
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(CompositeMeterRegistries.NONE,
|
||||
createObjectProvider(this.properties), createObjectProvider(this.customizers),
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders), createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
createObjectProvider(this.filters), createObjectProvider(this.binders),
|
||||
createMeterRegistryCloserProvider(this.meterRegistryCloser));
|
||||
processor.postProcessAfterInitialization(this.mockRegistry, "meterRegistry");
|
||||
then(this.mockBinder).shouldHaveNoInteractions();
|
||||
processor.afterSingletonsInstantiated();
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ import io.micrometer.observation.ObservationHandler;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration.MeterRegistryCloser;
|
||||
import org.springframework.boot.micrometer.observation.autoconfigure.ObservationHandlerGroup;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
Reference in New Issue
Block a user