From 9a8c182d198e8e339aa6b775ab5ee9bcf1612aec Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 26 Jan 2018 21:01:00 -0800 Subject: [PATCH] Only use micrometer composites when necessary Update micrometer auto-configuration so that a `CompositeMeterRegistry` is only created when more than one `MeterRegistry` bean is declared. When a composite is crated, it is marked as `@Primary` so that it can be directly injected. Meter registries can now be defined directly as beans, and auto-configuration can back off in the usual way. The `MeterRegistryConfigurer` is now called `MeterRegistryCustomizer` and is generically types so it's easy to apply customizations to a particular `MeterRegistry` implementation. Fixes gh-11799 Co-authored-by: Jon Schneider --- .../metrics/MeterRegistriesConfiguration.java | 44 +++++ ...urer.java => MeterRegistryCustomizer.java} | 13 +- .../metrics/MeterRegistryPostProcessor.java | 94 +++++++++ .../metrics/MetricsAutoConfiguration.java | 71 ++----- ... CompositeMeterRegistryConfiguration.java} | 22 +-- .../CompositeMeterRegistryPostProcessor.java | 122 ++++++++++++ .../atlas/AtlasExportConfiguration.java | 13 +- .../datadog/DatadogExportConfiguration.java | 14 +- .../ganglia/GangliaExportConfiguration.java | 11 +- .../graphite/GraphiteExportConfiguration.java | 11 +- .../influx/InfluxExportConfiguration.java | 14 +- .../export/jmx/JmxExportConfiguration.java | 11 +- .../PrometheusExportConfiguration.java | 17 +- .../simple/SimpleExportConfiguration.java | 16 +- .../statsd/StatsdExportConfiguration.java | 13 +- .../SpringApplicationHierarchyTests.java | 11 +- ...java => MeterRegistryCustomizerTests.java} | 37 ++-- .../MeterRegistryPostProcessorTests.java | 184 ++++++++++++++++++ ...ricsAutoConfigurationIntegrationTests.java | 2 + .../MetricsConfigurationCompositeTests.java | 47 ----- ...positeMeterRegistryConfigurationTests.java | 111 +++++++++++ ...positeMeterRegistryPostProcessorTests.java | 134 +++++++++++++ .../SimpleExportConfigurationTests.java | 61 ------ 23 files changed, 788 insertions(+), 285 deletions(-) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistriesConfiguration.java rename spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/{MeterRegistryConfigurer.java => MeterRegistryCustomizer.java} (73%) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.java rename spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/{MetricsExporter.java => CompositeMeterRegistryConfiguration.java} (59%) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessor.java rename spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/{MeterRegistryConfigurerTests.java => MeterRegistryCustomizerTests.java} (59%) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessorTests.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsConfigurationCompositeTests.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfigurationTests.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessorTests.java delete mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfigurationTests.java diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistriesConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistriesConfiguration.java new file mode 100644 index 0000000000..f189d39f7a --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistriesConfiguration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics; + +import org.springframework.boot.actuate.autoconfigure.metrics.export.atlas.AtlasExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.datadog.DatadogExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.ganglia.GangliaExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.graphite.GraphiteExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.influx.InfluxExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.jmx.JmxExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdExportConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * Imports for registry configurations. + * + * @author Jon Schneider + */ +@Configuration +@Import({ AtlasExportConfiguration.class, DatadogExportConfiguration.class, + GangliaExportConfiguration.class, GraphiteExportConfiguration.class, + InfluxExportConfiguration.class, JmxExportConfiguration.class, + PrometheusExportConfiguration.class, SimpleExportConfiguration.class, + StatsdExportConfiguration.class }) +class MeterRegistriesConfiguration { + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizer.java similarity index 73% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurer.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizer.java index a12b27f636..0f1775d117 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -23,19 +23,20 @@ import io.micrometer.core.instrument.MeterRegistry; * Callback interface that can be used to customize auto-configured {@link MeterRegistry * MeterRegistries}. *

- * Configurers are guaranteed to be applied before any {@link Meter} is registered with + * Customizers are guaranteed to be applied before any {@link Meter} is registered with * the registry. * * @author Jon Schneider + * @param The registry type to customize * @since 2.0.0 */ @FunctionalInterface -public interface MeterRegistryConfigurer { +public interface MeterRegistryCustomizer { /** - * Configure the given {@code registry}. - * @param registry the registry to configure + * Customize the given {@code registry}. + * @param registry the registry to customize */ - void configureRegistry(MeterRegistry registry); + void customize(T registry); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.java new file mode 100644 index 0000000000..d7de4d0a58 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.java @@ -0,0 +1,94 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics; + +import java.util.Collection; +import java.util.Collections; + +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 org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.util.LambdaSafe; + +/** + * {@link BeanPostProcessor} to apply {@link MeterRegistryCustomizer customizers} and + * {@link MeterBinder binters} and {@link Metrics#addRegistry global registration} to + * {@link MeterRegistry meter registries}. This post processor intentionally skips + * {@link CompositeMeterRegistry} with the assumptions that the registries it contains are + * beans and will be customized directly. + * + * @author Jon Schneider + * @author Phillip Webb + */ +class MeterRegistryPostProcessor implements BeanPostProcessor { + + private final Collection> customizers; + + private final Collection binders; + + private final boolean addToGlobalRegistry; + + MeterRegistryPostProcessor(ObjectProvider> binders, + ObjectProvider>> customizers, + boolean addToGlobalRegistry) { + this.binders = binders.getIfAvailable(Collections::emptyList); + this.customizers = customizers.getIfAvailable(Collections::emptyList); + this.addToGlobalRegistry = addToGlobalRegistry; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof MeterRegistry) { + postProcess((MeterRegistry) bean); + } + return bean; + } + + private void postProcess(MeterRegistry registry) { + if (registry instanceof CompositeMeterRegistry) { + return; + } + // Customizers must be applied before binders, as they may add custom tags or + // alter timer or summary configuration. + customize(registry); + addBinders(registry); + if (this.addToGlobalRegistry && registry != Metrics.globalRegistry) { + Metrics.addRegistry(registry); + } + } + + @SuppressWarnings("unchecked") + private void customize(MeterRegistry registry) { + LambdaSafe.callbacks(MeterRegistryCustomizer.class, this.customizers, registry) + .withLogger(MeterRegistryPostProcessor.class) + .invoke((customizer) -> customizer.customize(registry)); + } + + private void addBinders(MeterRegistry registry) { + this.binders.forEach((binder) -> binder.bindTo(registry)); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.java index 541f1b6037..ff31bc4ec7 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.java @@ -17,28 +17,17 @@ package org.springframework.boot.actuate.autoconfigure.metrics; import java.util.Collection; -import java.util.Collections; 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 org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.autoconfigure.metrics.amqp.RabbitMetricsConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; -import org.springframework.boot.actuate.autoconfigure.metrics.export.atlas.AtlasExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.datadog.DatadogExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.ganglia.GangliaExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.graphite.GraphiteExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.influx.InfluxExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.jmx.JmxExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleExportConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdExportConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.export.CompositeMeterRegistryConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.reactive.server.WebFluxMetricsConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.client.RestTemplateMetricsConfiguration; @@ -61,14 +50,13 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.integration.config.EnableIntegrationManagement; import org.springframework.integration.support.management.IntegrationManagementConfigurer; -import org.springframework.util.Assert; /** * {@link EnableAutoConfiguration Auto-configuration} for Micrometer-based metrics. * - * @since 2.0.0 * @author Jon Schneider * @author Stephane Nicoll + * @since 2.0.0 */ @Configuration @ConditionalOnClass(Timed.class) @@ -76,32 +64,19 @@ import org.springframework.util.Assert; @Import({ MeterBindersConfiguration.class, WebMvcMetricsConfiguration.class, WebFluxMetricsConfiguration.class, RestTemplateMetricsConfiguration.class, CacheMetricsConfiguration.class, DataSourcePoolMetricsConfiguration.class, - RabbitMetricsConfiguration.class, AtlasExportConfiguration.class, - DatadogExportConfiguration.class, GangliaExportConfiguration.class, - GraphiteExportConfiguration.class, InfluxExportConfiguration.class, - JmxExportConfiguration.class, PrometheusExportConfiguration.class, - SimpleExportConfiguration.class, StatsdExportConfiguration.class }) + RabbitMetricsConfiguration.class, MeterRegistriesConfiguration.class, + CompositeMeterRegistryConfiguration.class }) @AutoConfigureAfter({ CacheAutoConfiguration.class, DataSourceAutoConfiguration.class, RabbitAutoConfiguration.class, RestTemplateAutoConfiguration.class }) public class MetricsAutoConfiguration { @Bean - @ConditionalOnMissingBean(MeterRegistry.class) - public CompositeMeterRegistry compositeMeterRegistry( - MetricsProperties metricsProperties, - ObjectProvider> exporters, - ObjectProvider> configurers) { - CompositeMeterRegistry composite = metricsProperties.isUseGlobalRegistry() - ? Metrics.globalRegistry : new CompositeMeterRegistry(); - configurers.getIfAvailable(Collections::emptyList) - .forEach((configurer) -> configurer.configureRegistry(composite)); - exporters.getIfAvailable(Collections::emptyList).forEach((exporter) -> { - MeterRegistry childRegistry = exporter.registry(); - Assert.state(composite != childRegistry, - "cannot add a CompositeMeterRegistry to itself"); - composite.add(childRegistry); - }); - return composite; + public static MeterRegistryPostProcessor meterRegistryPostProcessor( + ObjectProvider> binders, + ObjectProvider>> customizers, + MetricsProperties properties) { + return new MeterRegistryPostProcessor(binders, customizers, + properties.isUseGlobalRegistry()); } @Bean @@ -112,6 +87,15 @@ public class MetricsAutoConfiguration { return new MetricsEndpoint(registry); } + @Bean + @ConditionalOnMissingBean + public Clock micrometerClock() { + return Clock.SYSTEM; + } + + /** + * Binds metrics from Spring Integration. + */ @Configuration @ConditionalOnClass(EnableIntegrationManagement.class) static class MetricsIntegrationConfiguration { @@ -133,19 +117,4 @@ public class MetricsAutoConfiguration { } - @Configuration - static class MeterRegistryConfigurationSupport { - - MeterRegistryConfigurationSupport(MeterRegistry registry, - MetricsProperties config, - ObjectProvider> binders) { - binders.getIfAvailable(Collections::emptyList) - .forEach((binder) -> binder.bindTo(registry)); - if (config.isUseGlobalRegistry() && registry != Metrics.globalRegistry) { - Metrics.addRegistry(registry); - } - } - - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/MetricsExporter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfiguration.java similarity index 59% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/MetricsExporter.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfiguration.java index a2f280bf31..babed24cd0 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/MetricsExporter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -16,23 +16,21 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export; -import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; /** - * A {@code MetricsExporter} can be used to export metrics, typically to an external - * server running as a separate process. + * Conditionally build a composite registry when more than one registry present. * * @author Jon Schneider - * @author Andy Wilkinson * @since 2.0.0 */ -@FunctionalInterface -public interface MetricsExporter { +@Configuration +public class CompositeMeterRegistryConfiguration { - /** - * Returns the {@link MeterRegistry} used to register metrics with the exporter. - * @return the meter registry - */ - MeterRegistry registry(); + @Bean + public static CompositeMeterRegistryPostProcessor compositeMeterRegistryPostProcessor() { + return new CompositeMeterRegistryPostProcessor(); + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessor.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessor.java new file mode 100644 index 0000000000..bab5c1f361 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessor.java @@ -0,0 +1,122 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics.export; + +import java.util.Arrays; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.util.ObjectUtils; + +/** + * {@link BeanFactoryPostProcessor} to register a {@link CompositeMeterRegistry} when + * necessary. + * + * @author Jon Schneider + * @author Phillip Webb + */ +@Order(Ordered.LOWEST_PRECEDENCE - 1) +class CompositeMeterRegistryPostProcessor + implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware { + + private static final String COMPOSITE_BEAN_NAME = "compositeMeterRegistry"; + + private ConfigurableListableBeanFactory beanFactory; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + if (beanFactory instanceof ConfigurableListableBeanFactory) { + this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; + } + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) + throws BeansException { + if (this.beanFactory == null) { + return; + } + String[] registryBeans = this.beanFactory.getBeanNamesForType(MeterRegistry.class, + true, false); + registerCompositeIfNecessary(registry, registryBeans); + } + + private void registerCompositeIfNecessary(BeanDefinitionRegistry registry, + String[] registryBeans) { + if (ObjectUtils.isEmpty(registryBeans)) { + registerNoOpMeterRegistry(registry); + } + if (registryBeans.length > 1 && !hasPrimaryDefinition(registryBeans)) { + registerPrimaryCompositeMeterRegistry(registry, registryBeans); + } + } + + private boolean hasPrimaryDefinition(String[] registryBeans) { + return Arrays.stream(registryBeans).map(this.beanFactory::getBeanDefinition) + .anyMatch(BeanDefinition::isPrimary); + } + + private void registerNoOpMeterRegistry(BeanDefinitionRegistry registry) { + // If there are no meter registries configured, we register an empty composite + // that effectively no-ops metrics instrumentation throughout the app. + GenericBeanDefinition definition = new GenericBeanDefinition(); + definition.setBeanClass(CompositeMeterRegistry.class); + registry.registerBeanDefinition(COMPOSITE_BEAN_NAME, definition); + } + + private void registerPrimaryCompositeMeterRegistry(BeanDefinitionRegistry registry, + String[] registryBeans) { + GenericBeanDefinition definition = new GenericBeanDefinition(); + definition.setBeanClass(CompositeMeterRegistry.class); + definition.setPrimary(true); + ConstructorArgumentValues arguments = new ConstructorArgumentValues(); + arguments.addIndexedArgumentValue(0, + new ValueHolder(null, Clock.class.getName())); + arguments.addIndexedArgumentValue(1, getBeanReferences(registryBeans)); + definition.setConstructorArgumentValues(arguments); + registry.registerBeanDefinition(COMPOSITE_BEAN_NAME, definition); + } + + private ManagedList getBeanReferences(String[] names) { + ManagedList references = new ManagedList<>(names.length); + Arrays.stream(names).map(RuntimeBeanReference::new).forEach(references::add); + return references; + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/atlas/AtlasExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/atlas/AtlasExportConfiguration.java index 2410f35f4f..62f61645ba 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/atlas/AtlasExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/atlas/AtlasExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -20,7 +20,6 @@ import com.netflix.spectator.atlas.AtlasConfig; import io.micrometer.atlas.AtlasMeterRegistry; import io.micrometer.core.instrument.Clock; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,14 +47,8 @@ public class AtlasExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.atlas.enabled", matchIfMissing = true) - public MetricsExporter atlasExporter(AtlasConfig atlasConfig, Clock clock) { - return () -> new AtlasMeterRegistry(atlasConfig, clock); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + public AtlasMeterRegistry atlasMeterRegistry(AtlasConfig atlasConfig, Clock clock) { + return new AtlasMeterRegistry(atlasConfig, clock); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogExportConfiguration.java index 11700e2c01..f692d7faaa 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/datadog/DatadogExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -20,7 +20,6 @@ import io.micrometer.core.instrument.Clock; import io.micrometer.datadog.DatadogConfig; import io.micrometer.datadog.DatadogMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,14 +47,9 @@ public class DatadogExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.datadog.enabled", matchIfMissing = true) - public MetricsExporter datadogExporter(DatadogConfig datadogConfig, Clock clock) { - return () -> new DatadogMeterRegistry(datadogConfig, clock); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + public DatadogMeterRegistry datadogMeterRegistry(DatadogConfig datadogConfig, + Clock clock) { + return new DatadogMeterRegistry(datadogConfig, clock); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/ganglia/GangliaExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/ganglia/GangliaExportConfiguration.java index 6a04e7d943..45714feafd 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/ganglia/GangliaExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/ganglia/GangliaExportConfiguration.java @@ -21,7 +21,6 @@ import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.ganglia.GangliaConfig; import io.micrometer.ganglia.GangliaMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,15 +47,9 @@ public class GangliaExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.ganglia.enabled", matchIfMissing = true) - public MetricsExporter gangliaExporter(GangliaConfig gangliaConfig, + public GangliaMeterRegistry gangliaMeterRegistry(GangliaConfig gangliaConfig, HierarchicalNameMapper nameMapper, Clock clock) { - return () -> new GangliaMeterRegistry(gangliaConfig, clock, nameMapper); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + return new GangliaMeterRegistry(gangliaConfig, clock, nameMapper); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteExportConfiguration.java index beafe8aee7..ab9c6b8364 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/graphite/GraphiteExportConfiguration.java @@ -21,7 +21,6 @@ import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.graphite.GraphiteConfig; import io.micrometer.graphite.GraphiteMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,15 +47,9 @@ public class GraphiteExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.graphite.enabled", matchIfMissing = true) - public MetricsExporter graphiteExporter(GraphiteConfig graphiteConfig, + public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig graphiteConfig, HierarchicalNameMapper nameMapper, Clock clock) { - return () -> new GraphiteMeterRegistry(graphiteConfig, clock, nameMapper); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + return new GraphiteMeterRegistry(graphiteConfig, clock, nameMapper); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/influx/InfluxExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/influx/InfluxExportConfiguration.java index 444263a352..b1afbf54ab 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/influx/InfluxExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/influx/InfluxExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -20,7 +20,6 @@ import io.micrometer.core.instrument.Clock; import io.micrometer.influx.InfluxConfig; import io.micrometer.influx.InfluxMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -47,14 +46,9 @@ public class InfluxExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.influx.enabled", matchIfMissing = true) - public MetricsExporter influxExporter(InfluxConfig influxConfig, Clock clock) { - return () -> new InfluxMeterRegistry(influxConfig, clock); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + public InfluxMeterRegistry influxMeterRegistry(InfluxConfig influxConfig, + Clock clock) { + return new InfluxMeterRegistry(influxConfig, clock); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxExportConfiguration.java index b6be253897..655dea9a06 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/jmx/JmxExportConfiguration.java @@ -21,7 +21,6 @@ import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.jmx.JmxConfig; import io.micrometer.jmx.JmxMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,15 +47,9 @@ public class JmxExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.jmx.enabled", matchIfMissing = true) - public MetricsExporter jmxExporter(JmxConfig config, + public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, HierarchicalNameMapper nameMapper, Clock clock) { - return () -> new JmxMeterRegistry(config, clock, nameMapper); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + return new JmxMeterRegistry(config, clock, nameMapper); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusExportConfiguration.java index 42fbd2b934..b9f0f680d6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -21,7 +21,6 @@ import io.micrometer.prometheus.PrometheusConfig; import io.micrometer.prometheus.PrometheusMeterRegistry; import io.prometheus.client.CollectorRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration; import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -50,10 +49,10 @@ public class PrometheusExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.prometheus.enabled", matchIfMissing = true) - public MetricsExporter prometheusExporter(PrometheusConfig prometheusConfig, - CollectorRegistry collectorRegistry, Clock clock) { - return () -> new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, - clock); + public PrometheusMeterRegistry prometheusMeterRegistry( + PrometheusConfig prometheusConfig, CollectorRegistry collectorRegistry, + Clock clock) { + return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock); } @Bean @@ -62,12 +61,6 @@ public class PrometheusExportConfiguration { return new CollectorRegistry(true); } - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; - } - @ManagementContextConfiguration public static class PrometheusScrapeEndpointConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfiguration.java index f46d8b0e46..522df44e06 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -17,10 +17,10 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.simple; import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.simple.SimpleConfig; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -39,15 +39,9 @@ public class SimpleExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.simple.enabled", matchIfMissing = true) - @ConditionalOnMissingBean(MetricsExporter.class) - public MetricsExporter simpleExporter(SimpleConfig config, Clock clock) { - return () -> new SimpleMeterRegistry(config, clock); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + @ConditionalOnMissingBean(MeterRegistry.class) + public SimpleMeterRegistry simpleMeterRegistry(SimpleConfig config, Clock clock) { + return new SimpleMeterRegistry(config, clock); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdExportConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdExportConfiguration.java index 27cb3526d3..b265b23d8e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdExportConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/statsd/StatsdExportConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -21,7 +21,6 @@ import io.micrometer.core.instrument.util.HierarchicalNameMapper; import io.micrometer.statsd.StatsdConfig; import io.micrometer.statsd.StatsdMeterRegistry; -import org.springframework.boot.actuate.autoconfigure.metrics.export.MetricsExporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -48,15 +47,9 @@ public class StatsdExportConfiguration { @Bean @ConditionalOnProperty(value = "management.metrics.export.statsd.enabled", matchIfMissing = true) - public MetricsExporter statsdExporter(StatsdConfig statsdConfig, + public StatsdMeterRegistry statsdMeterRegistry(StatsdConfig statsdConfig, HierarchicalNameMapper hierarchicalNameMapper, Clock clock) { - return () -> new StatsdMeterRegistry(statsdConfig, hierarchicalNameMapper, clock); - } - - @Bean - @ConditionalOnMissingBean - public Clock micrometerClock() { - return Clock.SYSTEM; + return new StatsdMeterRegistry(statsdConfig, hierarchicalNameMapper, clock); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java index 9e0aaccbe4..2099341639 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/SpringApplicationHierarchyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure; import org.junit.After; import org.junit.Test; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration; @@ -67,8 +68,8 @@ public class SpringApplicationHierarchyTests { CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, MongoDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class, RedisAutoConfiguration.class, - RedisRepositoriesAutoConfiguration.class, - FlywayAutoConfiguration.class }, excludeName = { + RedisRepositoriesAutoConfiguration.class, FlywayAutoConfiguration.class, + MetricsAutoConfiguration.class }, excludeName = { "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" }) public static class Child { @@ -79,8 +80,8 @@ public class SpringApplicationHierarchyTests { CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, MongoDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class, RedisAutoConfiguration.class, - RedisRepositoriesAutoConfiguration.class, - FlywayAutoConfiguration.class }, excludeName = { + RedisRepositoriesAutoConfiguration.class, FlywayAutoConfiguration.class, + MetricsAutoConfiguration.class }, excludeName = { "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" }) public static class Parent { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurerTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizerTests.java similarity index 59% rename from spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurerTests.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizerTests.java index 40108f5755..f0253652c6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurerTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryCustomizerTests.java @@ -17,20 +17,22 @@ package org.springframework.boot.actuate.autoconfigure.metrics; import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.MeterRegistry.Config; import org.junit.Test; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; /** - * Tests for applying {@link MeterRegistryConfigurer MeterRegistryConfigurers}. + * Tests for applying {@link MeterRegistryCustomizer} beans. * * @author Jon Schneider * @author Andy Wilkinson */ -public class MeterRegistryConfigurerTests { +public class MeterRegistryCustomizerTests { private ApplicationContextRunner contextRunner = new ApplicationContextRunner() .with(MetricsRun.simple()); @@ -38,26 +40,35 @@ public class MeterRegistryConfigurerTests { @Test public void commonTagsAreAppliedToAutoConfiguredBinders() { this.contextRunner - .withUserConfiguration(MeterRegistryConfigurerConfiguration.class) - .run((context) -> assertThat(context.getBean(MeterRegistry.class) - .get("jvm.memory.used").tags("region", "us-east-1").gauge()) - .isNotNull()); + .withUserConfiguration(MeterRegistryCustomizerConfiguration.class) + .run((context) -> { + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry.get("jvm.memory.used").tags("region", "us-east-1") + .gauge()).isNotNull(); + }); } @Test public void commonTagsAreAppliedBeforeRegistryIsInjectableElsewhere() { this.contextRunner - .withUserConfiguration(MeterRegistryConfigurerConfiguration.class) - .run((context) -> assertThat(context.getBean(MeterRegistry.class) - .get("my.thing").tags("region", "us-east-1").gauge()) - .isNotNull()); + .withUserConfiguration(MeterRegistryCustomizerConfiguration.class) + .run((context) -> { + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat( + registry.get("my.thing").tags("region", "us-east-1").gauge()) + .isNotNull(); + }); } - static class MeterRegistryConfigurerConfiguration { + @Configuration + static class MeterRegistryCustomizerConfiguration { @Bean - public MeterRegistryConfigurer registryConfigurer() { - return (registry) -> registry.config().commonTags("region", "us-east-1"); + public MeterRegistryCustomizer commonTags() { + return (registry) -> { + Config config = registry.config(); + config.commonTags("region", "us-east-1"); + }; } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessorTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessorTests.java new file mode 100644 index 0000000000..edf4fce9ab --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessorTests.java @@ -0,0 +1,184 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +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 org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.util.Assert; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Tests for {@link MeterRegistryPostProcessor}. + * + * @author Phillip Webb + */ +public class MeterRegistryPostProcessorTests { + + private List binderBeans = new ArrayList<>(); + + private List> customizerBeans = new ArrayList<>(); + + private ObjectProvider> binders = TestObjectProvider + .of(this.binderBeans); + + private ObjectProvider>> customizers = TestObjectProvider + .of(this.customizerBeans); + + @Mock + private MeterBinder mockBinder; + + @Mock + private MeterRegistryCustomizer mockCustomizer; + + @Mock + private MeterRegistry mockRegistry; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void postProcessWhenNotRegistryShouldReturnBean() { + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + Object bean = new Object(); + String beanName = "name"; + assertThat(processor.postProcessBeforeInitialization(bean, beanName)) + .isEqualTo(bean); + assertThat(processor.postProcessAfterInitialization(bean, beanName)) + .isEqualTo(bean); + } + + @Test + public void postProcessorWhenCompositeShouldSkip() { + this.binderBeans.add(this.mockBinder); + this.customizerBeans.add(this.mockCustomizer); + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + assertThat(processor.postProcessAfterInitialization(new CompositeMeterRegistry(), + "name")); + verifyZeroInteractions(this.mockBinder, this.mockCustomizer); + } + + @Test + public void postProcessShouldApplyCustomizer() { + this.customizerBeans.add(this.mockCustomizer); + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + assertThat(processor.postProcessAfterInitialization(this.mockRegistry, "name")); + verify(this.mockCustomizer).customize(this.mockRegistry); + } + + @Test + public void postProcessShouldApplyBinder() { + this.binderBeans.add(this.mockBinder); + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + assertThat(processor.postProcessAfterInitialization(this.mockRegistry, "name")); + verify(this.mockBinder).bindTo(this.mockRegistry); + } + + @Test + public void postProcessShouldCustomizeBeforeApplyingBinder() { + this.binderBeans.add(this.mockBinder); + this.customizerBeans.add(this.mockCustomizer); + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + processor.postProcessAfterInitialization(this.mockRegistry, "name"); + InOrder ordered = inOrder(this.mockCustomizer, this.mockBinder); + ordered.verify(this.mockCustomizer).customize(this.mockRegistry); + ordered.verify(this.mockBinder).bindTo(this.mockRegistry); + } + + @Test + public void postProcessWhenAddToGlobalRegistryShouldAddToGlobalRegistry() { + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, true); + try { + processor.postProcessAfterInitialization(this.mockRegistry, "name"); + assertThat(Metrics.globalRegistry.getRegistries()) + .contains(this.mockRegistry); + } + finally { + Metrics.removeRegistry(this.mockRegistry); + } + } + + @Test + public void postProcessWhenNotAddToGlobalRegistryShouldAddToGlobalRegistry() { + MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor( + this.binders, this.customizers, false); + processor.postProcessAfterInitialization(this.mockRegistry, "name"); + assertThat(Metrics.globalRegistry.getRegistries()) + .doesNotContain(this.mockRegistry); + } + + private static class TestObjectProvider implements ObjectProvider { + + private final T value; + + TestObjectProvider(T value) { + this.value = value; + } + + @Override + public T getObject() throws BeansException { + Assert.state(this.value != null, "No value"); + return this.value; + } + + @Override + public T getObject(Object... args) throws BeansException { + return this.value; + } + + @Override + public T getIfAvailable() throws BeansException { + return this.value; + } + + @Override + public T getIfUnique() throws BeansException { + throw new UnsupportedOperationException(); + } + + public static TestObjectProvider of(T value) { + return new TestObjectProvider<>(value); + } + + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfigurationIntegrationTests.java index 2712edda74..e3668ac5b5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfigurationIntegrationTests.java @@ -51,6 +51,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Primary; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.test.context.TestPropertySource; @@ -140,6 +141,7 @@ public class MetricsAutoConfigurationIntegrationTests { @Import(PersonController.class) static class MetricsApp { + @Primary @Bean public MeterRegistry registry() { return new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock()); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsConfigurationCompositeTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsConfigurationCompositeTests.java deleted file mode 100644 index 353d6cd076..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsConfigurationCompositeTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2018 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 - * - * http://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.actuate.autoconfigure.metrics; - -import io.micrometer.core.instrument.composite.CompositeMeterRegistry; -import io.micrometer.graphite.GraphiteMeterRegistry; -import io.micrometer.prometheus.PrometheusMeterRegistry; -import org.junit.Test; - -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MetricsAutoConfiguration} creating a {@link CompositeMeterRegistry}. - * - * @author Jon Schneider - */ -public class MetricsConfigurationCompositeTests { - - @Test - public void compositeContainsImplementationsOnClasspath() { - new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) - .withPropertyValues("management.metrics.use-global-registry=false") - .run((context) -> assertThat( - context.getBean(CompositeMeterRegistry.class).getRegistries()) - .hasAtLeastOneElementOfType(PrometheusMeterRegistry.class) - .hasAtLeastOneElementOfType(GraphiteMeterRegistry.class)); - } - -} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfigurationTests.java new file mode 100644 index 0000000000..50c3bf6225 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryConfigurationTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics.export; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.MockClock; +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import io.micrometer.core.instrument.simple.SimpleConfig; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.graphite.GraphiteMeterRegistry; +import io.micrometer.jmx.JmxMeterRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsRun; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CompositeMeterRegistryConfiguration}. + * + * @author Jon Schneider + */ +@RunWith(SpringRunner.class) +public class CompositeMeterRegistryConfigurationTests { + + private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .with(MetricsRun.simple()); + + /** + * The simple registry is off by default UNLESS there is no other registry + * implementation on the classpath, in which case it is on. + */ + @Test + public void simpleWithNoCompositeCreated() { + this.contextRunner + .run((context) -> assertThat(context.getBean(MeterRegistry.class)) + .isInstanceOf(SimpleMeterRegistry.class)); + } + + /** + * An empty composite is created in the absence of any other registry implementation. + * This effectively no-ops instrumentation code throughout the application. + */ + @Test + public void emptyCompositeCreated() { + new ApplicationContextRunner().with(MetricsRun.limitedTo()).run((context) -> { + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry).isInstanceOf(CompositeMeterRegistry.class); + assertThat(((CompositeMeterRegistry) registry).getRegistries()).isEmpty(); + }); + } + + @Test + public void noCompositeCreatedWhenSingleImplementationIsEnabled() { + new ApplicationContextRunner().with(MetricsRun.limitedTo("graphite")) + .run((context) -> assertThat(context.getBean(MeterRegistry.class)) + .isInstanceOf(GraphiteMeterRegistry.class)); + } + + @Test + public void noCompositeCreatedWhenMultipleRegistriesButOneMarkedAsPrimary() { + new ApplicationContextRunner().with(MetricsRun.limitedTo("graphite", "jmx")) + .withUserConfiguration(PrimarySimpleMeterRegistryConfiguration.class) + .run((context) -> assertThat(context.getBean(MeterRegistry.class)) + .isInstanceOf(SimpleMeterRegistry.class)); + } + + @Test + public void compositeCreatedWhenMultipleImplementationsAreEnabled() { + new ApplicationContextRunner().with(MetricsRun.limitedTo("graphite", "jmx")) + .run((context) -> { + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry).isInstanceOf(CompositeMeterRegistry.class); + assertThat(((CompositeMeterRegistry) registry).getRegistries()) + .hasAtLeastOneElementOfType(GraphiteMeterRegistry.class) + .hasAtLeastOneElementOfType(JmxMeterRegistry.class); + }); + } + + @Configuration + static class PrimarySimpleMeterRegistryConfiguration { + + @Primary + @Bean + public MeterRegistry simpleMeterRegistry() { + return new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock()); + } + + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessorTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessorTests.java new file mode 100644 index 0000000000..622f8b45fc --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/CompositeMeterRegistryPostProcessorTests.java @@ -0,0 +1,134 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.actuate.autoconfigure.metrics.export; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CompositeMeterRegistryPostProcessor}. + * + * @author Phillip Webb + */ +public class CompositeMeterRegistryPostProcessorTests { + + private static final String COMPOSITE_NAME = "compositeMeterRegistry"; + + private ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(BaseConfig.class); + + @Test + public void registerWhenHasNoMeterRegistryShouldRegisterEmptyComposite() { + this.contextRunner.withUserConfiguration(NoMeterRegistryConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(MeterRegistry.class); + CompositeMeterRegistry registry = context.getBean(COMPOSITE_NAME, + CompositeMeterRegistry.class); + assertThat(registry.getRegistries()).isEmpty(); + }); + } + + @Test + public void registerWhenHasSingleMeterRegistryShouldDoNothing() { + this.contextRunner.withUserConfiguration(SingleMeterRegistryConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(MeterRegistry.class); + MeterRegistry registry = context.getBean(MeterRegistry.class); + assertThat(registry).isInstanceOf(TestMeterRegistry.class); + }); + } + + @Test + public void registerWhenHasMultipleMeterRegistriesShouldAddPrimaryComposite() { + this.contextRunner.withUserConfiguration(MultipleMeterRegistriesConfig.class) + .run((context) -> { + assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(3) + .containsKeys("meterRegistryOne", "meterRegistryTwo", + COMPOSITE_NAME); + MeterRegistry primary = context.getBean(MeterRegistry.class); + assertThat(primary).isInstanceOf(CompositeMeterRegistry.class); + assertThat(((CompositeMeterRegistry) primary).getRegistries()) + .hasSize(2); + }); + } + + @Test + public void registerWhenHasMultipleRegistriesAndOneIsPrimaryShouldDoNothing() { + + } + + @Configuration + static class BaseConfig { + + @Bean + public CompositeMeterRegistryPostProcessor compositeMeterRegistryPostProcessor() { + return new CompositeMeterRegistryPostProcessor(); + } + + @Bean + @ConditionalOnMissingBean + public Clock micrometerClock() { + return Clock.SYSTEM; + } + + } + + @Configuration + static class NoMeterRegistryConfig { + + } + + @Configuration + static class SingleMeterRegistryConfig { + + @Bean + public MeterRegistry meterRegistry() { + return new TestMeterRegistry(); + } + + } + + @Configuration + static class MultipleMeterRegistriesConfig { + + @Bean + public MeterRegistry meterRegistryOne() { + return new TestMeterRegistry(); + } + + @Bean + public MeterRegistry meterRegistryTwo() { + return new SimpleMeterRegistry(); + } + + } + + static class TestMeterRegistry extends SimpleMeterRegistry { + + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfigurationTests.java deleted file mode 100644 index b9f622bcff..0000000000 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleExportConfigurationTests.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2012-2018 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 - * - * http://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.actuate.autoconfigure.metrics.export.simple; - -import io.micrometer.core.instrument.composite.CompositeMeterRegistry; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link SimpleExportConfiguration}. - * - * @author Jon Schneider - */ -@RunWith(SpringRunner.class) -public class SimpleExportConfigurationTests { - - @Test - public void simpleMeterRegistryIsInTheCompositeWhenNoOtherRegistryIs() { - new ApplicationContextRunner() - .withPropertyValues("management.metrics.export.atlas.enabled=false", - "management.metrics.export.datadog.enabled=false", - "management.metrics.export.ganglia.enabled=false", - "management.metrics.export.graphite.enabled=false", - "management.metrics.export.influx.enabled=false", - "management.metrics.export.jmx.enabled=false", - "management.metrics.export.prometheus.enabled=false", - "management.metrics.export.statsd.enabled=false", - "management.metrics.use-global-registry=false") - .withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) - .run((context) -> { - CompositeMeterRegistry meterRegistry = context - .getBean(CompositeMeterRegistry.class); - assertThat(meterRegistry.getRegistries()).hasSize(1); - assertThat(meterRegistry.getRegistries()) - .hasOnlyElementsOfType(SimpleMeterRegistry.class); - }); - } - -}