Skip to content

Commit

Permalink
Avoid eager initialization when configuring Data repository metrics
Browse files Browse the repository at this point in the history
Fixes gh-26630
  • Loading branch information
wilkinsona committed May 21, 2021
1 parent 3a28aee commit 7a70508
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
Expand Up @@ -16,6 +16,8 @@

package org.springframework.boot.actuate.autoconfigure.metrics.data;

import java.util.function.Supplier;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.metrics.data.MetricsRepositoryMethodInvocationListener;
Expand All @@ -33,8 +35,9 @@ class MetricsRepositoryMethodInvocationListenerBeanPostProcessor implements Bean

private final RepositoryFactoryCustomizer customizer;

MetricsRepositoryMethodInvocationListenerBeanPostProcessor(MetricsRepositoryMethodInvocationListener listener) {
this.customizer = (repositoryFactory) -> repositoryFactory.addInvocationListener(listener);
MetricsRepositoryMethodInvocationListenerBeanPostProcessor(
Supplier<MetricsRepositoryMethodInvocationListener> listener) {
this.customizer = new MetricsRepositoryFactoryCustomizer(listener);
}

@Override
Expand All @@ -45,4 +48,25 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
return bean;
}

private static final class MetricsRepositoryFactoryCustomizer implements RepositoryFactoryCustomizer {

private final Supplier<MetricsRepositoryMethodInvocationListener> listenerSupplier;

private volatile MetricsRepositoryMethodInvocationListener listener;

private MetricsRepositoryFactoryCustomizer(
Supplier<MetricsRepositoryMethodInvocationListener> listenerSupplier) {
this.listenerSupplier = listenerSupplier;
}

@Override
public void customize(RepositoryFactorySupport repositoryFactory) {
if (this.listener == null) {
this.listener = this.listenerSupplier.get();
}
repositoryFactory.addInvocationListener(this.listener);
}

}

}
Expand Up @@ -18,6 +18,7 @@

import io.micrometer.core.instrument.MeterRegistry;

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.MetricsProperties;
Expand Down Expand Up @@ -72,9 +73,9 @@ public MetricsRepositoryMethodInvocationListener metricsRepositoryMethodInvocati

@Bean
public static MetricsRepositoryMethodInvocationListenerBeanPostProcessor metricsRepositoryMethodInvocationListenerBeanPostProcessor(
MetricsRepositoryMethodInvocationListener metricsRepositoryMethodInvocationListener) {
ObjectProvider<MetricsRepositoryMethodInvocationListener> metricsRepositoryMethodInvocationListener) {
return new MetricsRepositoryMethodInvocationListenerBeanPostProcessor(
metricsRepositoryMethodInvocationListener);
metricsRepositoryMethodInvocationListener::getObject);
}

}
Expand Up @@ -38,7 +38,7 @@ class MetricsRepositoryMethodInvocationListenerBeanPostProcessorTests {
private MetricsRepositoryMethodInvocationListener listener = mock(MetricsRepositoryMethodInvocationListener.class);

private MetricsRepositoryMethodInvocationListenerBeanPostProcessor postProcessor = new MetricsRepositoryMethodInvocationListenerBeanPostProcessor(
this.listener);
() -> this.listener);

@Test
@SuppressWarnings("rawtypes")
Expand Down
Expand Up @@ -24,6 +24,7 @@
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.binder.MeterBinder;
import io.micrometer.core.instrument.distribution.HistogramSnapshot;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -125,6 +126,13 @@ void timerWorksWithTimedAnnotationsWhenAutoTimeRequestsIsFalse() {
});
}

@Test
void doesNotTriggerEarlyInitializationThatPreventsMeterBindersFromBindingMeters() {
this.contextRunner.withUserConfiguration(MeterBinderConfiguration.class)
.run((context) -> assertThat(context.getBean(MeterRegistry.class).find("binder.test").counter())
.isNotNull());
}

private MeterRegistry getInitializedMeterRegistry(AssertableApplicationContext context,
Class<?> repositoryInterface) {
MetricsRepositoryMethodInvocationListener listener = context
Expand Down Expand Up @@ -158,6 +166,16 @@ public Iterable<Tag> repositoryTags(RepositoryMethodInvocation invocation) {

}

@Configuration(proxyBeanMethods = false)
static class MeterBinderConfiguration {

@Bean
MeterBinder meterBinder() {
return (registry) -> registry.counter("binder.test");
}

}

@Configuration(proxyBeanMethods = false)
static class MetricsRepositoryMethodInvocationListenerConfiguration {

Expand Down

0 comments on commit 7a70508

Please sign in to comment.