/*
* 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;
/**
* 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 4.2
*/
public class AggregatingMessageHandlerMetrics extends DefaultMessageHandlerMetrics {
private static final int DEFAULT_SAMPLE_SIZE = 1000;
private final int sampleSize;
private long start;
public AggregatingMessageHandlerMetrics() {
this(null, DEFAULT_SAMPLE_SIZE);
}
/**
* Construct an instance with the default moving average window (10).
* @param name the name.
* @param sampleSize the sample size over which to aggregate the duration.
*/
public AggregatingMessageHandlerMetrics(String name, int sampleSize) {
super(name);
this.sampleSize = sampleSize;
}
/**
* Construct an instance with the supplied {@link ExponentialMovingAverage} calculating
* the duration of processing by the message handler (and any downstream synchronous
* endpoints).
* @param name the name.
* @param duration an {@link ExponentialMovingAverage} for calculating the duration.
* @param sampleSize the sample size over which to aggregate the duration.
*/
public AggregatingMessageHandlerMetrics(String name, ExponentialMovingAverage duration, int sampleSize) {
super(name, duration);
this.sampleSize = sampleSize;
}
@Override
public synchronized MetricsContext beforeHandle() {
long count = this.handleCount.getAndIncrement();
if (isFullStatsEnabled() && count % this.sampleSize == 0) {
this.start = System.nanoTime();
}
this.activeCount.incrementAndGet();
return new AggregatingHandlerMetricsContext(this.start, count + 1);
}
@Override
public void afterHandle(MetricsContext context, boolean success) {
this.activeCount.decrementAndGet();
AggregatingHandlerMetricsContext aggregatingContext = (AggregatingHandlerMetricsContext) context;
if (success) {
if (isFullStatsEnabled() && aggregatingContext.newCount % this.sampleSize == 0) {
this.duration.append(System.nanoTime() - aggregatingContext.start);
}
}
else {
this.errorCount.incrementAndGet();
}
}
protected static class AggregatingHandlerMetricsContext extends DefaultHandlerMetricsContext {
protected long newCount;
public AggregatingHandlerMetricsContext(long start, long newCount) {
super(start);
this.newCount = newCount;
}
}
}