/* * Copyright 2009-2016 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.concurrent.atomic.AtomicLong; /** * Default implementation; use the full constructor to customize the moving averages. * * @author Dave Syer * @author Helena Edelson * @author Gary Russell * @since 2.0 */ public class DefaultMessageChannelMetrics extends AbstractMessageChannelMetrics { public static final long ONE_SECOND_SECONDS = 1; public static final long ONE_MINUTE_SECONDS = 60; public static final int DEFAULT_MOVING_AVERAGE_WINDOW = 10; protected final ExponentialMovingAverage sendDuration; protected final ExponentialMovingAverageRate sendErrorRate; protected final ExponentialMovingAverageRatio sendSuccessRatio; protected final ExponentialMovingAverageRate sendRate; protected final AtomicLong sendCount = new AtomicLong(); protected final AtomicLong sendErrorCount = new AtomicLong(); protected final AtomicLong receiveCount = new AtomicLong(); protected final AtomicLong receiveErrorCount = new AtomicLong(); public DefaultMessageChannelMetrics() { this(null); } /** * Construct an instance with default metrics with {@code window=10, period=1 second, * lapsePeriod=1 minute}. * @param name the name. */ public DefaultMessageChannelMetrics(String name) { this(name, new ExponentialMovingAverage(DEFAULT_MOVING_AVERAGE_WINDOW, 1000000.), new ExponentialMovingAverageRate( ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true), new ExponentialMovingAverageRatio( ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true), new ExponentialMovingAverageRate( ONE_SECOND_SECONDS, ONE_MINUTE_SECONDS, DEFAULT_MOVING_AVERAGE_WINDOW, true)); } /** * Construct an instance with the supplied metrics. For proper representation of metrics, the * supplied sendDuration must have a {@code factor=1000000.} and the the other arguments * must be created with the {@code millis} constructor argument set to true. * @param name the name. * @param sendDuration an {@link ExponentialMovingAverage} for calculating the send duration. * @param sendErrorRate an {@link ExponentialMovingAverageRate} for calculating the send error rate. * @param sendSuccessRatio an {@link ExponentialMovingAverageRatio} for calculating the success ratio. * @param sendRate an {@link ExponentialMovingAverageRate} for calculating the send rate. * @since 4.2 */ public DefaultMessageChannelMetrics(String name, ExponentialMovingAverage sendDuration, ExponentialMovingAverageRate sendErrorRate, ExponentialMovingAverageRatio sendSuccessRatio, ExponentialMovingAverageRate sendRate) { super(name); this.sendDuration = sendDuration; this.sendErrorRate = sendErrorRate; this.sendSuccessRatio = sendSuccessRatio; this.sendRate = sendRate; } public void destroy() { if (logger.isDebugEnabled()) { logger.debug(this.sendDuration); } } @Override public MetricsContext beforeSend() { long start = 0; if (isFullStatsEnabled()) { start = System.nanoTime(); this.sendRate.increment(start); } this.sendCount.incrementAndGet(); return new DefaultChannelMetricsContext(start); } @Override public void afterSend(MetricsContext context, boolean result) { if (result && isFullStatsEnabled()) { long now = System.nanoTime(); this.sendSuccessRatio.success(now); this.sendDuration.append(now - ((DefaultChannelMetricsContext) context).start); } else { if (isFullStatsEnabled()) { long now = System.nanoTime(); this.sendSuccessRatio.failure(now); this.sendErrorRate.increment(now); } this.sendErrorCount.incrementAndGet(); } } @Override public synchronized void reset() { this.sendDuration.reset(); this.sendErrorRate.reset(); this.sendSuccessRatio.reset(); this.sendRate.reset(); this.sendCount.set(0); this.sendErrorCount.set(0); this.receiveErrorCount.set(0); this.receiveCount.set(0); } @Override public int getSendCount() { return (int) this.sendCount.get(); } @Override public long getSendCountLong() { return this.sendCount.get(); } @Override public int getSendErrorCount() { return (int) this.sendErrorCount.get(); } @Override public long getSendErrorCountLong() { return this.sendErrorCount.get(); } @Override public double getTimeSinceLastSend() { return this.sendRate.getTimeSinceLastMeasurement(); } @Override public double getMeanSendRate() { return this.sendRate.getMean(); } @Override public double getMeanErrorRate() { return this.sendErrorRate.getMean(); } @Override public double getMeanErrorRatio() { return 1 - this.sendSuccessRatio.getMean(); } @Override public double getMeanSendDuration() { return this.sendDuration.getMean(); } @Override public double getMinSendDuration() { return this.sendDuration.getMin(); } @Override public double getMaxSendDuration() { return this.sendDuration.getMax(); } @Override public double getStandardDeviationSendDuration() { return this.sendDuration.getStandardDeviation(); } @Override public Statistics getSendDuration() { return this.sendDuration.getStatistics(); } @Override public Statistics getSendRate() { return this.sendRate.getStatistics(); } @Override public Statistics getErrorRate() { return this.sendErrorRate.getStatistics(); } @Override public void afterReceive() { this.receiveCount.incrementAndGet(); } @Override public void afterError() { this.receiveErrorCount.incrementAndGet(); } @Override public int getReceiveCount() { return (int) this.receiveCount.get(); } @Override public long getReceiveCountLong() { return this.receiveCount.get(); } @Override public int getReceiveErrorCount() { return (int) this.receiveErrorCount.get(); } @Override public long getReceiveErrorCountLong() { return this.receiveErrorCount.get(); } @Override public String toString() { return String.format("MessageChannelMonitor: [name=%s, sends=%d" + (this.receiveCount.get() == 0 ? "" : this.receiveCount.get()) + "]", name, this.sendCount.get()); } protected static class DefaultChannelMetricsContext implements MetricsContext { protected final long start; protected DefaultChannelMetricsContext(long start) { this.start = start; } } }