INT-3755: Separate Stats Enablement from JMX

JIRA: https://jira.spring.io/browse/INT-3755
JIRA: https://jira.spring.io/browse/INT-3756

Previously JMX was required to enable capturing message counts and statistics.

This is now a separate operation from JMX and can be enabled independently.

For backwards compatibility, enabling JMX will automatically enable statistics
(unless separately configured).

INT-3755: Polishing; PR Comments

Doc Polishing

JavaDocs polishing
This commit is contained in:
Gary Russell
2015-07-02 16:47:07 -04:00
committed by Artem Bilan
parent c68c7b3412
commit 9600006694
44 changed files with 1011 additions and 482 deletions

View File

@@ -100,7 +100,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
}
@Override
public void enableCounts(boolean countsEnabled) {
public void setCountsEnabled(boolean countsEnabled) {
this.countsEnabled = countsEnabled;
if (!countsEnabled) {
this.statsEnabled = false;
@@ -113,7 +113,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
}
@Override
public void enableStats(boolean statsEnabled) {
public void setStatsEnabled(boolean statsEnabled) {
if (statsEnabled) {
this.countsEnabled = true;
}

View File

@@ -95,7 +95,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
}
@Override
public void enableCounts(boolean countsEnabled) {
public void setCountsEnabled(boolean countsEnabled) {
this.countsEnabled = countsEnabled;
if (!countsEnabled) {
this.statsEnabled = false;
@@ -108,7 +108,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
}
@Override
public void enableStats(boolean statsEnabled) {
public void setStatsEnabled(boolean statsEnabled) {
if (statsEnabled) {
this.countsEnabled = true;
}

View File

@@ -102,12 +102,12 @@ public class AggregatorFactoryBean extends AbstractSimpleMessageHandlerFactoryBe
this.aggregator.setChannelResolver(channelResolver);
}
public void enableStats(boolean statsEnabled) {
this.aggregator.enableStats(statsEnabled);
public void setStatsEnabled(boolean statsEnabled) {
this.aggregator.setStatsEnabled(statsEnabled);
}
public void enableCounts(boolean countsEnabled) {
this.aggregator.enableCounts(countsEnabled);
public void setCountsEnabled(boolean countsEnabled) {
this.aggregator.setCountsEnabled(countsEnabled);
}
public void setLockRegistry(LockRegistry lockRegistry) {

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2014-2015 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.integration.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.integration.support.management.IntegrationManagement;
import org.springframework.integration.support.management.IntegrationManagementConfigurer;
/**
* Enables default configuring of management in Spring Integration components in an existing application.
*
* <p>The resulting {@link IntegrationManagementConfigurer}
* bean is defined under the name {@code integrationManagementConfigurer}.
*
* @author Gary Russell
* @since 4.2
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(IntegrationManagementConfiguration.class)
public @interface EnableIntegrationManagement {
/**
* A list of simple patterns for component names for which message counts will be
* enabled (defaults to '*'). Enables message
* counting (`sendCount`, `errorCount`, `receiveCount`) for those components that
* support counters (channels, message handlers, etc). This is the initial setting
* only, individual components can have counts enabled/disabled at runtime. May be
* overridden by an entry in {@link #statsEnabled() statsEnabled} which is additional
* functionality over simple counts. If a pattern starts with `!`, counts are disabled
* for matches. For components that match multiple patterns, the first pattern wins.
* Disabling counts at runtime also disables stats.
* Defaults to no components, unless JMX is enabled in which case, defaults to all
* components. Overrides {@link #defaultCountsEnabled()} for matching bean names.
* @return the patterns.
*/
String[] countsEnabled() default "";
/**
* A list of simple patterns for component names for which message statistics will be
* enabled (response times, rates etc), as well as counts (a positive match here
* overrides {@link #countsEnabled() countsEnabled}, you can't have statistics without
* counts). (defaults to '*'). Enables
* statistics for those components that support statistics (channels - when sending,
* message handlers, etc). This is the initial setting only, individual components can
* have stats enabled/disabled at runtime. If a pattern starts with `!`, stats (and
* counts) are disabled for matches. Note: this means that '!foo' here will disable
* stats and counts for 'foo' even if counts are enabled for 'foo' in
* {@link #countsEnabled() countsEnabled}. For components
* that match multiple patterns, the first pattern wins. Enabling stats at runtime
* also enables counts.
* Defaults to no components, unless JMX is enabled in which case, defaults to all
* components.
* @return the patterns.
*/
String[] statsEnabled() default "";
/**
* The default setting for enabling counts when a bean name is not matched by
* {@link #countsEnabled() countsEnabled}.
* @return the value; false by default, or true when JMX is enabled.
*/
String defaultCountsEnabled() default "false";
/**
* The default setting for enabling statistics when a bean name is not matched by
* {@link #statsEnabled() statsEnabled}.
* @return the value; false by default, or true when JMX is enabled.
*/
String defaultStatsEnabled() default "false";
/**
* Use to disable all logging in the main message flow in framework components. When 'false', such logging will be
* skipped, regardless of logging level. When 'true', the logging is controlled as normal by the logging
* subsystem log level configuration.
* <p>
* It has been found that in high-volume messaging environments, calls to methods such as
* {@code logger.isDebuggingEnabled()} can be quite expensive and account for an inordinate amount of CPU
* time.
* <p>
* Set this to false to disable logging by default in all framework components that implement
* {@link IntegrationManagement} (channels, message handlers etc). This turns off logging such as
* "PreSend on channel", "Received message" etc.
* <p>
* After the context is initialized, individual components can have their setting changed by invoking
* {@link IntegrationManagement#setLoggingEnabled(boolean)}.
* @return the value; true by default.
*/
String defaultLoggingEnabled() default "true";
/**
* The bean name of a {@code MetricsFactory}. The {@code DefaultMetricsFactory} is used
* if omitted.
* @return the bean name.
*/
String metricsFactory() default "";
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2015 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.integration.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.integration.support.management.IntegrationManagementConfigurer;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@code @Configuration} class that registers a {@link IntegrationManagementConfigurer} bean.
*
* <p>This configuration class is automatically imported when using the
* {@link EnableIntegrationManagement} annotation. See its javadoc for complete usage details.
*
* @author Artem Bilan
* @author Gary Russell
* @since 4.2
*/
@Configuration
public class IntegrationManagementConfiguration implements ImportAware, EnvironmentAware {
private AnnotationAttributes attributes;
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableIntegrationManagement.class.getName());
this.attributes = AnnotationAttributes.fromMap(map);
Assert.notNull(this.attributes,
"@EnableIntegrationManagement is not present on importing class " + importMetadata.getClassName());
}
@Bean(name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public IntegrationManagementConfigurer managementConfigurer() {
IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer();
setupCountsEnabledNamePatterns(configurer);
setupStatsEnabledNamePatterns(configurer);
configurer.setDefaultLoggingEnabled(
Boolean.parseBoolean(this.environment.resolvePlaceholders(
(String) this.attributes.get("defaultLoggingEnabled"))));
configurer.setDefaultCountsEnabled(
Boolean.parseBoolean(this.environment.resolvePlaceholders(
(String) this.attributes.get("defaultCountsEnabled"))));
configurer.setDefaultStatsEnabled(
Boolean.parseBoolean(this.environment.resolvePlaceholders(
(String) this.attributes.get("defaultStatsEnabled"))));
configurer.setMetricsFactoryBeanName((String) this.attributes.get("metricsFactory"));
return configurer;
}
private void setupCountsEnabledNamePatterns(IntegrationManagementConfigurer configurer) {
List<String> patterns = new ArrayList<String>();
String[] countsEnabled = this.attributes.getStringArray("countsEnabled");
for (String managedComponent : countsEnabled) {
String pattern = this.environment.resolvePlaceholders(managedComponent);
patterns.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(pattern)));
}
configurer.setEnabledCountsPatterns(patterns.toArray(new String[patterns.size()]));
}
private void setupStatsEnabledNamePatterns(IntegrationManagementConfigurer exporter) {
List<String> patterns = new ArrayList<String>();
String[] statsEnabled = this.attributes.getStringArray("statsEnabled");
for (String managedComponent : statsEnabled) {
String pattern = this.environment.resolvePlaceholders(managedComponent);
patterns.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(pattern)));
}
exporter.setEnabledStatsPatterns(patterns.toArray(new String[patterns.size()]));
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2015 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.integration.config.xml;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.support.management.IntegrationManagementConfigurer;
import org.w3c.dom.Element;
/**
* Parser for the &lt;management/&gt; element.
*
* @author Gary Russell
* @since 4.2
*/
public class IntegrationManagementParser extends AbstractBeanDefinitionParser {
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
return IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME;
}
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(IntegrationManagementConfigurer.class);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-logging-enabled");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-counts-enabled");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-stats-enabled");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "counts-enabled-patterns",
"enabledCountsPatterns");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "stats-enabled-patterns",
"enabledStatsPatterns");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "metrics-factory");
return builder.getBeanDefinition();
}
@Override
protected boolean shouldFireEvents() {
return false;
}
}

View File

@@ -83,6 +83,7 @@ public class IntegrationNamespaceHandler extends AbstractIntegrationNamespaceHan
registerBeanDefinitionParser("retry-advice", retryParser);
registerBeanDefinitionParser("scatter-gather", new ScatterGatherParser());
registerBeanDefinitionParser("idempotent-receiver", new IdempotentReceiverInterceptorParser());
registerBeanDefinitionParser("management", new IntegrationManagementParser());
}
}

View File

@@ -24,10 +24,10 @@ import java.util.concurrent.atomic.AtomicLong;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.expression.Expression;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.endpoint.management.MessageSourceMetrics;
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
import org.springframework.integration.support.context.NamedComponent;
import org.springframework.integration.support.management.IntegrationManagedResource;
import org.springframework.integration.support.management.MessageSourceMetrics;
import org.springframework.integration.util.AbstractExpressionEvaluator;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
@@ -98,7 +98,7 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
}
@Override
public void enableCounts(boolean countsEnabled) {
public void setCountsEnabled(boolean countsEnabled) {
this.countsEnabled = countsEnabled;
}

View File

@@ -21,11 +21,11 @@ import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.context.Orderable;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
import org.springframework.integration.handler.management.DefaultMessageHandlerMetrics;
import org.springframework.integration.handler.management.MessageHandlerMetrics;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.integration.support.management.ConfigurableMetricsAware;
import org.springframework.integration.support.management.IntegrationManagedResource;
import org.springframework.integration.support.management.MessageHandlerMetrics;
import org.springframework.integration.support.management.MetricsContext;
import org.springframework.integration.support.management.Statistics;
import org.springframework.messaging.Message;
@@ -203,7 +203,7 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
}
@Override
public void enableStats(boolean statsEnabled) {
public void setStatsEnabled(boolean statsEnabled) {
if (statsEnabled) {
this.countsEnabled = true;
}
@@ -219,7 +219,7 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
}
@Override
public void enableCounts(boolean countsEnabled) {
public void setCountsEnabled(boolean countsEnabled) {
this.countsEnabled = countsEnabled;
if (!countsEnabled) {
this.statsEnabled = false;

View File

@@ -20,11 +20,12 @@ import org.springframework.integration.support.management.ExponentialMovingAvera
import org.springframework.integration.support.management.MetricsContext;
/**
* An implementation of {@link MessageHandlerMetrics} that aggregates the total response
* An implementation of {@link org.springframework.integration.support.management.MessageHandlerMetrics}
* that aggregates the total response
* time over a sample, to avoid fetching the system time twice for every message.
*
* @author Gary Russell
* @since 2.0
* @since 4.2
*/
public class AggregatingMessageHandlerMetrics extends DefaultMessageHandlerMetrics {

View File

@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.support.management.MappingMessageRouterManagement;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.messaging.Message;

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.integration.channel.management.AbstractMessageChannelMetrics;
import org.springframework.integration.channel.management.AggregatingMessageChannelMetrics;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
import org.springframework.integration.handler.management.AggregatingMessageHandlerMetrics;
/**
* Implementation that returns aggregating metrics.
*
* @author Gary Russell
* @since 4.2
*
*/
public class AggregatingMetricsFactory implements MetricsFactory {
private final int sampleSize;
/**
* @param sampleSize the number of messages over which to aggregate the elapsed time.
*/
public AggregatingMetricsFactory(int sampleSize) {
this.sampleSize = sampleSize;
}
@Override
public AbstractMessageChannelMetrics createChannelMetrics(String name) {
return new AggregatingMessageChannelMetrics(name, this.sampleSize);
}
@Override
public AbstractMessageHandlerMetrics createHandlerMetrics(String name) {
return new AggregatingMessageHandlerMetrics(name, this.sampleSize);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.integration.channel.management.AbstractMessageChannelMetrics;
import org.springframework.integration.channel.management.DefaultMessageChannelMetrics;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
import org.springframework.integration.handler.management.DefaultMessageHandlerMetrics;
/**
* Default implementation.
*
* @author Gary Russell
* @since 4.2
*
*/
public class DefaultMetricsFactory implements MetricsFactory {
@Override
public AbstractMessageChannelMetrics createChannelMetrics(String name) {
return new DefaultMessageChannelMetrics(name);
}
@Override
public AbstractMessageHandlerMetrics createHandlerMetrics(String name) {
return new DefaultMessageHandlerMetrics(name);
}
}

View File

@@ -36,8 +36,8 @@ public interface IntegrationManagement {
@ManagedOperation
void reset();
@ManagedOperation(description = "Enable message counting statistics")
void enableCounts(boolean countsEnabled);
@ManagedAttribute(description = "Enable message counting statistics")
void setCountsEnabled(boolean countsEnabled);
@ManagedAttribute
boolean isCountsEnabled();

View File

@@ -15,34 +15,141 @@
*/
package org.springframework.integration.support.management;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.BeansException;
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.channel.management.AbstractMessageChannelMetrics;
import org.springframework.integration.channel.management.MessageChannelMetrics;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
/**
* Configures beans that implement {@link IntegrationManagement}.
*
* TODO: This class will be expanded by INT-3755/3756.
* Configures counts, stats, logging for all (or selected) components.
*
* @author Gary Russell
* @since 4.2
*
*/
public class IntegrationManagementConfigurer implements SmartInitializingSingleton, ApplicationContextAware {
public class IntegrationManagementConfigurer implements SmartInitializingSingleton, ApplicationContextAware,
BeanNameAware {
public static final String MANAGEMENT_CONFIGURER_NAME = "integrationManagementConfigurer";
private ApplicationContext applicationContext;
private String beanName;
private boolean defaultLoggingEnabled = true;
private Boolean defaultCountsEnabled = false;
private Boolean defaultStatsEnabled = false;
private MetricsFactory metricsFactory = new DefaultMetricsFactory();
private String metricsFactoryBeanName;
private String[] enabledCountsPatterns = { };
private String[] enabledStatsPatterns = { };
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
/**
* Set a metrics factory.
* @param metricsFactory the factory.
* @since 4.2
*/
public void setMetricsFactory(MetricsFactory metricsFactory) {
this.metricsFactory = metricsFactory;
}
public void setMetricsFactoryBeanName(String metricsFactory) {
this.metricsFactoryBeanName = metricsFactory;
}
/**
* Set the array of simple patterns for component names for which message counts will
* be enabled (defaults to '*').
* Enables message counting (`sendCount`, `errorCount`, `receiveCount`)
* for those components that support counters (channels, message handlers, etc).
* This is the initial setting only, individual components can have counts
* enabled/disabled at runtime. May be overridden by an entry in
* {@link #setEnabledStatsPatterns(String[]) enabledStatsPatterns} which is additional
* functionality over simple counts. If a pattern starts with `!`, counts are disabled
* for matches. For components that match multiple patterns, the first pattern wins.
* Disabling counts at runtime also disables stats.
* @param enabledCountsPatterns the patterns.
*/
public void setEnabledCountsPatterns(String[] enabledCountsPatterns) {
Assert.notEmpty(enabledCountsPatterns, "enabledCountsPatterns must not be empty");
this.enabledCountsPatterns = Arrays.copyOf(enabledCountsPatterns, enabledCountsPatterns.length);
}
/**
* Set the array of simple patterns for component names for which message statistics
* will be enabled (response times, rates etc), as well as counts (a positive match
* here overrides {@link #setEnabledCountsPatterns(String[]) enabledCountsPatterns},
* you can't have statistics without counts). (defaults to '*').
* Enables statistics for those components that support statistics
* (channels - when sending, message handlers, etc). This is the initial setting only,
* individual components can have stats enabled/disabled at runtime. If a pattern
* starts with `!`, stats (and counts) are disabled for matches. Note: this means that
* '!foo' here will disable stats and counts for 'foo' even if counts are enabled for
* 'foo' in {@link #setEnabledCountsPatterns(String[]) enabledCountsPatterns}. For
* components that match multiple patterns, the first pattern wins. Enabling stats at
* runtime also enables counts.
* @param enabledStatsPatterns the patterns.
*/
public void setEnabledStatsPatterns(String[] enabledStatsPatterns) {
Assert.notEmpty(enabledStatsPatterns, "componentNamePatterns must not be empty");
this.enabledStatsPatterns = Arrays.copyOf(enabledStatsPatterns, enabledStatsPatterns.length);
}
/**
* Set whether managed components maintain message counts by default.
* Defaults to false, unless an Integration MBean Exporter is configured.
* @param defaultCountsEnabled true to enable.
*/
public void setDefaultCountsEnabled(Boolean defaultCountsEnabled) {
this.defaultCountsEnabled = defaultCountsEnabled;
}
public Boolean getDefaultCountsEnabled() {
return defaultCountsEnabled;
}
/**
* Set whether managed components maintain message statistics by default.
* Defaults to false, unless an Integration MBean Exporter is configured.
* @param defaultStatsEnabled true to enable.
*/
public void setDefaultStatsEnabled(Boolean defaultStatsEnabled) {
this.defaultStatsEnabled = defaultStatsEnabled;
}
public Boolean getDefaultStatsEnabled() {
return defaultStatsEnabled;
}
/**
* Disable all logging in the normal message flow in framework components. When 'false', such logging will be
* skipped, regardless of logging level. When 'true', the logging is controlled as normal by the logging
@@ -69,10 +176,133 @@ public class IntegrationManagementConfigurer implements SmartInitializingSinglet
@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 (this.metricsFactoryBeanName != null) {
this.metricsFactory = this.applicationContext.getBean(this.metricsFactoryBeanName, MetricsFactory.class);
}
Map<String, IntegrationManagement> managed = this.applicationContext.getBeansOfType(IntegrationManagement.class);
for (IntegrationManagement bean : managed.values()) {
for (Entry<String, IntegrationManagement> entry : managed.entrySet()) {
IntegrationManagement bean = entry.getValue();
bean.setLoggingEnabled(this.defaultLoggingEnabled);
if (bean instanceof MessageChannelMetrics) {
configureChannelMetrics(entry.getKey(), (MessageChannelMetrics) bean);
}
else if (bean instanceof MessageHandlerMetrics) {
configureHandlerMetrics(entry.getKey(), (MessageHandlerMetrics) bean);
}
else if (bean instanceof MessageSourceMetrics) {
configureSourceMetrics(entry.getKey(), (MessageSourceMetrics) bean);
}
}
}
@SuppressWarnings("unchecked")
private void configureChannelMetrics(String name, MessageChannelMetrics bean) {
AbstractMessageChannelMetrics metrics = this.metricsFactory.createChannelMetrics(name);
Assert.state(metrics != null, "'metrics' must not be null");
Boolean enabled = smartMatch(this.enabledCountsPatterns, name);
if (enabled != null) {
bean.setCountsEnabled(enabled);
}
else {
bean.setCountsEnabled(this.defaultCountsEnabled);
}
enabled = smartMatch(this.enabledStatsPatterns, name);
if (enabled != null) {
bean.setStatsEnabled(enabled);
metrics.setFullStatsEnabled(enabled);
}
else {
bean.setStatsEnabled(this.defaultStatsEnabled);
metrics.setFullStatsEnabled(this.defaultStatsEnabled);
}
if (bean instanceof ConfigurableMetricsAware) {
((ConfigurableMetricsAware<AbstractMessageChannelMetrics>) bean).configureMetrics(metrics);
}
}
@SuppressWarnings("unchecked")
private void configureHandlerMetrics(String name, MessageHandlerMetrics bean) {
AbstractMessageHandlerMetrics metrics = this.metricsFactory.createHandlerMetrics(name);
Assert.state(metrics != null, "'metrics' must not be null");
Boolean enabled = smartMatch(this.enabledCountsPatterns, name);
if (enabled != null) {
bean.setCountsEnabled(enabled);
}
else {
bean.setCountsEnabled(this.defaultCountsEnabled);
}
enabled = smartMatch(this.enabledStatsPatterns, name);
if (enabled != null) {
bean.setStatsEnabled(enabled);
metrics.setFullStatsEnabled(enabled);
}
else {
bean.setStatsEnabled(this.defaultStatsEnabled);
metrics.setFullStatsEnabled(this.defaultStatsEnabled);
}
if (bean instanceof ConfigurableMetricsAware) {
((ConfigurableMetricsAware<AbstractMessageHandlerMetrics>) bean).configureMetrics(metrics);
}
}
private void configureSourceMetrics(String name, MessageSourceMetrics bean) {
Boolean enabled = smartMatch(this.enabledCountsPatterns, name);
if (enabled != null) {
bean.setCountsEnabled(enabled);
}
else {
bean.setCountsEnabled(this.defaultCountsEnabled);
}
}
/**
* Simple pattern match against the supplied patterns; also supports negated ('!')
* patterns. First match wins (positive or negative).
* @param patterns the patterns.
* @param name the name to match.
* @return null if no match; true for positive match; false for negative match.
*/
private Boolean smartMatch(String[] patterns, String name) {
if (patterns != null) {
for (String pattern : patterns) {
boolean reverse = false;
String patternToUse = pattern;
if (pattern.startsWith("!")) {
reverse = true;
patternToUse = pattern.substring(1);
}
else if (pattern.startsWith("\\")) {
patternToUse = pattern.substring(1);
}
if (PatternMatchUtils.simpleMatch(patternToUse, name)) {
return !reverse;
}
}
}
return null;
}
public MessageChannelMetrics getChannelMetrics(String name) {
if (this.applicationContext.containsBean(name)) {
return this.applicationContext.getBean(name, MessageChannelMetrics.class);
}
return null;
}
public MessageHandlerMetrics getHandlerMetrics(String name) {
if (this.applicationContext.containsBean(name)) {
return this.applicationContext.getBean(name, MessageHandlerMetrics.class);
}
return null;
}
public MessageSourceMetrics getSourceMetrics(String name) {
if (this.applicationContext.containsBean(name)) {
return this.applicationContext.getBean(name, MessageSourceMetrics.class);
}
return null;
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.integration.support.management;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
@@ -28,8 +27,8 @@ import org.springframework.jmx.export.annotation.ManagedOperation;
*/
public interface IntegrationStatsManagement extends IntegrationManagement {
@ManagedOperation(description = "Enable all statistics")
void enableStats(boolean statsEnabled);
@ManagedAttribute(description = "Enable all statistics")
void setStatsEnabled(boolean statsEnabled);
@ManagedAttribute
boolean isStatsEnabled();

View File

@@ -0,0 +1,182 @@
/*
* Copyright 2002-2015 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.integration.support.management;
import org.springframework.context.Lifecycle;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* A {@link MessageHandlerMetrics} that exposes in addition the {@link Lifecycle} interface. The lifecycle methods can
* be used to stop and start polling endpoints, for instance, in a live system.
*
* @author Dave Syer
* @author Gary Russell
* @since 2.0
*/
@IntegrationManagedResource
public class LifecycleMessageHandlerMetrics implements MessageHandlerMetrics, Lifecycle,
ConfigurableMetricsAware<AbstractMessageHandlerMetrics> {
private final Lifecycle lifecycle;
protected final MessageHandlerMetrics delegate;
public LifecycleMessageHandlerMetrics(Lifecycle lifecycle, MessageHandlerMetrics delegate) {
this.lifecycle = lifecycle;
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
@Override
public void configureMetrics(AbstractMessageHandlerMetrics metrics) {
if (this.delegate instanceof ConfigurableMetricsAware) {
((ConfigurableMetricsAware<AbstractMessageHandlerMetrics>) this.delegate).configureMetrics(metrics);
}
}
@Override
@ManagedAttribute
public boolean isRunning() {
return this.lifecycle.isRunning();
}
@Override
@ManagedOperation
public void start() {
this.lifecycle.start();
}
@Override
@ManagedOperation
public void stop() {
this.lifecycle.stop();
}
@Override
public void reset() {
this.delegate.reset();
}
@Override
public int getErrorCount() {
return this.delegate.getErrorCount();
}
@Override
public int getHandleCount() {
return this.delegate.getHandleCount();
}
@Override
public double getMaxDuration() {
return this.delegate.getMaxDuration();
}
@Override
public double getMeanDuration() {
return this.delegate.getMeanDuration();
}
@Override
public double getMinDuration() {
return this.delegate.getMinDuration();
}
@Override
public double getStandardDeviationDuration() {
return this.delegate.getStandardDeviationDuration();
}
@Override
public Statistics getDuration() {
return this.delegate.getDuration();
}
@Override
public String getManagedName() {
return this.delegate.getManagedName();
}
@Override
public String getManagedType() {
return this.delegate.getManagedType();
}
@Override
public int getActiveCount() {
return this.delegate.getActiveCount();
}
@Override
public long getHandleCountLong() {
return this.delegate.getHandleCountLong();
}
@Override
public long getErrorCountLong() {
return this.delegate.getErrorCountLong();
}
@Override
public long getActiveCountLong() {
return this.delegate.getActiveCountLong();
}
@Override
public void setStatsEnabled(boolean statsEnabled) {
this.delegate.setStatsEnabled(statsEnabled);
}
@Override
public void setCountsEnabled(boolean countsEnabled) {
this.delegate.setCountsEnabled(countsEnabled);
}
@Override
public boolean isStatsEnabled() {
return this.delegate.isStatsEnabled();
}
@Override
public boolean isCountsEnabled() {
return this.delegate.isCountsEnabled();
}
@Override
public void setLoggingEnabled(boolean enabled) {
this.delegate.setLoggingEnabled(enabled);
}
@Override
public boolean isLoggingEnabled() {
return this.delegate.isLoggingEnabled();
}
@Override
public void setManagedName(String name) {
this.delegate.setManagedName(name);
}
@Override
public void setManagedType(String source) {
this.delegate.setManagedType(source);
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2002-2015 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.integration.support.management;
import org.springframework.context.Lifecycle;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* A {@link MessageSourceMetrics} that exposes in addition the {@link Lifecycle} interface. The lifecycle methods can
* be used to start and stop polling endpoints, for instance, in a live system.
*
* @author Dave Syer
* @author Gary Russell
* @since 2.0
*/
@IntegrationManagedResource
public class LifecycleMessageSourceMetrics implements MessageSourceMetrics, Lifecycle {
private final Lifecycle lifecycle;
private final MessageSourceMetrics delegate;
public LifecycleMessageSourceMetrics(Lifecycle lifecycle, MessageSourceMetrics delegate) {
this.lifecycle = lifecycle;
this.delegate = delegate;
}
@Override
@ManagedOperation
public void reset() {
this.delegate.reset();
}
@Override
@ManagedAttribute
public boolean isRunning() {
return this.lifecycle.isRunning();
}
@Override
@ManagedOperation
public void start() {
this.lifecycle.start();
}
@Override
@ManagedOperation
public void stop() {
this.lifecycle.stop();
}
@Override
public String getManagedName() {
return this.delegate.getManagedName();
}
@Override
public String getManagedType() {
return this.delegate.getManagedType();
}
@Override
public int getMessageCount() {
return this.delegate.getMessageCount();
}
@Override
public long getMessageCountLong() {
return this.delegate.getMessageCountLong();
}
@Override
public void setCountsEnabled(boolean countsEnabled) {
delegate.setCountsEnabled(countsEnabled);
}
@Override
public boolean isCountsEnabled() {
return delegate.isCountsEnabled();
}
@Override
public void setLoggingEnabled(boolean enabled) {
delegate.setLoggingEnabled(enabled);
}
@Override
public boolean isLoggingEnabled() {
return delegate.isLoggingEnabled();
}
@Override
public void setManagedName(String name) {
delegate.setManagedName(name);
}
@Override
public void setManagedType(String source) {
delegate.setManagedType(source);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.context.Lifecycle;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.util.Assert;
/**
* Adds {@link TrackableComponent}.
*
* @author Gary Russell
* @since 4.2
*/
@IntegrationManagedResource
public class LifecycleTrackableMessageHandlerMetrics extends LifecycleMessageHandlerMetrics
implements TrackableComponent {
private final TrackableComponent trackable;
public LifecycleTrackableMessageHandlerMetrics(Lifecycle lifecycle, MessageHandlerMetrics delegate) {
super(lifecycle, delegate);
Assert.isInstanceOf(TrackableComponent.class, delegate);
this.trackable = (TrackableComponent) delegate;
}
@Override
public String getComponentName() {
return this.trackable.getComponentName();
}
@Override
public String getComponentType() {
return this.trackable.getComponentType();
}
@Override
public void setShouldTrack(boolean shouldTrack) {
this.trackable.setShouldTrack(shouldTrack);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.context.Lifecycle;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.util.Assert;
/**
* Adds {@link TrackableComponent}.
*
* @author Gary Russell
* @since 2.0
*/
@IntegrationManagedResource
public class LifecycleTrackableMessageSourceMetrics extends LifecycleMessageSourceMetrics
implements TrackableComponent {
private final TrackableComponent trackable;
public LifecycleTrackableMessageSourceMetrics(Lifecycle lifecycle, MessageSourceMetrics delegate) {
super(lifecycle, delegate);
Assert.isInstanceOf(TrackableComponent.class, lifecycle);
this.trackable = (TrackableComponent) lifecycle;
}
@Override
public String getComponentName() {
return this.trackable.getComponentName();
}
@Override
public String getComponentType() {
return this.trackable.getComponentType();
}
@Override
public void setShouldTrack(boolean shouldTrack) {
this.trackable.setShouldTrack(shouldTrack);
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.router;
package org.springframework.integration.support.management;
import java.util.Map;
import java.util.Properties;

View File

@@ -14,10 +14,8 @@
* limitations under the License.
*/
package org.springframework.integration.handler.management;
package org.springframework.integration.support.management;
import org.springframework.integration.support.management.IntegrationStatsManagement;
import org.springframework.integration.support.management.Statistics;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.support.MetricType;

View File

@@ -11,9 +11,8 @@
* specific language governing permissions and limitations under the License.
*/
package org.springframework.integration.endpoint.management;
package org.springframework.integration.support.management;
import org.springframework.integration.support.management.IntegrationManagement;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.support.MetricType;

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.integration.channel.management.AbstractMessageChannelMetrics;
import org.springframework.integration.handler.management.AbstractMessageHandlerMetrics;
/**
* Factories implementing this interface provide metric objects for message channels and
* message handlers.
*
* @author Gary Russell
* @since 4.2
*
*/
public interface MetricsFactory {
/**
* Factory method to create an {@link AbstractMessageChannelMetrics}.
* @param name the name.
* @return the metrics.
*/
AbstractMessageChannelMetrics createChannelMetrics(String name);
/**
* Factory method to create an {@link AbstractMessageHandlerMetrics}.
* @param name the name.
* @return the metrics.
*/
AbstractMessageHandlerMetrics createHandlerMetrics(String name);
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2015 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.integration.support.management;
import java.util.Map;
import java.util.Properties;
import org.springframework.context.Lifecycle;
/**
* Allows Router operations to appear in the same MBean as statistics.
*
* @author Gary Russell
* @since 4.2
*
*/
public class RouterMetrics extends LifecycleMessageHandlerMetrics implements MappingMessageRouterManagement {
private final MappingMessageRouterManagement router;
public RouterMetrics(Lifecycle lifecycle, MappingMessageRouterManagement delegate) {
super(lifecycle, (MessageHandlerMetrics) delegate);
this.router = delegate;
}
@Override
public void setChannelMapping(String key, String channelName) {
this.router.setChannelMapping(key, channelName);
}
@Override
public void removeChannelMapping(String key) {
this.router.removeChannelMapping(key);
}
@Override
public void replaceChannelMappings(Properties channelMappings) {
this.router.replaceChannelMappings(channelMappings);
}
@Override
public Map<String, String> getChannelMappings() {
return this.router.getChannelMappings();
}
@Override
public void setChannelMappings(Map<String, String> channelMappings) {
this.router.setChannelMappings(channelMappings);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2015 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.integration.support.management;
import org.springframework.context.Lifecycle;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.util.Assert;
/**
* Adds {@link TrackableComponent}.
*
* @author Gary Russell
* @since 2.0
*/
public class TrackableRouterMetrics extends RouterMetrics implements TrackableComponent {
private final TrackableComponent trackable;
public TrackableRouterMetrics(Lifecycle lifecycle, MappingMessageRouterManagement delegate) {
super(lifecycle, delegate);
Assert.isInstanceOf(TrackableComponent.class, delegate);
this.trackable = (TrackableComponent) delegate;
}
@Override
public String getComponentName() {
return this.trackable.getComponentName();
}
@Override
public String getComponentType() {
return this.trackable.getComponentType();
}
@Override
public void setShouldTrack(boolean shouldTrack) {
this.trackable.setShouldTrack(shouldTrack);
}
}

View File

@@ -4482,6 +4482,82 @@ The list of component name patterns you want to track (e.g., tracked-components
</xsd:complexType>
</xsd:element>
<xsd:element name="management">
<xsd:complexType>
<xsd:attribute name="default-logging-enabled" use="optional">
<xsd:annotation>
<xsd:documentation>
Set false, to disable all main-path debug logging for components that implement
'IntegrationManagement' (channels, message handlers etc). For high-volume environments
avoiding calls to 'isDebuggingEnabled()` can improve performance.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="default-counts-enabled" use="optional">
<xsd:annotation>
<xsd:documentation>
The default value for components that don't match 'counts-enabled-patterns'.
Defaults to false, or true when an Integration MBean Exporter is provided.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="default-stats-enabled" use="optional">
<xsd:annotation>
<xsd:documentation>
The default value for components that don't match 'stats-enabled-patterns'.
Defaults to false, or true when an Integration MBean Exporter is provided.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="counts-enabled-patterns" use="optional">
<xsd:annotation>
<xsd:documentation>
Comma separated list of simple patterns for component names for which message counts
will be enabled (defaults to '*'). Only patterns that also match 'managed-components'
will be considered. Enables message counting (`sendCount`, `errorCount`, `receiveCount`)
for those components that support counters (channels, message handlers, etc).
This is the initial setting only, individual components can have counts enabled/disabled
at runtime. May be overridden by an entry in 'stats-enabled' which is additional
functionality over simple counts. If a pattern starts with `!`, counts are disabled
for matches. For components with names that match multiple patterns, the first pattern wins.
Disabling counts at runtime also disables stats.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="stats-enabled-patterns" use="optional">
<xsd:annotation>
<xsd:documentation>
Comma separated list of simple patterns for component names for which message statistics
will be enabled (response times, rates etc), as well as counts (a positive match here
overrides `counts-enabled`, you can't have statistics without counts).
(defaults to '*'). Only patterns that also match 'managed-components'
will be considered. Enables statistics for those components that support
statistics (channels - when sending, message handlers, etc).
This is the initial setting only, individual components can have stats enabled/disabled
at runtime. If a pattern starts with `!`, stats (and counts) are disabled
for matches. Note: this means that '!foo' here will disable stats
and counts for 'foo' even if counts are enabled for 'foo' in 'counts-enabled'.
For components with names that match multiple patterns, the first pattern wins.
Enabling stats at runtime also enables counts.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="metrics-factory" use="optional">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.support.management.MetricsFactory" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
A MetricsFactory responsible for creating objects that maintain metrics for message
channels and message handlers.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="control-bus-type">
<xsd:annotation>
<xsd:documentation><![CDATA[

View File

@@ -64,6 +64,7 @@ public class IntegrationManagementConfigurerTests {
beans.put("baz", source);
when(ctx.getBeansOfType(IntegrationManagement.class)).thenReturn(beans);
IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer();
configurer.setBeanName(IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME);
configurer.setApplicationContext(ctx);
configurer.setDefaultLoggingEnabled(false);
configurer.afterSingletonsInstantiated();