Use auto-configuration to create composite, not a BFPP
Closes gh-12122pull/12124/head
parent
1e932860c4
commit
73460a5b25
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for a
|
||||
* {@link CompositeMeterRegistry}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Import({ NoOpMeterRegistryConfiguration.class,
|
||||
CompositeMeterRegistryConfiguration.class })
|
||||
@ConditionalOnClass(CompositeMeterRegistry.class)
|
||||
public class CompositeMeterRegistryAutoConfiguration {
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.List;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryConfiguration.MultipleNonPrimaryMeterRegistriesCondition;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* Configuration for a {@link CompositeMeterRegistry}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Conditional(MultipleNonPrimaryMeterRegistriesCondition.class)
|
||||
class CompositeMeterRegistryConfiguration {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public CompositeMeterRegistry compositeMeterRegistry(Clock clock,
|
||||
List<MeterRegistry> registries) {
|
||||
return new CompositeMeterRegistry(clock, registries);
|
||||
}
|
||||
|
||||
static class MultipleNonPrimaryMeterRegistriesCondition extends NoneNestedConditions {
|
||||
|
||||
MultipleNonPrimaryMeterRegistriesCondition() {
|
||||
super(ConfigurationPhase.REGISTER_BEAN);
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean(MeterRegistry.class)
|
||||
static class NoMeterRegistryCondition {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnSingleCandidate(MeterRegistry.class)
|
||||
static class SingleInjectableMeterRegistry {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,120 +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 java.util.Arrays;
|
||||
|
||||
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.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
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);
|
||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
ConstructorArgumentValues arguments = new ConstructorArgumentValues();
|
||||
arguments.addIndexedArgumentValue(1, getBeanReferences(registryBeans));
|
||||
definition.setConstructorArgumentValues(arguments);
|
||||
registry.registerBeanDefinition(COMPOSITE_BEAN_NAME, definition);
|
||||
}
|
||||
|
||||
private ManagedList<RuntimeBeanReference> getBeanReferences(String[] names) {
|
||||
ManagedList<RuntimeBeanReference> references = new ManagedList<>(names.length);
|
||||
Arrays.stream(names).map(RuntimeBeanReference::new).forEach(references::add);
|
||||
return references;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.Clock;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* Configuration for a no-op meter registry when the context does not contain an
|
||||
* auto-configured {@link MeterRegistry}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@ConditionalOnBean(Clock.class)
|
||||
@ConditionalOnMissingBean(MeterRegistry.class)
|
||||
class NoOpMeterRegistryConfiguration {
|
||||
|
||||
@Bean
|
||||
public CompositeMeterRegistry noOpMeterRegistry(Clock clock) {
|
||||
return new CompositeMeterRegistry(clock);
|
||||
}
|
||||
|
||||
}
|
44
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryPostProcessorTests.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryAutoConfigurationTests.java
44
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryPostProcessorTests.java → spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryAutoConfigurationTests.java
Loading…
Reference in New Issue