INT-4333: Don't Override Explicit Management Props

JIRA: https://jira.spring.io/browse/INT-4333

If the user has explicitly set management properties in a bean definition,
the configurer should not override those settings with defaults.
This commit is contained in:
Gary Russell
2017-09-01 12:29:12 -04:00
committed by Artem Bilan
parent 3a2be8e9e0
commit cfab1fb1a4
12 changed files with 151 additions and 16 deletions

View File

@@ -68,6 +68,8 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
private final Comparator<Object> 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();

View File

@@ -45,7 +45,9 @@ import org.springframework.util.StringUtils;
public class NullChannel implements PollableChannel, MessageChannelMetrics,
ConfigurableMetricsAware<AbstractMessageChannelMetrics>, 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()) {

View File

@@ -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 <T> 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 <T> the supplier type.
* @return new {@link IntegrationFlowBuilder}.
* @see Supplier
*/
public static <T> IntegrationFlowBuilder from(Supplier<T> messageSource, Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
public static <T> IntegrationFlowBuilder from(Supplier<T> messageSource,
Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
return from(messageSource, "get", endpointConfigurer);
}

View File

@@ -45,6 +45,8 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
private final AtomicLong messageCount = new AtomicLong();
private final ManagementOverrides managementOverrides = new ManagementOverrides();
private volatile Map<String, Expression> headerExpressions = Collections.emptyMap();
private volatile String beanName;
@@ -100,6 +102,7 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
@Override
public void setCountsEnabled(boolean countsEnabled) {
this.countsEnabled = countsEnabled;
this.managementOverrides.countsConfigured = true;
}
@Override
@@ -110,6 +113,7 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
@Override
public void setLoggingEnabled(boolean loggingEnabled) {
this.loggingEnabled = loggingEnabled;
this.managementOverrides.loggingConfigured = true;
}
@Override
@@ -127,6 +131,11 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
return this.messageCount.get();
}
@Override
public ManagementOverrides getOverrides() {
return this.managementOverrides;
}
@Override
public final Message<T> receive() {
return buildMessage(doReceive());

View File

@@ -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),

View File

@@ -53,6 +53,8 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
MessageHandlerMetrics, ConfigurableMetricsAware<AbstractMessageHandlerMetrics>, TrackableComponent, Orderable,
CoreSubscriber<Message<?>> {
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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<String, IntegrationManagement> managed = this.applicationContext.getBeansOfType(IntegrationManagement.class);
for (Entry<String, IntegrationManagement> 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<AbstractMessageChannelMetrics>) 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<AbstractMessageHandlerMetrics>) 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);
}

View File

@@ -182,4 +182,9 @@ public class LifecycleMessageHandlerMetrics implements MessageHandlerMetrics, Li
this.delegate.setManagedType(source);
}
@Override
public ManagementOverrides getOverrides() {
return this.delegate.getOverrides();
}
}

View File

@@ -119,4 +119,9 @@ public class LifecycleMessageSourceMetrics implements MessageSourceMetrics, Life
this.delegate.setManagedType(source);
}
@Override
public ManagementOverrides getOverrides() {
return this.delegate.getOverrides();
}
}

View File

@@ -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<Object>() {
@@ -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<String, IntegrationManagement> beans = new HashMap<String, IntegrationManagement>();
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;
}
}
}

View File

@@ -15,6 +15,7 @@ See <<mgmt-channel-features>> and <<mgmt-handler-features>> 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 `<bean/>` 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]
----
<int:management
default-logging-enabled="false" <1>
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 <<jmx>>), 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