diff --git a/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java b/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java index 98931c7a5b..4b44299a1b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java @@ -68,6 +68,8 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport private final Comparator orderComparator = new OrderComparator(); + private final ManagementOverrides managementOverrides = new ManagementOverrides(); + private volatile boolean shouldTrack = false; private volatile Class[] datatypes = new Class[0]; @@ -101,8 +103,10 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; + this.managementOverrides.countsConfigured = true; if (!countsEnabled) { this.statsEnabled = false; + this.managementOverrides.statsConfigured = true; } } @@ -115,9 +119,11 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport public void setStatsEnabled(boolean statsEnabled) { if (statsEnabled) { this.countsEnabled = true; + this.managementOverrides.countsConfigured = true; } this.statsEnabled = statsEnabled; this.channelMetrics.setFullStatsEnabled(statsEnabled); + this.managementOverrides.statsConfigured = true; } @Override @@ -133,6 +139,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport @Override public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; + this.managementOverrides.loggingConfigured = true; } protected AbstractMessageChannelMetrics getMetrics() { @@ -143,6 +150,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport public void configureMetrics(AbstractMessageChannelMetrics metrics) { Assert.notNull(metrics, "'metrics' must not be null"); this.channelMetrics = metrics; + this.managementOverrides.metricsConfigured = true; } /** @@ -323,6 +331,11 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport return this.channelMetrics.getErrorRate(); } + @Override + public ManagementOverrides getOverrides() { + return this.managementOverrides; + } + @Override protected void onInit() throws Exception { super.onInit(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/channel/NullChannel.java b/spring-integration-core/src/main/java/org/springframework/integration/channel/NullChannel.java index 2414cc76ed..d83e86138a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/channel/NullChannel.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/channel/NullChannel.java @@ -45,7 +45,9 @@ import org.springframework.util.StringUtils; public class NullChannel implements PollableChannel, MessageChannelMetrics, ConfigurableMetricsAware, BeanNameAware, NamedComponent { - private final Log logger = LogFactory.getLog(this.getClass()); + private final Log logger = LogFactory.getLog(getClass()); + + private final ManagementOverrides managementOverrides = new ManagementOverrides(); private volatile AbstractMessageChannelMetrics channelMetrics = new DefaultMessageChannelMetrics("nullChannel"); @@ -71,6 +73,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics, @Override public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; + this.managementOverrides.loggingConfigured = true; } @Override @@ -87,6 +90,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics, public void configureMetrics(AbstractMessageChannelMetrics metrics) { Assert.notNull(metrics, "'metrics' must not be null"); this.channelMetrics = metrics; + this.managementOverrides.metricsConfigured = true; } @Override @@ -97,8 +101,10 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics, @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; + this.managementOverrides.countsConfigured = true; if (!countsEnabled) { this.statsEnabled = false; + this.managementOverrides.statsConfigured = true; } } @@ -111,9 +117,11 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics, public void setStatsEnabled(boolean statsEnabled) { if (statsEnabled) { this.countsEnabled = true; + this.managementOverrides.countsConfigured = true; } this.statsEnabled = statsEnabled; this.channelMetrics.setFullStatsEnabled(statsEnabled); + this.managementOverrides.statsConfigured = true; } @Override @@ -196,6 +204,11 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics, return this.channelMetrics.getErrorRate(); } + @Override + public ManagementOverrides getOverrides() { + return this.managementOverrides; + } + @Override public boolean send(Message message) { if (this.loggingEnabled && this.logger.isDebugEnabled()) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java index bde4c5eade..1e5bc41f6f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlows.java @@ -153,6 +153,7 @@ public final class IntegrationFlows { * Provides {@link Supplier} as source of messages to the integration flow which will * be triggered by the application context's default poller (which must be declared). * @param messageSource the {@link Supplier} to populate. + * @param the supplier type. * @return new {@link IntegrationFlowBuilder}. * @see Supplier */ @@ -166,10 +167,12 @@ public final class IntegrationFlows { * @param messageSource the {@link Supplier} to populate. * @param endpointConfigurer the {@link Consumer} to provide more options for the * {@link org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean}. + * @param the supplier type. * @return new {@link IntegrationFlowBuilder}. * @see Supplier */ - public static IntegrationFlowBuilder from(Supplier messageSource, Consumer endpointConfigurer) { + public static IntegrationFlowBuilder from(Supplier messageSource, + Consumer endpointConfigurer) { return from(messageSource, "get", endpointConfigurer); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractMessageSource.java b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractMessageSource.java index 699b98564b..8cabc1e968 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractMessageSource.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractMessageSource.java @@ -45,6 +45,8 @@ public abstract class AbstractMessageSource extends AbstractExpressionEvaluat private final AtomicLong messageCount = new AtomicLong(); + private final ManagementOverrides managementOverrides = new ManagementOverrides(); + private volatile Map headerExpressions = Collections.emptyMap(); private volatile String beanName; @@ -100,6 +102,7 @@ public abstract class AbstractMessageSource extends AbstractExpressionEvaluat @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; + this.managementOverrides.countsConfigured = true; } @Override @@ -110,6 +113,7 @@ public abstract class AbstractMessageSource extends AbstractExpressionEvaluat @Override public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; + this.managementOverrides.loggingConfigured = true; } @Override @@ -127,6 +131,11 @@ public abstract class AbstractMessageSource extends AbstractExpressionEvaluat return this.messageCount.get(); } + @Override + public ManagementOverrides getOverrides() { + return this.managementOverrides; + } + @Override public final Message receive() { return buildMessage(doReceive()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java index 2fba505acb..015928f3cb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java @@ -87,6 +87,8 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint private final AtomicLong messageCount = new AtomicLong(); + private final ManagementOverrides managementOverrides = new ManagementOverrides(); + private ErrorMessageStrategy errorMessageStrategy = new DefaultErrorMessageStrategy(); private volatile MessageChannel requestChannel; @@ -291,6 +293,7 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint @Override public void setLoggingEnabled(boolean enabled) { this.loggingEnabled = enabled; + this.managementOverrides.loggingConfigured = true; } @Override @@ -301,6 +304,7 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; + this.managementOverrides.countsConfigured = true; } @Override @@ -319,6 +323,11 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint this.errorMessageStrategy = errorMessageStrategy; } + @Override + public ManagementOverrides getOverrides() { + return this.managementOverrides; + } + @Override protected void onInit() throws Exception { Assert.state(!(this.requestChannelName != null && this.requestChannel != null), diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java index cf577671e7..fb864b520a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java @@ -53,6 +53,8 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im MessageHandlerMetrics, ConfigurableMetricsAware, TrackableComponent, Orderable, CoreSubscriber> { + private final ManagementOverrides managementOverrides = new ManagementOverrides(); + private volatile boolean shouldTrack = false; private volatile int order = Ordered.LOWEST_PRECEDENCE; @@ -77,6 +79,7 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im @Override public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; + this.managementOverrides.loggingConfigured = true; } @Override @@ -103,6 +106,12 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im public void configureMetrics(AbstractMessageHandlerMetrics metrics) { Assert.notNull(metrics, "'metrics' must not be null"); this.handlerMetrics = metrics; + this.managementOverrides.metricsConfigured = true; + } + + @Override + public ManagementOverrides getOverrides() { + return this.managementOverrides; } @Override @@ -232,11 +241,13 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im public void setStatsEnabled(boolean statsEnabled) { if (statsEnabled) { this.countsEnabled = true; + this.managementOverrides.countsConfigured = true; } this.statsEnabled = statsEnabled; if (this.handlerMetrics != null) { this.handlerMetrics.setFullStatsEnabled(statsEnabled); } + this.managementOverrides.statsConfigured = true; } @Override @@ -247,8 +258,10 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im @Override public void setCountsEnabled(boolean countsEnabled) { this.countsEnabled = countsEnabled; + this.managementOverrides.countsConfigured = true; if (!countsEnabled) { this.statsEnabled = false; + this.managementOverrides.statsConfigured = true; } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagement.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagement.java index 07d16d3d3d..cd57c11459 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagement.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagement.java @@ -43,4 +43,30 @@ public interface IntegrationManagement { @ManagedAttribute boolean isCountsEnabled(); + /** + * Return the overrides. + * @return the overrides. + * @since 5.0 + */ + ManagementOverrides getOverrides(); + + /** + * Toggles to inform the management configurer to not set these properties since + * the user has manually configured them in a bean definition. If true, the + * corresponding property will not be set by the configurer. + * + * @since 5.0 + */ + class ManagementOverrides { + + public boolean loggingConfigured; + + public boolean countsConfigured; + + public boolean statsConfigured; + + public boolean metricsConfigured; + + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagementConfigurer.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagementConfigurer.java index be14166f79..21ad9d79f9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagementConfigurer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/IntegrationManagementConfigurer.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.integration.support.management.IntegrationManagement.ManagementOverrides; import org.springframework.util.Assert; import org.springframework.util.PatternMatchUtils; import org.springframework.util.StringUtils; @@ -206,7 +207,9 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet Map managed = this.applicationContext.getBeansOfType(IntegrationManagement.class); for (Entry entry : managed.entrySet()) { IntegrationManagement bean = entry.getValue(); - bean.setLoggingEnabled(this.defaultLoggingEnabled); + if (!bean.getOverrides().loggingConfigured) { + bean.setLoggingEnabled(this.defaultLoggingEnabled); + } if (bean instanceof MessageChannelMetrics) { configureChannelMetrics(entry.getKey(), (MessageChannelMetrics) bean); } @@ -223,12 +226,15 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet private void configureChannelMetrics(String name, MessageChannelMetrics bean) { AbstractMessageChannelMetrics metrics = this.metricsFactory.createChannelMetrics(name); Assert.state(metrics != null, "'metrics' must not be null"); + ManagementOverrides overrides = bean.getOverrides(); Boolean enabled = smartMatch(this.enabledCountsPatterns, name); if (enabled != null) { bean.setCountsEnabled(enabled); } else { - bean.setCountsEnabled(this.defaultCountsEnabled); + if (!overrides.countsConfigured) { + bean.setCountsEnabled(this.defaultCountsEnabled); + } } enabled = smartMatch(this.enabledStatsPatterns, name); if (enabled != null) { @@ -236,10 +242,12 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet metrics.setFullStatsEnabled(enabled); } else { - bean.setStatsEnabled(this.defaultStatsEnabled); - metrics.setFullStatsEnabled(this.defaultStatsEnabled); + if (!overrides.statsConfigured) { + bean.setStatsEnabled(this.defaultStatsEnabled); + metrics.setFullStatsEnabled(this.defaultStatsEnabled); + } } - if (bean instanceof ConfigurableMetricsAware) { + if (bean instanceof ConfigurableMetricsAware && !overrides.metricsConfigured) { ((ConfigurableMetricsAware) bean).configureMetrics(metrics); } this.channelsByName.put(name, bean); @@ -249,12 +257,15 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet private void configureHandlerMetrics(String name, MessageHandlerMetrics bean) { AbstractMessageHandlerMetrics metrics = this.metricsFactory.createHandlerMetrics(name); Assert.state(metrics != null, "'metrics' must not be null"); + ManagementOverrides overrides = bean.getOverrides(); Boolean enabled = smartMatch(this.enabledCountsPatterns, name); if (enabled != null) { bean.setCountsEnabled(enabled); } else { - bean.setCountsEnabled(this.defaultCountsEnabled); + if (!overrides.countsConfigured) { + bean.setCountsEnabled(this.defaultCountsEnabled); + } } enabled = smartMatch(this.enabledStatsPatterns, name); if (enabled != null) { @@ -262,10 +273,12 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet metrics.setFullStatsEnabled(enabled); } else { - bean.setStatsEnabled(this.defaultStatsEnabled); - metrics.setFullStatsEnabled(this.defaultStatsEnabled); + if (!overrides.statsConfigured) { + bean.setStatsEnabled(this.defaultStatsEnabled); + metrics.setFullStatsEnabled(this.defaultStatsEnabled); + } } - if (bean instanceof ConfigurableMetricsAware) { + if (bean instanceof ConfigurableMetricsAware && !overrides.metricsConfigured) { ((ConfigurableMetricsAware) bean).configureMetrics(metrics); } @@ -278,7 +291,9 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet bean.setCountsEnabled(enabled); } else { - bean.setCountsEnabled(this.defaultCountsEnabled); + if (!bean.getOverrides().countsConfigured) { + bean.setCountsEnabled(this.defaultCountsEnabled); + } } this.sourcesByName.put(bean.getManagedName() != null ? bean.getManagedName() : name, bean); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java index f23922e667..990b0574b5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageHandlerMetrics.java @@ -182,4 +182,9 @@ public class LifecycleMessageHandlerMetrics implements MessageHandlerMetrics, Li this.delegate.setManagedType(source); } + @Override + public ManagementOverrides getOverrides() { + return this.delegate.getOverrides(); + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java index bab8141c8e..79aef073d5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/LifecycleMessageSourceMetrics.java @@ -119,4 +119,9 @@ public class LifecycleMessageSourceMetrics implements MessageSourceMetrics, Life this.delegate.setManagedType(source); } + @Override + public ManagementOverrides getOverrides() { + return this.delegate.getOverrides(); + } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/support/management/IntegrationManagementConfigurerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/support/management/IntegrationManagementConfigurerTests.java index cbd7ad7c59..620e6317b1 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/support/management/IntegrationManagementConfigurerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/support/management/IntegrationManagementConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 the original author or authors. + * Copyright 2015-2017 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. @@ -50,7 +50,7 @@ import org.springframework.messaging.MessageChannel; public class IntegrationManagementConfigurerTests { @Test - public void testLogging() { + public void testDefaults() { DirectChannel channel = new DirectChannel(); AbstractMessageHandler handler = new RecipientListRouter(); AbstractMessageSource source = new AbstractMessageSource() { @@ -68,6 +68,8 @@ public class IntegrationManagementConfigurerTests { assertTrue(channel.isLoggingEnabled()); assertTrue(handler.isLoggingEnabled()); assertTrue(source.isLoggingEnabled()); + channel.setCountsEnabled(true); + channel.setStatsEnabled(true); ApplicationContext ctx = mock(ApplicationContext.class); Map beans = new HashMap(); beans.put("foo", channel); @@ -82,6 +84,8 @@ public class IntegrationManagementConfigurerTests { assertFalse(channel.isLoggingEnabled()); assertFalse(handler.isLoggingEnabled()); assertFalse(source.isLoggingEnabled()); + assertTrue(channel.isCountsEnabled()); + assertTrue(channel.isStatsEnabled()); } @Test @@ -93,6 +97,8 @@ public class IntegrationManagementConfigurerTests { assertTrue(channel.isStatsEnabled()); assertThat(TestUtils.getPropertyValue(channel, "channelMetrics"), instanceOf(DefaultMessageChannelMetrics.class)); + channel = ctx.getBean("loggingOffChannel", AbstractMessageChannel.class); + assertFalse(channel.isLoggingEnabled()); ctx.close(); } @@ -106,6 +112,12 @@ public class IntegrationManagementConfigurerTests { return new DirectChannel(); } + @Bean + public MessageChannel loggingOffChannel() { + DirectChannel directChannel = new DirectChannel(); + directChannel.setLoggingEnabled(false); + return directChannel; + } } } diff --git a/src/reference/asciidoc/metrics.adoc b/src/reference/asciidoc/metrics.adoc index 110a55a54d..c7e4c12691 100644 --- a/src/reference/asciidoc/metrics.adoc +++ b/src/reference/asciidoc/metrics.adoc @@ -15,6 +15,7 @@ See <> and <> below. This causes the automatic registration of the `IntegrationManagementConfigurer` bean in the application context. Only one such bean can exist in the context and it must have the bean name `integrationManagementConfigurer` if registered manually via a `` definition. +This bean applies it's configuration to beans after all beans in the context have been instantiated. In addition to metrics, you can control *debug* logging in the main message flow. It has been found that in very high volume applications, even calls to `isDebugEnabled()` can be quite expensive with @@ -27,7 +28,7 @@ A number of options are available: [source, xml] ---- + default-logging-enabled="true" <1> default-counts-enabled="false" <2> default-stats-enabled="false" <3> counts-enabled-patterns="foo, !baz, ba*" <4> @@ -40,7 +41,7 @@ A number of options are available: @Configuration @EnableIntegration @EnableIntegrationManagement( - defaultLoggingEnabled = "false", <1> + defaultLoggingEnabled = "true", <1> defaultCountsEnabled = "false", <2> defaultStatsEnabled = "false", <3> countsEnabled = { "foo", "${count.patterns}" }, <4> @@ -53,10 +54,16 @@ public static class ContextConfiguration { <1> Set to `false` to disable all logging in the main message flow, regardless of the log system category settings. Set to 'true' to enable debug logging (if also enabled by the logging subsystem). +Only applied if you have not explicitly configured the setting in a bean definition. +Default `true`. <2> Enable or disable count metrics for components not matching one of the patterns in <4>. +Only applied if you have not explicitly configured the setting in a bean definition. +Default `false`. <3> Enable or disable statistical metrics for components not matching one of the patterns in <5>. +Only applied if you have not explicitly configured the setting in a bean definition. +Default 'false'. <4> A comma-delimited list of patterns for beans for which counts should be enabled; negate the pattern with `!`. First match wins (positive or negative). @@ -81,6 +88,11 @@ See the javadocs for complete information about these classes. When JMX is enabled (see <>), these metrics are also exposed by the `IntegrationMBeanExporter`. +[IMPORTANT] +==== +`defaultLoggingEnabled`, `defaultCountsEnabled`, and `defaultStatsEnabled` are only applied if you have not explicitly configured the corresponding setting in a bean definition. +==== + [[mgmt-channel-features]] ==== MessageChannel Metric Features