INT-3636: JMX Eliminate Channel Metric Proxies

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

- Add `enableStats()` managed operation
- Delegate to a channel metrics object instead of using a proxy

INT-3636: Polishing; PR Comments

Change field name in `MBeanExporterHelper`.

INT-3636: Polishing
This commit is contained in:
Gary Russell
2015-02-17 13:54:18 +02:00
committed by Artem Bilan
parent 8c81cffd27
commit b07686cdc0
29 changed files with 525 additions and 243 deletions

View File

@@ -64,6 +64,7 @@
<value type="java.lang.String">SendCountLong</value>
<value type="java.lang.String">SendErrorCount</value>
<value type="java.lang.String">SendErrorCountLong</value>
<value type="java.lang.String">StatsEnabled</value>
</array>
</constructor-arg>
</bean>

View File

@@ -21,16 +21,15 @@ import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.messaging.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -95,7 +94,6 @@ public class DynamicRouterTests {
}
@Test @DirtiesContext
@Ignore // Requires Spring 3.2.3 TODO: Remove when minimum SF is >= 3.2.3
public void testRouteChangeMapNamedArgs() throws Exception {
routingChannel.send(new GenericMessage<String>("123"));
assertEquals("123", processAChannel.receive(0).getPayload());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* 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.
@@ -33,7 +33,6 @@ import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextInitializer;
@@ -42,7 +41,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.integration.test.util.TestUtils;
@@ -54,6 +52,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Artem Bilan
* @author Gary Russell
* @since 4.0
*/
@ContextConfiguration(initializers = EnableMBeanExportTests.EnvironmentApplicationContextInitializer.class)
@@ -73,8 +72,6 @@ public class EnableMBeanExportTests {
@SuppressWarnings("unchecked")
@Test
public void testEnableMBeanExport() throws MalformedObjectNameException, ClassNotFoundException {
assertTrue(AopUtils.isAopProxy(this.beanFactory.getBean(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)));
assertTrue(AopUtils.isAopProxy(this.beanFactory.getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)));
assertSame(this.mBeanServer, this.exporter.getServer());
String[] componentNamePatterns = TestUtils.getPropertyValue(this.exporter, "componentNamePatterns", String[].class);

View File

@@ -1,129 +0,0 @@
/*
* Copyright 2002-2013 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.monitor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.test.util.TestUtils;
/**
* @author Dave Syer
* @author Gary Russell
*
*/
public class ExponentialMovingAverageRateTests {
private final static Log logger = LogFactory.getLog(ExponentialMovingAverageRateTests.class);
private final ExponentialMovingAverageRate history = new ExponentialMovingAverageRate(1., 10., 10);
@Test
public void testWindow() {
ExponentialMovingAverageRate rate = new ExponentialMovingAverageRate(1., 10., 20);
double decay = TestUtils.getPropertyValue(rate, "rates.decay", Double.class);
assertEquals(95, (int) (decay * 100.));
}
@Test
public void testGetCount() {
assertEquals(0, history.getCount());
history.increment();
assertEquals(1, history.getCount());
}
@Test
public void testGetTimeSinceLastMeasurement() throws Exception {
history.increment();
Thread.sleep(20L);
assertTrue(history.getTimeSinceLastMeasurement() > 0);
}
@Test
public void testGetEarlyMean() throws Exception {
long t0 = System.currentTimeMillis();
assertEquals(0, history.getMean(), 0.01);
Thread.sleep(20L);
history.increment();
long elapsed = System.currentTimeMillis() - t0;
if (elapsed < 30L) {
assertTrue(history.getMean() > 10);
}
else {
logger.warn("Test took too long to verify mean");
}
}
@Test
public void testGetMean() throws Exception {
long t0 = System.currentTimeMillis();
assertEquals(0, history.getMean(), 0.01);
Thread.sleep(20L);
history.increment();
Thread.sleep(20L);
history.increment();
double before = history.getMean();
long elapsed = System.currentTimeMillis() - t0;
if (elapsed < 50L) {
assertTrue(before > 10);
Thread.sleep(20L);
elapsed = System.currentTimeMillis() - t0;
if (elapsed < 80L) {
assertTrue(history.getMean() < before);
}
else {
logger.warn("Test took too long to verify mean");
}
}
else {
logger.warn("Test took too long to verify mean");
}
}
@Test
@Ignore
public void testGetStandardDeviation() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
Thread.sleep(20L);
history.increment();
Thread.sleep(22L);
history.increment();
Thread.sleep(18L);
// System.err.println(history);
assertTrue("Standard deviation should be non-zero: " + history, history.getStandardDeviation() > 0);
}
@Test
@Ignore
public void testReset() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.increment();
Thread.sleep(30L);
history.increment();
assertFalse(0==history.getStandardDeviation());
history.reset();
assertEquals(0, history.getStandardDeviation(), 0.01);
assertEquals(0, history.getCount());
assertEquals(0, history.getTimeSinceLastMeasurement(), 0.01);
assertEquals(0, history.getMean(), 0.01);
assertEquals(0, history.getMin(), 0.01);
assertEquals(0, history.getMax(), 0.01);
}
}

View File

@@ -1,133 +0,0 @@
/*
* Copyright 2002-2010 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.monitor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* @author Dave Syer
*
*/
public class ExponentialMovingAverageRatioTests {
private ExponentialMovingAverageRatio history = new ExponentialMovingAverageRatio(
0.5, 10);
@Test
public void testGetCount() {
assertEquals(0, history.getCount());
history.success();
assertEquals(1, history.getCount());
}
@Test
public void testGetTimeSinceLastMeasurement() throws Exception {
history.success();
Thread.sleep(20L);
assertTrue(history.getTimeSinceLastMeasurement() > 0);
}
@Test
public void testGetEarlyMean() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
}
@Test
public void testGetEarlyFailure() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.failure();
assertEquals(0, history.getMean(), 0.01);
}
@Test
public void testDecayedMean() throws Exception {
history.failure();
Thread.sleep(200L);
assertEquals(average(0, Math.exp(-0.4)), history.getMean(), 0.01);
}
@Test
public void testGetMean() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(1, history.getMean(), 0.01);
}
@Test
public void testGetMeanFailuresHighRate() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.success();
assertEquals(average(1), history.getMean(), 0.01);
history.failure();
assertEquals(average(1, 0.5), history.getMean(), 0.1);
history.success();
assertEquals(average(1, 0.5, 0.67), history.getMean(), 0.1);
}
@Test
public void testGetMeanFailuresLowRate() throws Exception {
assertEquals(1, history.getMean(), 0.01);
history.failure();
assertEquals(average(0), history.getMean(), 0.01);
history.failure();
assertEquals(average(0, 0), history.getMean(), 0.01);
history.success();
assertEquals(average(0, 0, 0.33), history.getMean(), 0.1);
}
@Test
public void testGetStandardDeviation() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.success();
assertEquals(0, history.getStandardDeviation(), 1);
}
@Test
public void testReset() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.success();
history.failure();
assertFalse(0==history.getStandardDeviation());
history.reset();
assertEquals(0, history.getStandardDeviation(), 0.01);
assertEquals(0, history.getCount());
assertEquals(0, history.getTimeSinceLastMeasurement(), 0.01);
assertEquals(1, history.getMean(), 0.01);
assertEquals(0, history.getMin(), 0.01);
assertEquals(0, history.getMax(), 0.01);
}
private double average(double... values) {
int count = 0;
double sum = 0;
for (double d : values) {
sum += d;
count++;
}
return sum / count;
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright 2002-2011 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.monitor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
/**
* @author Dave Syer
* @author Artem Bilan
*
*/
public class ExponentialMovingAverageTests {
private ExponentialMovingAverage history = new ExponentialMovingAverage(10);
@Test
public void testGetCount() {
assertEquals(0, history.getCount());
history.append(1);
assertEquals(1, history.getCount());
}
@Test
public void testGetMean() throws Exception {
assertEquals(0, history.getMean(), 0.01);
history.append(1);
history.append(1);
assertEquals(1, history.getMean(), 0.01);
}
@Test
public void testGetStandardDeviation() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.append(1);
history.append(1);
assertEquals(0, history.getStandardDeviation(), 0.01);
}
@Test
public void testReset() throws Exception {
assertEquals(0, history.getStandardDeviation(), 0.01);
history.append(1);
history.append(2);
assertFalse(0==history.getStandardDeviation());
history.reset();
assertEquals(0, history.getStandardDeviation(), 0.01);
// INT-2165
assertEquals(String.format("[N=%d, min=%f, max=%f, mean=%f, sigma=%f]", 0, 0d, 0d, 0d, 0d), history.toString());
}
}

View File

@@ -34,6 +34,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.context.OrderlyShutdownCapable;
@@ -350,17 +351,12 @@ public class MBeanExporterIntegrationTests {
boolean isStopCalled();
}
public static class ActiveChannelImpl implements MessageChannel, Lifecycle, ActiveChannel {
public static class ActiveChannelImpl extends AbstractMessageChannel implements Lifecycle, ActiveChannel {
private boolean stopCalled;
@Override
public boolean send(Message<?> message) {
return false;
}
@Override
public boolean send(Message<?> message, long timeout) {
protected boolean doSend(Message<?> message, long timeout) {
return false;
}

View File

@@ -1,3 +1,15 @@
/*
* Copyright 2011-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.monitor;
import static org.hamcrest.Matchers.equalTo;
@@ -8,22 +20,23 @@ import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.integration.channel.NullChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessagingException;
import org.springframework.integration.channel.NullChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessagingException;
import org.springframework.util.ClassUtils;
/**
* @author Tareq Abedrabbo
* @author Dave Syer
* @author Gary Russell
* @since 2.0.4
*/
public class MessageMetricsAdviceTests {
@@ -72,19 +85,6 @@ public class MessageMetricsAdviceTests {
exported.handleMessage(MessageBuilder.withPayload("test").build());
}
@Test
public void adviceExportedChannel() throws Exception {
Advised advised = (Advised) mBeanExporter.postProcessAfterInitialization(channel, "testChannel");
DummyInterceptor interceptor = new DummyInterceptor();
advised.addAdvice(interceptor);
assertThat(advised.getAdvisors().length, equalTo(2));
((MessageChannel) advised).send(MessageBuilder.withPayload("test").build());
assertThat(interceptor.invoked, is(true));
}
@Test
public void exportAdvisedChannel() throws Exception {
@@ -105,6 +105,7 @@ public class MessageMetricsAdviceTests {
@SuppressWarnings("unused")
boolean invoked = false;
@Override
public void handleMessage(Message<?> message) throws MessagingException {
invoked = true;
}
@@ -114,6 +115,7 @@ public class MessageMetricsAdviceTests {
boolean invoked = false;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
invoked = true;
return invocation.proceed();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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
@@ -13,16 +13,18 @@
package org.springframework.integration_.mbeanexporterhelper;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*
*/
public class INT_2626Tests {
@Test // This context failed to load before the INT-2626 fix was applied
public void testInt2626(){
new ClassPathXmlApplicationContext("INT-2626-config.xml", this.getClass());
new ClassPathXmlApplicationContext("INT-2626-config.xml", this.getClass()).close();
}
}