INT-3759: Ability to Disable Logging on Main Path
JIRA: https://jira.spring.io/browse/INT-3759 Add `IntegrationManagementConfigurer` to globally set the default. This will be documented/expanded when JIRAs 3755/3756 are implemented. Polishing; PR Comments Test Polishing
This commit is contained in:
committed by
Artem Bilan
parent
a480354210
commit
9cc0652b61
@@ -29,12 +29,22 @@ public abstract class AbstractAmqpChannel extends AbstractMessageChannel {
|
||||
|
||||
private final AmqpTemplate amqpTemplate;
|
||||
|
||||
private volatile boolean loggingEnabled = true;
|
||||
|
||||
AbstractAmqpChannel(AmqpTemplate amqpTemplate) {
|
||||
Assert.notNull(amqpTemplate, "amqpTemplate must not be null");
|
||||
this.amqpTemplate = amqpTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return this.loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggingEnabled(boolean loggingEnabled) {
|
||||
this.loggingEnabled = loggingEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to return an Exchange name.
|
||||
|
||||
@@ -127,7 +127,7 @@ public class PollableAmqpChannel extends AbstractAmqpChannel implements Pollable
|
||||
boolean counted = false;
|
||||
boolean countsEnabled = isCountsEnabled();
|
||||
try {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (isLoggingEnabled() && logger.isTraceEnabled()) {
|
||||
logger.trace("preReceive on channel '" + this + "'");
|
||||
}
|
||||
if (interceptorList.getInterceptors().size() > 0) {
|
||||
@@ -139,7 +139,7 @@ public class PollableAmqpChannel extends AbstractAmqpChannel implements Pollable
|
||||
}
|
||||
Object object = getAmqpTemplate().receiveAndConvert(this.queueName);
|
||||
if (object == null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (isLoggingEnabled() && logger.isTraceEnabled()) {
|
||||
logger.trace("postReceive on channel '" + this + "', message is null");
|
||||
}
|
||||
return null;
|
||||
@@ -155,7 +155,7 @@ public class PollableAmqpChannel extends AbstractAmqpChannel implements Pollable
|
||||
else {
|
||||
message = getMessageBuilderFactory().withPayload(object).build();
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (isLoggingEnabled() && logger.isDebugEnabled()) {
|
||||
logger.debug("postReceive on channel '" + this + "', message: " + message);
|
||||
}
|
||||
if (interceptorStack != null) {
|
||||
@@ -177,7 +177,7 @@ public class PollableAmqpChannel extends AbstractAmqpChannel implements Pollable
|
||||
|
||||
@Override
|
||||
public Message<?> receive(long timeout) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
if (isLoggingEnabled() && logger.isInfoEnabled()) {
|
||||
logger.info("Calling receive with a timeout value on PollableAmqpChannel. " +
|
||||
"The timeout will be ignored since no receive timeout is supported.");
|
||||
}
|
||||
|
||||
@@ -81,6 +81,8 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
|
||||
|
||||
private volatile boolean statsEnabled;
|
||||
|
||||
private volatile boolean loggingEnabled = true;
|
||||
|
||||
private volatile AbstractMessageChannelMetrics channelMetrics = new DefaultMessageChannelMetrics();
|
||||
|
||||
public AbstractMessageChannel() {
|
||||
@@ -107,7 +109,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
|
||||
|
||||
@Override
|
||||
public boolean isCountsEnabled() {
|
||||
return countsEnabled;
|
||||
return this.countsEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,6 +126,16 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
|
||||
return this.statsEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return this.loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggingEnabled(boolean loggingEnabled) {
|
||||
this.loggingEnabled = loggingEnabled;
|
||||
}
|
||||
|
||||
protected AbstractMessageChannelMetrics getMetrics() {
|
||||
return this.channelMetrics;
|
||||
}
|
||||
@@ -413,7 +425,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
|
||||
if (this.datatypes.length > 0) {
|
||||
message = this.convertPayloadIfNecessary(message);
|
||||
}
|
||||
boolean debugEnabled = logger.isDebugEnabled();
|
||||
boolean debugEnabled = this.loggingEnabled && logger.isDebugEnabled();
|
||||
if (debugEnabled) {
|
||||
logger.debug("preSend on channel '" + this + "', message: " + message);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
|
||||
|
||||
private volatile boolean statsEnabled;
|
||||
|
||||
private volatile boolean loggingEnabled = true;
|
||||
|
||||
private String beanName;
|
||||
|
||||
@Override
|
||||
@@ -61,6 +63,16 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
|
||||
this.channelMetrics = new DefaultMessageChannelMetrics(getComponentName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return this.loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggingEnabled(boolean loggingEnabled) {
|
||||
this.loggingEnabled = loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentName() {
|
||||
return StringUtils.hasText(this.beanName) ? this.beanName: "nullChannel";
|
||||
@@ -186,7 +198,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
|
||||
|
||||
@Override
|
||||
public boolean send(Message<?> message) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (this.loggingEnabled && logger.isDebugEnabled()) {
|
||||
logger.debug("message sent to null channel: " + message);
|
||||
}
|
||||
if (this.countsEnabled) {
|
||||
@@ -202,7 +214,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
|
||||
|
||||
@Override
|
||||
public Message<?> receive() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (this.loggingEnabled && logger.isDebugEnabled()) {
|
||||
logger.debug("receive called on null channel");
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.integration.channel.management;
|
||||
|
||||
import org.springframework.integration.support.management.MetricsEnablement;
|
||||
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;
|
||||
@@ -29,7 +29,7 @@ import org.springframework.jmx.support.MetricType;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface MessageChannelMetrics extends MetricsEnablement {
|
||||
public interface MessageChannelMetrics extends IntegrationStatsManagement {
|
||||
|
||||
/**
|
||||
* @return the number of successful sends
|
||||
|
||||
@@ -55,6 +55,8 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
|
||||
|
||||
private volatile boolean countsEnabled;
|
||||
|
||||
private volatile boolean loggingEnabled = true;
|
||||
|
||||
public void setHeaderExpressions(Map<String, Expression> headerExpressions) {
|
||||
this.headerExpressions = (headerExpressions != null)
|
||||
? headerExpressions : Collections.<String, Expression>emptyMap();
|
||||
@@ -100,6 +102,16 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
|
||||
this.countsEnabled = countsEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return this.loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggingEnabled(boolean loggingEnabled) {
|
||||
this.loggingEnabled = loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.messageCount.set(0);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
package org.springframework.integration.endpoint.management;
|
||||
|
||||
import org.springframework.integration.support.management.CountsEnablement;
|
||||
import org.springframework.integration.support.management.IntegrationManagement;
|
||||
import org.springframework.jmx.export.annotation.ManagedMetric;
|
||||
import org.springframework.jmx.support.MetricType;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.jmx.support.MetricType;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface MessageSourceMetrics extends CountsEnablement {
|
||||
public interface MessageSourceMetrics extends IntegrationManagement {
|
||||
|
||||
/**
|
||||
* @return the number of successful handler calls
|
||||
|
||||
@@ -62,6 +62,18 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
|
||||
|
||||
private volatile String managedType;
|
||||
|
||||
private volatile boolean loggingEnabled = true;
|
||||
|
||||
@Override
|
||||
public boolean isLoggingEnabled() {
|
||||
return this.loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggingEnabled(boolean loggingEnabled) {
|
||||
this.loggingEnabled = loggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
@@ -99,7 +111,7 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
|
||||
public final void handleMessage(Message<?> message) {
|
||||
Assert.notNull(message, "Message must not be null");
|
||||
Assert.notNull(message.getPayload(), "Message payload must not be null");//NOSONAR - false positive
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
if (this.loggingEnabled && this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(this + " received message: " + message);
|
||||
}
|
||||
MetricsContext start = null;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.integration.handler.management;
|
||||
|
||||
import org.springframework.integration.support.management.MetricsEnablement;
|
||||
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;
|
||||
@@ -26,7 +26,7 @@ import org.springframework.jmx.support.MetricType;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface MessageHandlerMetrics extends MetricsEnablement {
|
||||
public interface MessageHandlerMetrics extends IntegrationStatsManagement {
|
||||
|
||||
/**
|
||||
* @return the number of successful handler calls
|
||||
|
||||
@@ -19,13 +19,19 @@ import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
|
||||
/**
|
||||
* Base interface containing methods to control basic statistics gathering.
|
||||
* Base interface for Integration managed components.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.2
|
||||
*
|
||||
*/
|
||||
public interface CountsEnablement {
|
||||
public interface IntegrationManagement {
|
||||
|
||||
@ManagedAttribute(description = "Use to disable debug logging during normal message flow")
|
||||
void setLoggingEnabled(boolean enabled);
|
||||
|
||||
@ManagedAttribute
|
||||
boolean isLoggingEnabled();
|
||||
|
||||
@ManagedOperation
|
||||
void reset();
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configures beans that implement {@link IntegrationManagement}.
|
||||
*
|
||||
* TODO: This class will be expanded by INT-3755/3756.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.2
|
||||
*
|
||||
*/
|
||||
public class IntegrationManagementConfigurer implements SmartInitializingSingleton, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private boolean defaultLoggingEnabled = true;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* subsystem log level configuration.
|
||||
* <p>
|
||||
* Exception logging (debug or otherwise) is not affected by this setting.
|
||||
* <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)}.
|
||||
* @param defaultLoggingEnabled defaults to true.
|
||||
*/
|
||||
public void setDefaultLoggingEnabled(boolean defaultLoggingEnabled) {
|
||||
this.defaultLoggingEnabled = defaultLoggingEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
Assert.state(this.applicationContext != null, "'applicationContext' must not be null");
|
||||
Map<String, IntegrationManagement> managed = this.applicationContext.getBeansOfType(IntegrationManagement.class);
|
||||
for (IntegrationManagement bean : managed.values()) {
|
||||
bean.setLoggingEnabled(this.defaultLoggingEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
* @since 4.2
|
||||
*
|
||||
*/
|
||||
public interface MetricsEnablement extends CountsEnablement {
|
||||
public interface IntegrationStatsManagement extends IntegrationManagement {
|
||||
|
||||
@ManagedOperation(description = "Enable all statistics")
|
||||
void enableStats(boolean statsEnabled);
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.endpoint.AbstractMessageSource;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.router.RecipientListRouter;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 4.2
|
||||
*
|
||||
*/
|
||||
public class IntegrationManagementConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testLogging() {
|
||||
DirectChannel channel = new DirectChannel();
|
||||
AbstractMessageHandler handler = new RecipientListRouter();
|
||||
AbstractMessageSource<?> source = new AbstractMessageSource<Object>() {
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doReceive() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
assertTrue(channel.isLoggingEnabled());
|
||||
assertTrue(handler.isLoggingEnabled());
|
||||
assertTrue(source.isLoggingEnabled());
|
||||
ApplicationContext ctx = mock(ApplicationContext.class);
|
||||
Map<String, IntegrationManagement> beans = new HashMap<String, IntegrationManagement>();
|
||||
beans.put("foo", channel);
|
||||
beans.put("bar", handler);
|
||||
beans.put("baz", source);
|
||||
when(ctx.getBeansOfType(IntegrationManagement.class)).thenReturn(beans);
|
||||
IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer();
|
||||
configurer.setApplicationContext(ctx);
|
||||
configurer.setDefaultLoggingEnabled(false);
|
||||
configurer.afterSingletonsInstantiated();
|
||||
assertFalse(channel.isLoggingEnabled());
|
||||
assertFalse(handler.isLoggingEnabled());
|
||||
assertFalse(source.isLoggingEnabled());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -163,6 +163,16 @@ public class LifecycleMessageHandlerMetrics implements MessageHandlerMetrics, Li
|
||||
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);
|
||||
|
||||
@@ -88,25 +88,31 @@ public class LifecycleMessageSourceMetrics implements MessageSourceMetrics, Life
|
||||
return this.delegate.getMessageCountLong();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enableCounts(boolean countsEnabled) {
|
||||
delegate.enableCounts(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);
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package org.springframework.integration.jmx;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -105,11 +109,18 @@ public class MBeanAttributeFilterTests {
|
||||
Map<String, Object> bean = (Map<String, Object>) payload
|
||||
.get(domain + ":name=in,type=MessageChannel");
|
||||
|
||||
assertEquals(8, bean.size());
|
||||
assertFalse(bean.containsKey("SendCount"));
|
||||
assertFalse(bean.containsKey("SendErrorCount"));
|
||||
assertFalse(bean.containsKey("SendCountLong"));
|
||||
assertFalse(bean.containsKey("SendErrorCountLong"));
|
||||
List<String> keys = new ArrayList<String>(bean.keySet());
|
||||
Collections.sort(keys);
|
||||
System.out.println(keys);
|
||||
assertThat(keys, contains("LoggingEnabled",
|
||||
"MaxSendDuration",
|
||||
"MeanErrorRate",
|
||||
"MeanErrorRatio",
|
||||
"MeanSendDuration",
|
||||
"MeanSendRate",
|
||||
"MinSendDuration",
|
||||
"StandardDeviationSendDuration",
|
||||
"TimeSinceLastSend"));
|
||||
|
||||
adapterNot.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user