Skip to content

Commit 5475474

Browse files
garyrussellartembilan
authored andcommitted
INT-4384: Micrometer Support
JIRA: https://jira.spring.io/browse/INT-4384 Add support for micrometer metrics collection. Initial commit. * Rebase; upgrade to Micrometer rc.8 * Polishing - PR Comments * Final Polishing
1 parent 3bd4930 commit 5475474

19 files changed

+648
-40
lines changed

build.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ subprojects { subproject ->
8888

8989
ext {
9090
activeMqVersion = '5.15.2'
91-
aspectjVersion = '1.8.13'
9291
apacheSshdVersion = '1.6.0'
92+
aspectjVersion = '1.8.13'
93+
assertjVersion = '2.6.0'
9394
boonVersion = '0.34'
9495
commonsDbcp2Version = '2.1.1'
9596
commonsIoVersion = '2.4'
@@ -119,6 +120,7 @@ subprojects { subproject ->
119120
jythonVersion = '2.5.3'
120121
kryoShadedVersion = '3.0.3'
121122
log4jVersion = '2.10.0'
123+
micrometerVersion = '1.0.0-rc.8'
122124
mockitoVersion = '2.11.0'
123125
mysqlVersion = '6.0.6'
124126
pahoMqttClientVersion = '1.2.0'
@@ -272,6 +274,7 @@ project('spring-integration-test-support') {
272274
compile ("org.mockito:mockito-core:$mockitoVersion") {
273275
exclude group: 'org.hamcrest', module: 'hamcrest-core'
274276
}
277+
compile "org.assertj:assertj-core:$assertjVersion"
275278
compile "org.springframework:spring-context:$springVersion"
276279
compile "org.springframework:spring-messaging:$springVersion"
277280
compile "org.springframework:spring-test:$springVersion"
@@ -316,6 +319,7 @@ project('spring-integration-core') {
316319
}
317320
compile("io.fastjson:boon:$boonVersion", optional)
318321
compile("com.esotericsoftware:kryo-shaded:$kryoShadedVersion", optional)
322+
compile "io.micrometer:micrometer-core:$micrometerVersion"
319323

320324
testCompile ("org.aspectj:aspectjweaver:$aspectjVersion")
321325
testCompile "io.projectreactor:reactor-test:$reactorVersion"

spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -433,12 +433,19 @@ public boolean send(Message<?> message, long timeout) {
433433
}
434434
}
435435
if (countsEnabled) {
436-
metrics = channelMetrics.beforeSend();
436+
if (channelMetrics.getTimer() != null) {
437+
final Message<?> messageToSend = message;
438+
sent = channelMetrics.getTimer().recordCallable(() -> doSend(messageToSend, timeout));
439+
}
440+
else {
441+
metrics = channelMetrics.beforeSend();
442+
sent = doSend(message, timeout);
443+
channelMetrics.afterSend(metrics, sent);
444+
metricsProcessed = true;
445+
}
437446
}
438-
sent = this.doSend(message, timeout);
439-
if (countsEnabled) {
440-
channelMetrics.afterSend(metrics, sent);
441-
metricsProcessed = true;
447+
else {
448+
sent = doSend(message, timeout);
442449
}
443450

444451
if (debugEnabled) {
@@ -452,7 +459,12 @@ public boolean send(Message<?> message, long timeout) {
452459
}
453460
catch (Exception e) {
454461
if (countsEnabled && !metricsProcessed) {
455-
channelMetrics.afterSend(metrics, false);
462+
if (channelMetrics.getErrorCounter() != null) {
463+
channelMetrics.getErrorCounter().increment();
464+
}
465+
else {
466+
channelMetrics.afterSend(metrics, false);
467+
}
456468
}
457469
if (interceptorStack != null) {
458470
interceptors.afterSendCompletion(message, this, sent, e, interceptorStack);

spring-integration-core/src/main/java/org/springframework/integration/endpoint/AbstractMessageSource.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import org.springframework.messaging.MessagingException;
3434
import org.springframework.util.CollectionUtils;
3535

36+
import io.micrometer.core.instrument.Counter;
37+
3638
/**
3739
* @author Mark Fisher
3840
* @author Oleg Zhurakousky
@@ -51,11 +53,13 @@ public abstract class AbstractMessageSource<T> extends AbstractExpressionEvaluat
5153

5254
private volatile Map<String, Expression> headerExpressions = Collections.emptyMap();
5355

54-
private volatile String beanName;
56+
private String beanName;
57+
58+
private String managedType;
5559

56-
private volatile String managedType;
60+
private String managedName;
5761

58-
private volatile String managedName;
62+
private Counter counter;
5963

6064
private volatile boolean countsEnabled;
6165

@@ -118,6 +122,11 @@ public void setLoggingEnabled(boolean loggingEnabled) {
118122
this.managementOverrides.loggingConfigured = true;
119123
}
120124

125+
@Override
126+
public void setCounter(Counter counter) {
127+
this.counter = counter;
128+
}
129+
121130
@Override
122131
public void reset() {
123132
this.messageCount.set(0);
@@ -182,7 +191,12 @@ else if (result != null) {
182191
.build();
183192
}
184193
if (this.countsEnabled && message != null) {
185-
this.messageCount.incrementAndGet();
194+
if (this.counter != null) {
195+
this.counter.increment();
196+
}
197+
else {
198+
this.messageCount.incrementAndGet();
199+
}
186200
}
187201
return message;
188202
}

spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -136,16 +136,31 @@ public void handleMessage(Message<?> message) {
136136
message = MessageHistory.write(message, this, this.getMessageBuilderFactory());
137137
}
138138
if (countsEnabled) {
139-
start = handlerMetrics.beforeHandle();
139+
if (handlerMetrics.getTimer() != null) {
140+
final Message<?> messageToSend = message;
141+
handlerMetrics.getTimer().recordCallable(() -> {
142+
handleMessageInternal(messageToSend);
143+
return null;
144+
});
145+
}
146+
else {
147+
start = handlerMetrics.beforeHandle();
148+
handleMessageInternal(message);
149+
handlerMetrics.afterHandle(start, true);
150+
}
140151
}
141-
this.handleMessageInternal(message);
142-
if (countsEnabled) {
143-
handlerMetrics.afterHandle(start, true);
152+
else {
153+
handleMessageInternal(message);
144154
}
145155
}
146156
catch (Exception e) {
147157
if (countsEnabled) {
148-
handlerMetrics.afterHandle(start, false);
158+
if (handlerMetrics.getErrorCounter() != null) {
159+
handlerMetrics.getErrorCounter().increment();
160+
}
161+
else {
162+
handlerMetrics.afterHandle(start, false);
163+
}
149164
}
150165
if (e instanceof MessagingException) {
151166
throw (MessagingException) e;

spring-integration-core/src/main/java/org/springframework/integration/support/management/AbstractMessageChannelMetrics.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2016 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,12 @@
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
2121

22+
import org.springframework.lang.Nullable;
23+
import org.springframework.util.Assert;
24+
25+
import io.micrometer.core.instrument.Counter;
26+
import io.micrometer.core.instrument.Timer;
27+
2228
/**
2329
* Abstract base class for channel metrics implementations.
2430
*
@@ -32,10 +38,36 @@ public abstract class AbstractMessageChannelMetrics implements ConfigurableMetri
3238

3339
protected final String name;
3440

41+
private final Timer timer;
42+
43+
private final Counter errorCounter;
44+
3545
private volatile boolean fullStatsEnabled;
3646

47+
/**
48+
* Construct an instance with the provided name.
49+
* @param name the name.
50+
*/
3751
public AbstractMessageChannelMetrics(String name) {
52+
this(name, null, null);
53+
}
54+
55+
/**
56+
* Construct an instance with the provided name, timer and error counter.
57+
* A non-null timer requires a non-null error counter. When a timer is provided,
58+
* Micrometer metrics are used and the legacy metrics are not maintained.
59+
* @param name the name.
60+
* @param timer the timer.
61+
* @param errorCounter the error counter.
62+
* @since 5.0.2
63+
*/
64+
public AbstractMessageChannelMetrics(String name, Timer timer, Counter errorCounter) {
65+
if (timer != null) {
66+
Assert.notNull(errorCounter, "'errorCounter' cannot be null if a timer is provided");
67+
}
3868
this.name = name;
69+
this.timer = timer;
70+
this.errorCounter = errorCounter;
3971
}
4072

4173
/**
@@ -72,6 +104,26 @@ protected boolean isFullStatsEnabled() {
72104
*/
73105
public abstract void reset();
74106

107+
/**
108+
* Return the timer if Micrometer metrics are being used.
109+
* @return the timer, or null to indicate Micrometer is not being used.
110+
* @since 5.0.2
111+
*/
112+
@Nullable
113+
public Timer getTimer() {
114+
return this.timer;
115+
}
116+
117+
/**
118+
* Return the error counter if Micrometer metrics are being used.
119+
* @return the counter or null if Micrometer is not being used.
120+
* @since 5.0.2
121+
*/
122+
@Nullable
123+
public Counter getErrorCounter() {
124+
return this.errorCounter;
125+
}
126+
75127
public abstract int getSendCount();
76128

77129
public abstract long getSendCountLong();

spring-integration-core/src/main/java/org/springframework/integration/support/management/AbstractMessageHandlerMetrics.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2016 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,9 @@
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
2121

22+
import io.micrometer.core.instrument.Counter;
23+
import io.micrometer.core.instrument.Timer;
24+
2225
/**
2326
* Abstract base class for handler metrics implementations.
2427
*
@@ -32,10 +35,20 @@ public abstract class AbstractMessageHandlerMetrics implements ConfigurableMetri
3235

3336
protected final String name;
3437

38+
private final Timer timer;
39+
40+
private final Counter errorCounter;
41+
3542
private volatile boolean fullStatsEnabled;
3643

3744
public AbstractMessageHandlerMetrics(String name) {
45+
this(name, null, null);
46+
}
47+
48+
public AbstractMessageHandlerMetrics(String name, Timer timer, Counter errorCounter) {
3849
this.name = name;
50+
this.timer = timer;
51+
this.errorCounter = errorCounter;
3952
}
4053

4154
/**
@@ -66,6 +79,14 @@ protected boolean isFullStatsEnabled() {
6679

6780
public abstract void reset();
6881

82+
public Timer getTimer() {
83+
return this.timer;
84+
}
85+
86+
public Counter getErrorCounter() {
87+
return this.errorCounter;
88+
}
89+
6990
public abstract long getHandleCountLong();
7091

7192
public abstract int getHandleCount();

spring-integration-core/src/main/java/org/springframework/integration/support/management/DefaultMessageChannelMetrics.java

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2017 the original author or authors.
2+
* Copyright 2009-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@
1818

1919
import java.util.concurrent.atomic.AtomicLong;
2020

21+
import io.micrometer.core.instrument.Counter;
22+
import io.micrometer.core.instrument.Timer;
23+
2124
/**
2225
* Default implementation; use the full constructor to customize the moving averages.
2326
*
@@ -61,13 +64,26 @@ public DefaultMessageChannelMetrics() {
6164
* @param name the name.
6265
*/
6366
public DefaultMessageChannelMetrics(String name) {
67+
this(name, null, null);
68+
}
69+
70+
/**
71+
* Construct an instance with default metrics with {@code window=10, period=1 second,
72+
* lapsePeriod=1 minute}.
73+
* @param name the name.
74+
* @param timer a timer.
75+
* @param errorCounter a counter.
76+
* @since 5.0.2
77+
*/
78+
public DefaultMessageChannelMetrics(String name, Timer timer, Counter errorCounter) {
6479
this(name, new ExponentialMovingAverage(DEFAULT_MOVING_AVERAGE_WINDOW, 1000000.),
65-
new ExponentialMovingAverageRate(
66-
ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true),
67-
new ExponentialMovingAverageRatio(
68-
ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true),
69-
new ExponentialMovingAverageRate(
70-
ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true));
80+
new ExponentialMovingAverageRate(
81+
ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true),
82+
new ExponentialMovingAverageRatio(
83+
ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true),
84+
new ExponentialMovingAverageRate(
85+
ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true),
86+
timer, errorCounter);
7187
}
7288

7389
/**
@@ -84,7 +100,26 @@ public DefaultMessageChannelMetrics(String name) {
84100
public DefaultMessageChannelMetrics(String name, ExponentialMovingAverage sendDuration,
85101
ExponentialMovingAverageRate sendErrorRate, ExponentialMovingAverageRatio sendSuccessRatio,
86102
ExponentialMovingAverageRate sendRate) {
87-
super(name);
103+
this(name, sendDuration, sendErrorRate, sendSuccessRatio, sendRate, null, null);
104+
}
105+
106+
/**
107+
* Construct an instance with the supplied metrics. For proper representation of metrics, the
108+
* supplied sendDuration must have a {@code factor=1000000.} and the the other arguments
109+
* must be created with the {@code millis} constructor argument set to true.
110+
* @param name the name.
111+
* @param sendDuration an {@link ExponentialMovingAverage} for calculating the send duration.
112+
* @param sendErrorRate an {@link ExponentialMovingAverageRate} for calculating the send error rate.
113+
* @param sendSuccessRatio an {@link ExponentialMovingAverageRatio} for calculating the success ratio.
114+
* @param sendRate an {@link ExponentialMovingAverageRate} for calculating the send rate.
115+
* @param timer a timer.
116+
* @param errorCounter a counter.
117+
* @since 5.0.2
118+
*/
119+
public DefaultMessageChannelMetrics(String name, ExponentialMovingAverage sendDuration,
120+
ExponentialMovingAverageRate sendErrorRate, ExponentialMovingAverageRatio sendSuccessRatio,
121+
ExponentialMovingAverageRate sendRate, Timer timer, Counter errorCounter) {
122+
super(name, timer, errorCounter);
88123
this.sendDuration = sendDuration;
89124
this.sendErrorRate = sendErrorRate;
90125
this.sendSuccessRatio = sendSuccessRatio;

0 commit comments

Comments
 (0)