Remove Legacy Metrics

- Simplify MBeans - instead of wrapping to expose lifecycle methods,
  implement `ManageableLifecycle`. Register an additional MBean for
  polled endpoints to control the lifecycle.

* Polishing

- Move `QueueChannel` `@ManagedAttribute`s to `QueueChannelOperations`
- Make all `AbstractEndpoints` `IntegrationManagedResource`s and remove `ManagedEndpoint`
  to allow exposure of any `@Managed*` methods (including those on `Pausable`)
- Revert to `Lifecycle` for classes that are not related to endpoints
- Remove legacy metrics from docs
This commit is contained in:
Gary Russell
2020-08-07 12:56:57 -04:00
committed by GitHub
parent da5d002d64
commit 1beb854fb4
148 changed files with 533 additions and 7064 deletions

View File

@@ -74,7 +74,6 @@ class MessageChannelReactiveUtilsTests {
@Disabled("Backpressure is not honored")
void testOverproducingWithSubscribableChannel() {
DirectChannel channel = new DirectChannel();
channel.setCountsEnabled(true);
Disposable.Composite compositeDisposable = Disposables.composite();
AtomicInteger sendCount = new AtomicInteger();

View File

@@ -148,15 +148,9 @@ public class ManualFlowTests {
assertThat(replyProducers.contains(bridgeHandler)).isTrue();
assertThat(this.integrationManagementConfigurer.getChannelMetrics("channel")).isNotNull();
assertThat(this.integrationManagementConfigurer.getHandlerMetrics("bridge")).isNotNull();
flowRegistration.destroy();
assertThat(replyProducers.contains(bridgeHandler)).isFalse();
assertThat(this.integrationManagementConfigurer.getChannelMetrics("channel")).isNull();
assertThat(this.integrationManagementConfigurer.getHandlerMetrics("bridge")).isNull();
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -73,7 +73,6 @@ public class MessagingGatewayTests {
this.messagingGateway.setReplyChannel(this.replyChannel);
this.messagingGateway.setBeanFactory(this.applicationContext);
this.messagingGateway.setCountsEnabled(true);
this.messagingGateway.afterPropertiesSet();
this.messagingGateway.start();
this.applicationContext.refresh();
@@ -93,7 +92,8 @@ public class MessagingGatewayTests {
Mockito.when(requestChannel.send(messageMock, 1000L)).thenReturn(true);
this.messagingGateway.send(messageMock);
Mockito.verify(requestChannel).send(messageMock, 1000L);
assertThat(this.messagingGateway.getMessageCount()).isEqualTo(1);
// TODO Micrometer counter
// assertThat(this.messagingGateway.getMessageCount()).isEqualTo(1);
}
@Test(expected = MessageDeliveryException.class)

View File

@@ -72,8 +72,6 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import net.minidev.json.JSONArray;
@@ -154,16 +152,12 @@ public class IntegrationGraphServerTests {
jsonArray = JsonPathUtils.evaluate(baos.toByteArray(), "$..nodes[?(@.name == 'router')]");
String routerJson = jsonArray.toJSONString();
assertThat(routerJson).contains("\"deprecated\":\"stats are deprecated");
this.server.rebuild();
graph = this.server.getGraph();
baos = new ByteArrayOutputStream();
objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.registerModule(new SimpleModule().addSerializer(IntegrationNode.Stats.class,
NullSerializer.instance));
objectMapper.writeValue(baos, graph);
// System . out . println(new String(baos.toByteArray()));
@@ -179,7 +173,6 @@ public class IntegrationGraphServerTests {
jsonArray = JsonPathUtils.evaluate(baos.toByteArray(), "$..nodes[?(@.name == 'router')]");
routerJson = jsonArray.toJSONString();
assertThat(routerJson).contains("\"stats\":null");
assertThat(routerJson).contains("\"sendTimers\":{\"successes\":{\"count\":4");
jsonArray = JsonPathUtils.evaluate(baos.toByteArray(), "$..nodes[?(@.name == 'toRouter')]");
String toRouterJson = jsonArray.toJSONString();

View File

@@ -1,175 +0,0 @@
/*
* Copyright 2002-2019 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
*
* https://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.assertj.core.api.Assertions.assertThat;
import java.util.Deque;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.assertj.core.data.Offset;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.util.StopWatch;
/**
* @author Dave Syer
* @author Gary Russell
* @author Steven Swor
* @author Artem Bilan
*/
@Ignore("Very sensitive to the time. Don't forget to test after some changes.")
@SuppressWarnings("deprecation")
public class ExponentialMovingAverageRateTests {
private static final Log logger = LogFactory.getLog(ExponentialMovingAverageRateTests.class);
private final ExponentialMovingAverageRate history = new ExponentialMovingAverageRate(1., 10., 10, true);
@Test
public void testGetCount() {
assertThat(history.getCount()).isEqualTo(0);
history.increment();
assertThat(history.getCount()).isEqualTo(1);
}
@Test
@SuppressWarnings("unchecked")
public void testGetTimeSinceLastMeasurement() {
long sleepTime = 20L;
// fill history with the same value.
long now = System.nanoTime() - 2 * sleepTime * 1000000;
for (int i = 0; i < TestUtils.getPropertyValue(history, "retention", Integer.class); i++) {
history.increment(now);
}
final Deque<Long> times = TestUtils.getPropertyValue(history, "times", Deque.class);
assertThat(times.peekFirst()).isEqualTo(Long.valueOf(now));
assertThat(times.peekLast()).isEqualTo(Long.valueOf(now));
//increment just so we'll have a different value between first and last
history.increment(System.nanoTime() - sleepTime * 1000000);
assertThat(times.peekLast()).isNotEqualTo(times.peekFirst());
/*
* We've called Thread.sleep twice with the same value in quick
* succession. If timeSinceLastSend is pulling off the correct end of
* the queue, then we should be closer to the sleep time than we are to
* 2 x sleepTime, but we should definitely be greater than the sleep
* time.
*/
double timeSinceLastMeasurement = history.getTimeSinceLastMeasurement();
assertThat(timeSinceLastMeasurement > sleepTime).isTrue();
assertThat(timeSinceLastMeasurement <= (1.5 * sleepTime)).isTrue();
}
@Test
public void testGetEarlyMean() throws Exception {
long t0 = System.currentTimeMillis();
assertThat(history.getMean()).isCloseTo(0, Offset.offset(0.01));
Thread.sleep(20L);
history.increment();
long elapsed = System.currentTimeMillis() - t0;
if (elapsed < 30L) {
assertThat(history.getMean() > 10).isTrue();
}
else {
logger.warn("Test took too long to verify mean");
}
}
@Test
public void testGetMean() throws Exception {
long t0 = System.currentTimeMillis();
assertThat(history.getMean()).isCloseTo(0, Offset.offset(0.01));
Thread.sleep(20L);
history.increment();
Thread.sleep(20L);
history.increment();
double before = history.getMean();
Statistics statisticsBefore = history.getStatistics();
long elapsed = System.currentTimeMillis() - t0;
if (elapsed < 50L) {
assertThat(before > 10).isTrue();
Thread.sleep(20L);
elapsed = System.currentTimeMillis() - t0;
if (elapsed < 80L) {
assertThat(history.getMean()).isLessThan(before);
assertThat(history.getStatistics().getMean()).isLessThan(statisticsBefore.getMean());
}
else {
logger.warn("Test took too long to verify mean");
}
}
else {
logger.warn("Test took too long to verify mean");
}
}
@Test
public void testGetStandardDeviation() throws Exception {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
Thread.sleep(20L);
history.increment();
Thread.sleep(22L);
history.increment();
Thread.sleep(18L);
assertThat(history.getStandardDeviation() > 0).as("Standard deviation should be non-zero: " + history).isTrue();
}
@Test
public void testReset() throws Exception {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
history.increment();
Thread.sleep(30L);
history.increment();
assertThat(0.0).isNotEqualTo(history.getStandardDeviation());
history.reset();
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getCount()).isEqualTo(0);
assertThat(history.getTimeSinceLastMeasurement()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getMean()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getMin()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getMax()).isCloseTo(0, Offset.offset(0.01));
}
@Test
public void testRate() {
ExponentialMovingAverageRate rate = new ExponentialMovingAverageRate(1, 60, 10);
int count = 1000000;
StopWatch watch = new StopWatch();
watch.start();
for (int i = 0; i < count; i++) {
rate.increment();
}
watch.stop();
double calculatedRate = count / (double) watch.getTotalTimeMillis() * 1000;
assertThat(rate.getMean()).isEqualTo(calculatedRate, Offset.offset(4000000d));
}
@Test
public void testPerf() {
ExponentialMovingAverageRate rate = new ExponentialMovingAverageRate(1, 60, 10);
for (int i = 0; i < 1000000; i++) {
rate.increment();
}
}
}

View File

@@ -1,202 +0,0 @@
/*
* Copyright 2002-2019 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
*
* https://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.assertj.core.api.Assertions.assertThat;
import java.util.Deque;
import org.assertj.core.data.Offset;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.test.util.TestUtils;
/**
* @author Dave Syer
* @author Gary Russell
* @author Artem Bilan
* @author Steven Swor
*/
@Ignore("Very sensitive to the time. Don't forget to test after some changes.")
@SuppressWarnings("deprecation")
public class ExponentialMovingAverageRatioTests {
private final ExponentialMovingAverageRatio history = new ExponentialMovingAverageRatio(0.5, 10, true);
@Test
public void testGetCount() {
assertThat(history.getCount()).isEqualTo(0);
history.success();
assertThat(history.getCount()).isEqualTo(1);
}
@Test
@SuppressWarnings("unchecked")
public void testGetTimeSinceLastMeasurement() {
long sleepTime = 20L;
// fill history with the same value.
long now = System.nanoTime() - 2 * sleepTime * 1000000;
for (int i = 0; i < TestUtils.getPropertyValue(history, "retention", Integer.class); i++) {
history.success(now);
}
final Deque<Long> times = TestUtils.getPropertyValue(history, "times", Deque.class);
assertThat(times.peekFirst()).isEqualTo(Long.valueOf(now));
assertThat(times.peekLast()).isEqualTo(Long.valueOf(now));
//increment just so we'll have a different value between first and last
history.success(System.nanoTime() - sleepTime * 1000000);
assertThat(times.peekLast()).isNotEqualTo(times.peekFirst());
/*
* We've called Thread.sleep twice with the same value in quick
* succession. If timeSinceLastSend is pulling off the correct end of
* the queue, then we should be closer to the sleep time than we are to
* 2 x sleepTime, but we should definitely be greater than the sleep
* time.
*/
double timeSinceLastMeasurement = history.getTimeSinceLastMeasurement();
assertThat(timeSinceLastMeasurement).isGreaterThan(sleepTime / 100);
assertThat(timeSinceLastMeasurement).isLessThanOrEqualTo(1.5 * sleepTime / 100);
}
@Test
public void testGetEarlyMean() {
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.success();
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
}
@Test
public void testGetEarlyFailure() {
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.failure();
assertThat(history.getMean()).isCloseTo(0, Offset.offset(0.01));
}
@Test
public void testDecayedMean() throws Exception {
history.failure(System.nanoTime() - 200000000);
assertThat(history.getMean()).isCloseTo(average(0, Math.exp(-0.4)), Offset.offset(0.01));
history.success();
history.failure();
double mean = history.getMean();
Statistics statistics = history.getStatistics();
Thread.sleep(50);
assertThat(history.getMean()).isGreaterThan(mean);
assertThat(history.getStatistics().getMean()).isGreaterThan(statistics.getMean());
}
@Test
public void testGetMean() {
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.success();
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.success();
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.success();
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
}
@Test
public void testGetMeanFailuresHighRate() {
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.success(); // need an extra now that we can't determine the time between the first and previous
history.success();
assertThat(history.getMean()).isCloseTo(average(1), Offset.offset(0.01));
history.failure();
assertThat(history.getMean()).isCloseTo(average(1, 0.5), Offset.offset(0.1));
history.success();
assertThat(history.getMean()).isCloseTo(average(1, 0.5, 0.67), Offset.offset(0.1));
}
@Test
public void testGetMeanFailuresLowRate() {
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
history.failure(); // need an extra now that we can't determine the time between the first and previous
history.failure();
assertThat(history.getMean()).isCloseTo(average(0), Offset.offset(0.01));
history.failure();
assertThat(history.getMean()).isCloseTo(average(0, 0), Offset.offset(0.01));
history.success();
assertThat(history.getMean()).isCloseTo(average(0, 0, 0.33), Offset.offset(0.1));
}
@Test
public void testGetStandardDeviation() {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
history.success();
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(1d));
}
@Test
public void testReset() {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
history.success();
history.failure();
assertThat(history.getStandardDeviation()).isNotEqualTo(0);
history.reset();
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getCount()).isEqualTo(0);
assertThat(history.getTimeSinceLastMeasurement()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
assertThat(history.getMin()).isCloseTo(0, Offset.offset(0.01));
assertThat(history.getMax()).isCloseTo(0, Offset.offset(0.01));
history.success();
assertThat(history.getMin()).isCloseTo(1, Offset.offset(0.01));
}
private double average(double... values) {
int count = 0;
double sum = 0;
for (double d : values) {
sum += d;
count++;
}
return sum / count;
}
@Test
public void testRatio() {
ExponentialMovingAverageRatio ratio = new ExponentialMovingAverageRatio(60, 10, true);
for (int i = 0; i < 100; i++) {
if (i % 10 == 1) {
ratio.failure();
}
else {
ratio.success();
}
}
assertThat(ratio.getMax()).isCloseTo(0.9, Offset.offset(0.02));
assertThat(ratio.getMean()).isCloseTo(0.9, Offset.offset(0.03));
}
@Test
@Ignore
public void testPerf() {
ExponentialMovingAverageRatio ratio = new ExponentialMovingAverageRatio(60, 10);
for (int i = 0; i < 100000; i++) {
if (i % 10 == 0) {
ratio.failure();
}
else {
ratio.success();
}
}
}
}

View File

@@ -1,127 +0,0 @@
/*
* Copyright 2002-2019 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
*
* https://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.assertj.core.api.Assertions.assertThat;
import org.assertj.core.data.Offset;
import org.junit.Ignore;
import org.junit.Test;
/**
* @author Dave Syer
* @author Artem Bilan
* @author Gary Russell
*/
@Ignore("Very sensitive to the time. Don't forget to test after some changes.")
@SuppressWarnings("deprecation")
public class ExponentialMovingAverageTests {
private final ExponentialMovingAverage history = new ExponentialMovingAverage(10);
@Test
@Ignore // used to compare LinkedList to ArrayDeque which was 35% faster
public void perf() {
for (int i = 0; i < 100000000; i++) {
history.append(0.0);
}
}
@Test
public void testGetCount() {
assertThat(history.getCount()).isEqualTo(0);
history.append(1);
assertThat(history.getCount()).isEqualTo(1);
}
@Test
public void testGetMean() {
assertThat(history.getMean()).isCloseTo(0, Offset.offset(0.01));
history.append(1);
history.append(1);
assertThat(history.getMean()).isCloseTo(1, Offset.offset(0.01));
}
@Test
public void testGetStandardDeviation() {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
history.append(1);
history.append(1);
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
}
@Test
public void testReset() {
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
history.append(1);
history.append(2);
assertThat(0 == history.getStandardDeviation()).isFalse();
history.reset();
assertThat(history.getStandardDeviation()).isCloseTo(0, Offset.offset(0.01));
// INT-2165
assertThat(history.toString())
.isEqualTo(String.format("[N=%d, min=%f, max=%f, mean=%f, sigma=%f]", 0, 0d, 0d, 0d, 0d));
history.append(1);
assertThat(history.getMin()).isCloseTo(1, Offset.offset(0.01));
}
@Test
public void testAv() {
ExponentialMovingAverage av = new ExponentialMovingAverage(10);
for (int i = 0; i < 10000; i++) {
switch (i % 3) {
case 0:
av.append(20);
break;
case 1:
av.append(30);
break;
case 2:
av.append(40);
break;
}
}
assertThat(av.getMax()).isCloseTo(40, Offset.offset(0.1));
assertThat(av.getMin()).isCloseTo(20, Offset.offset(0.1));
assertThat(av.getMean()).isCloseTo(30, Offset.offset(1.0));
}
@Test
@Ignore
public void testPerf() {
ExponentialMovingAverage av = new ExponentialMovingAverage(10);
for (int i = 0; i < 10000000; i++) {
switch (i % 4) {
case 0:
av.append(20);
break;
case 1:
av.append(30);
break;
case 2:
av.append(40);
break;
case 3:
av.append(50);
break;
}
}
}
}

View File

@@ -66,8 +66,6 @@ public class IntegrationManagementConfigurerTests {
assertThat(channel.isLoggingEnabled()).isTrue();
assertThat(handler.isLoggingEnabled()).isTrue();
assertThat(source.isLoggingEnabled()).isTrue();
channel.setCountsEnabled(true);
channel.setStatsEnabled(true);
ApplicationContext ctx = mock(ApplicationContext.class);
Map<String, IntegrationManagement> beans = new HashMap<String, IntegrationManagement>();
beans.put("foo", channel);
@@ -82,8 +80,6 @@ public class IntegrationManagementConfigurerTests {
assertThat(channel.isLoggingEnabled()).isFalse();
assertThat(handler.isLoggingEnabled()).isFalse();
assertThat(source.isLoggingEnabled()).isFalse();
assertThat(channel.isCountsEnabled()).isTrue();
assertThat(channel.isStatsEnabled()).isTrue();
}
@Test
@@ -91,8 +87,6 @@ public class IntegrationManagementConfigurerTests {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(ConfigEmptyAnnotation.class);
AbstractMessageChannel channel = ctx.getBean("channel", AbstractMessageChannel.class);
assertThat(channel.isCountsEnabled()).isTrue();
assertThat(channel.isStatsEnabled()).isTrue();
channel = ctx.getBean("loggingOffChannel", AbstractMessageChannel.class);
assertThat(channel.isLoggingEnabled()).isFalse();
ctx.close();