Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;
import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorRegistrar;

/**
* Enables default configuring of management in Spring Integration components in an existing application.
Expand All @@ -31,13 +32,14 @@
* bean is defined under the name {@code integrationManagementConfigurer}.
*
* @author Gary Russell
* @author Artem Bilan
*
* @since 4.2
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(IntegrationManagementConfiguration.class)
@Import({ MicrometerMetricsCaptorRegistrar.class, IntegrationManagementConfiguration.class })
public @interface EnableIntegrationManagement {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.Map;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
Expand All @@ -27,6 +28,7 @@
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.integration.support.management.metrics.MetricsCaptor;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -62,11 +64,13 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {

@Bean(name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public IntegrationManagementConfigurer managementConfigurer() {
public IntegrationManagementConfigurer managementConfigurer(ObjectProvider<MetricsCaptor> metricsCaptorProvider) {

IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer();
configurer.setDefaultLoggingEnabled(
Boolean.parseBoolean(this.environment.resolvePlaceholders(
(String) this.attributes.get("defaultLoggingEnabled"))));
configurer.setMetricsCaptor(metricsCaptorProvider.getIfUnique());
return configurer;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,27 @@

package org.springframework.integration.config;

import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.support.management.IntegrationManagement;
import org.springframework.integration.support.management.IntegrationManagement.ManagementOverrides;
import org.springframework.integration.support.management.metrics.MeterFacade;
import org.springframework.integration.support.management.metrics.MetricsCaptor;
import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptor;
import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;


/**
Expand All @@ -49,13 +52,16 @@
*
*/
public class IntegrationManagementConfigurer
implements SmartInitializingSingleton, ApplicationContextAware, BeanNameAware, BeanPostProcessor {
implements SmartInitializingSingleton, ApplicationContextAware, BeanNameAware, BeanPostProcessor,
DisposableBean {

/**
* Bean name of the configurer.
*/
public static final String MANAGEMENT_CONFIGURER_NAME = "integrationManagementConfigurer";

private final Set<MeterFacade> gauges = new HashSet<>();

private ApplicationContext applicationContext;

private String beanName;
Expand Down Expand Up @@ -99,15 +105,15 @@ public void setDefaultLoggingEnabled(boolean defaultLoggingEnabled) {
this.defaultLoggingEnabled = defaultLoggingEnabled;
}

public void setMetricsCaptor(@Nullable MetricsCaptor metricsCaptor) {
this.metricsCaptor = metricsCaptor;
}

@Override
public void afterSingletonsInstantiated() {
Assert.state(this.applicationContext != null, "'applicationContext' must not be null");
Assert.state(MANAGEMENT_CONFIGURER_NAME.equals(this.beanName), getClass().getSimpleName()
+ " bean name must be " + MANAGEMENT_CONFIGURER_NAME);
if (ClassUtils.isPresent("io.micrometer.core.instrument.MeterRegistry",
this.applicationContext.getClassLoader())) {
this.metricsCaptor = MicrometerMetricsCaptor.loadCaptor(this.applicationContext);
}
if (this.metricsCaptor != null) {
injectCaptor();
registerComponentGauges();
Expand Down Expand Up @@ -144,20 +150,29 @@ public Object postProcessAfterInitialization(Object bean, String name) throws Be
}

private void registerComponentGauges() {
this.metricsCaptor.gaugeBuilder("spring.integration.channels", this,
(c) -> this.applicationContext.getBeansOfType(MessageChannel.class).size())
.description("The number of message channels")
.build();

this.metricsCaptor.gaugeBuilder("spring.integration.handlers", this,
(c) -> this.applicationContext.getBeansOfType(MessageHandler.class).size())
.description("The number of message handlers")
.build();

this.metricsCaptor.gaugeBuilder("spring.integration.sources", this,
(c) -> this.applicationContext.getBeansOfType(MessageSource.class).size())
.description("The number of message sources")
.build();
this.gauges.add(
this.metricsCaptor.gaugeBuilder("spring.integration.channels", this,
(c) -> this.applicationContext.getBeansOfType(MessageChannel.class).size())
.description("The number of message channels")
.build());

this.gauges.add(
this.metricsCaptor.gaugeBuilder("spring.integration.handlers", this,
(c) -> this.applicationContext.getBeansOfType(MessageHandler.class).size())
.description("The number of message handlers")
.build());

this.gauges.add(
this.metricsCaptor.gaugeBuilder("spring.integration.sources", this,
(c) -> this.applicationContext.getBeansOfType(MessageSource.class).size())
.description("The number of message sources")
.build());
}

@Override
public void destroy() {
this.gauges.forEach(MeterFacade::remove);
this.gauges.clear();
}

private static ManagementOverrides getOverrides(IntegrationManagement bean) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2018-2020 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.
Expand Down Expand Up @@ -86,7 +86,10 @@ public MeterFacade removeMeter(MeterFacade facade) {
* there's already a {@link MetricsCaptor} bean, return that.
* @param applicationContext the application context.
* @return the instance.
* @deprecated since 5.2.9 in favor of {@code @Import(MicrometerMetricsCaptorRegistrar.class)};
* will be removed in 6.0.
*/
@Deprecated
public static MetricsCaptor loadCaptor(ApplicationContext applicationContext) {
try {
MeterRegistry registry = applicationContext.getBean(MeterRegistry.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2020 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.integration.support.management.micrometer;

import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;

/**
* An {@link ImportBeanDefinitionRegistrar} to conditionally add a {@link MicrometerMetricsCaptor}
* bean when {@code io.micrometer.core.instrument.MeterRegistry} is present in classpath and
* no {@link MicrometerMetricsCaptor#MICROMETER_CAPTOR_NAME} bean present yet.
*
* @author Artem Bilan
*
* @since 5.2.9
*/
public class MicrometerMetricsCaptorRegistrar implements ImportBeanDefinitionRegistrar {

private static final Class<?> METER_REGISTRY_CLASS;

static {
Class<?> aClass = null;
try {
aClass = ClassUtils.forName("io.micrometer.core.instrument.MeterRegistry",
ClassUtils.getDefaultClassLoader());
}
catch (ClassNotFoundException e) {
// Ignore - no Micrometer in classpath
}
METER_REGISTRY_CLASS = aClass;
}

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (METER_REGISTRY_CLASS != null
&& !registry.containsBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME)) {
String[] beanNamesForType =
((ListableBeanFactory) registry).getBeanNamesForType(METER_REGISTRY_CLASS, false, false);
for (String beanName : beanNamesForType) {
registry.registerBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME,
BeanDefinitionBuilder.genericBeanDefinition(MicrometerMetricsCaptor.class)
.addConstructorArgReference(beanName)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
.getBeanDefinition());
return;
}

}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2018-2020 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.
Expand Down Expand Up @@ -112,7 +112,7 @@ public void contextLoads() {
public static class Config {

@Bean
public MeterRegistry meterRegistry() {
public static MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ void testIncludesDynamic() {
@ImportResource("org/springframework/integration/graph/integration-graph-context.xml")
public static class Config {

@Bean
public static MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

@Bean
public IntegrationGraphServer server() {
IntegrationGraphServer server = new IntegrationGraphServer();
Expand All @@ -274,11 +279,6 @@ public IntegrationGraphServer server() {
return server;
}

@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

@Bean
public MessageProducer producer() {
MessageProducerSupport producer = new MessageProducerSupport() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2019 the original author or authors.
* Copyright 2018-2020 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.
Expand All @@ -17,10 +17,9 @@
package org.springframework.integration.support.management.micrometer;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
Expand All @@ -32,7 +31,7 @@
import org.springframework.integration.support.management.metrics.MetricsCaptor;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;

import io.micrometer.core.instrument.MeterRegistry;
Expand All @@ -46,7 +45,7 @@
* @since 5.1
*
*/
@RunWith(SpringRunner.class)
@SpringJUnitConfig
@TestExecutionListeners(DependencyInjectionTestExecutionListener.class)
public class MicrometerCustomMetricsTests {

Expand Down Expand Up @@ -81,20 +80,18 @@ public void testSend() {

// Test meter removal
this.context.close();
try {
registry.get("myTimer").timers();
fail("Expected MeterNotFoundException");
}
catch (MeterNotFoundException e) {
assertThat(e).hasMessageContaining("No meter with name 'myTimer' was found");
}
try {
registry.get("myCounter").counters();
fail("Expected MeterNotFoundException");
}
catch (MeterNotFoundException e) {
assertThat(e).hasMessageContaining("No meter with name 'myCounter' was found");
}

assertThatExceptionOfType(MeterNotFoundException.class)
.isThrownBy(() -> registry.get("myTimer").timers())
.withMessageContaining("No meter with name 'myTimer' was found");

assertThatExceptionOfType(MeterNotFoundException.class)
.isThrownBy(() -> registry.get("myCounter").counters())
.withMessageContaining("No meter with name 'myCounter' was found");

assertThatExceptionOfType(MeterNotFoundException.class)
.isThrownBy(() -> registry.get("spring.integration.channels").gauge())
.withMessageContaining("No meter with name 'spring.integration.channels' was found");
}

@Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void testMicrometerMetrics() {
public static class Config {

@Bean
public MeterRegistry meterRegistry() {
public static MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

Expand Down