INT-1420: add javadocs

This commit is contained in:
Dave Syer
2010-09-07 10:24:53 +01:00
parent e1704c6267
commit 04dbe63366
9 changed files with 203 additions and 18 deletions

View File

@@ -33,7 +33,11 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.util.Assert;
/**
* JMX-based Control Bus implementation. Exports all channel and endpoint beans from a given BeanFactory as MBeans.
* JMX-based Control Bus implementation. Routes control messages on an operation channel to the other control points
* (channels and handlers) via JMX. To use the control bus send a message to the operation channel with a header
* {@link #TARGET_BEAN_NAME} equal to the bean name of the channel or endpoint you want to target. Include also a header
* {@link JmxHeaders#OPERATION_NAME} to specify the operation you want to invoke and a message payload containing the
* arguments (if any).
*
* @author Mark Fisher
* @since 2.0

View File

@@ -14,8 +14,11 @@ package org.springframework.integration.monitor;
/**
* Cumulative statistics for a series of real numbers with higher weight given to recent data but without storing any
* history. Older values are given exponentially smaller weight, with a decay factor determined by a "window" size
* chosen by the client.
* history. Clients call {@link #append(double)} every time there is a new measurement, and then can collect summary
* statistics from the convenience getters (e.g. {@link #getStatistics()}). Older values are given exponentially smaller
* weight, with a decay factor determined by a "window" size chosen by the caller. The result is a good approximation to
* the statistics of the series but with more weight given to recent measurements, so if the statistics change over time
* those trends can be approximately reflected.
*
* @author Dave Syer
*
@@ -37,12 +40,20 @@ public class ExponentialMovingAverage {
private final double decay;
/**
* Create a moving average accumulator with decay lapse window provided. Measurements older than this will have
* smaller weight than <code>1/e</code>.
*
* @param window the exponential lapse window (number of measurements)
*/
public ExponentialMovingAverage(int window) {
this.decay = 1 - 1. / window;
}
/**
* Add a new measurement to the series.
*
* @param value the measurement to append
*/
public void append(double value) {
if (value > max || count == 0)
max = value;
@@ -54,28 +65,46 @@ public class ExponentialMovingAverage {
count++;
}
/**
* @return the number of measurements recorded
*/
public int getCount() {
return count;
}
/**
* @return the mean value
*/
public double getMean() {
return weight > 0 ? sum / weight : 0.;
}
/**
* @return the approximate standard deviation
*/
public double getStandardDeviation() {
double mean = getMean();
double var = weight > 0 ? sumSquares / weight - mean * mean : 0.;
return var > 0 ? Math.sqrt(var) : 0;
}
/**
* @return the maximum value recorded (not weighted)
*/
public double getMax() {
return max;
}
/**
* @return the minimum value recorded (not weighted)
*/
public double getMin() {
return min;
}
/**
* @return summary statistics (count, mean, standard deviation etc.)
*/
public Statistics getStatistics() {
return new Statistics(count, min, max, getMean(), getStandardDeviation());
}

View File

@@ -13,8 +13,17 @@
package org.springframework.integration.monitor;
/**
* Cumulative statistics for rate with higher weight given to recent data but without storing any history. Older values
* are given exponentially smaller weight, with a decay factor determined by a duration chosen by the client.
* Cumulative statistics for an event rate with higher weight given to recent data but without storing any history.
* Clients call {@link #increment()} when a new event occurs, and then use convenience methods (e.g. {@link #getMean()})
* to retrieve estimates of the rate of event arrivals and the statistics of the series. Older values are given
* exponentially smaller weight, with a decay factor determined by a duration chosen by the client. The rate measurement
* weights decay in two dimensions:
* <ul>
* <li>in time according to the lapse period supplied: <code>weight = exp((t0-t)/T)</code> where <code>t0</code> is the
* last measurement time, <code>t</code> is the current time and <code>T</code> is the lapse period)</li>
* <li>per measurement according to the lapse window supplied: <code>weight = exp(-i/L)</code> where <code>L</code> is
* the lapse window and <code>i</code> is the sequence number of the measurement.</li>
* </ul>
*
* @author Dave Syer
*
@@ -48,6 +57,9 @@ public class ExponentialMovingAverageRate {
this.period = period * 1000; // convert to millisecs
}
/**
* Add a new event to the series.
*/
public void increment() {
long t = System.currentTimeMillis();
@@ -66,6 +78,9 @@ public class ExponentialMovingAverageRate {
}
/**
* @return the number of measurements recorded
*/
public int getCount() {
return rates.getCount();
}
@@ -77,9 +92,12 @@ public class ExponentialMovingAverageRate {
return (System.currentTimeMillis() - t0) / 1000.;
}
/**
* @return the mean value
*/
public double getMean() {
int count = rates.getCount();
if (count==0) {
if (count == 0) {
return 0;
}
long t = System.currentTimeMillis();
@@ -87,18 +105,30 @@ public class ExponentialMovingAverageRate {
return count / (count / rates.getMean() + value);
}
/**
* @return the approximate standard deviation
*/
public double getStandardDeviation() {
return rates.getStandardDeviation();
}
/**
* @return the maximum value recorded (not weighted)
*/
public double getMax() {
return min > 0 ? 1 / min : 0;
}
/**
* @return the minimum value recorded (not weighted)
*/
public double getMin() {
return max > 0 ? 1 / max : 0;
}
/**
* @return summary statistics (count, mean, standard deviation etc.)
*/
public Statistics getStatistics() {
return new Statistics(getCount(), min, max, getMean(), getStandardDeviation());
}

View File

@@ -13,9 +13,15 @@
package org.springframework.integration.monitor;
/**
* Cumulative statistics for success rate (ratio) with higher weight given to recent data but without storing any
* history. Older values are given exponentially smaller weight, with a decay factor determined by a duration chosen by
* the client.
* Cumulative statistics for success ratio with higher weight given to recent data but without storing any history.
* Clients call {@link #success()} or {@link #failure()} when an event occurs, and the ratio of success to total events
* is accumulated. Older values are given exponentially smaller weight, with a decay factor determined by a duration
* chosen by the client. The rate measurement weights decay in two dimensions:
* <ul>
* <li>in time according to the lapse period supplied: <code>weight = exp((t0-t)/T)</code> where <code>t0</code> is the
* last measurement time, <code>t</code> is the current time and <code>T</code> is the lapse period)</li>
* <li>per measurement according to the lapse window supplied: <code>weight = exp(-i/L)</code> where <code>L</code> is
* the lapse window and <code>i</code> is the sequence number of the measurement.</li>
*
* @author Dave Syer
*
@@ -41,10 +47,16 @@ public class ExponentialMovingAverageRatio {
this.lapse = lapsePeriod > 0 ? 0.001 / lapsePeriod : 0; // convert to millisecs
}
/**
* Add a new event with successful outcome.
*/
public void success() {
append(1);
}
/**
* Add a new event with failed outcome.
*/
public void failure() {
append(0);
}
@@ -60,6 +72,9 @@ public class ExponentialMovingAverageRatio {
}
/**
* @return the number of measurements recorded
*/
public int getCount() {
return cumulative.getCount();
}
@@ -71,6 +86,9 @@ public class ExponentialMovingAverageRatio {
return (System.currentTimeMillis() - t0) / 1000.;
}
/**
* @return the mean success rate
*/
public double getMean() {
int count = cumulative.getCount();
if (count == 0) {
@@ -81,18 +99,30 @@ public class ExponentialMovingAverageRatio {
return alpha * cumulative.getMean() + 1 - alpha;
}
/**
* @return the approximate standard deviation of the success rate measurements
*/
public double getStandardDeviation() {
return cumulative.getStandardDeviation();
}
/**
* @return the maximum value recorded of the exponential weighted average (per measurement) success rate
*/
public double getMax() {
return cumulative.getMax();
}
/**
* @return the minimum value recorded of the exponential weighted average (per measurement) success rate
*/
public double getMin() {
return cumulative.getMin();
}
/**
* @return summary statistics (count, mean, standard deviation etc.)
*/
public Statistics getStatistics() {
return new Statistics(getCount(), getMin(), getMax(), getMean(), getStandardDeviation());
}

View File

@@ -56,7 +56,25 @@ import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* MBean exporter for Spring Integration components in an existing application.
* <p>
* MBean exporter for Spring Integration components in an existing application. Add an instance of this as a bean
* definition in the same context as the components you need to monitor and all message channels and message handlers
* will be exposed.
* </p>
* <p>
* Channels will report metrics on send and receive (counts, rates, errors) and handlers will report metrics on
* execution duration. Channels will be registered under their name (bean id), if explicit, or the last part of their
* internal name (e.g. "nullChannel") if registered by the framework. A handler that is attached to an endpoint will be
* registered with the endpoint name (bean id) if there is one, otherwise under the name of the input channel. Handler
* object names contain a <code>bean</code> key that reports the source of the name: "endpoint" if the name is the
* endpoint id; "anonymous" if it is the input channel; and "handler" as a fallback, where the object name is just the
* <code>toString()</code> of the handler.
* </p>
* <p>
* This component is itself an MBean, reporting attributes concerning the names and object names of the channels and
* handlers. It doesn't register itself to avoid conflicts with the standard <code>&lt;context:mbean-export/&gt;</code>
* from Spring (which should therefore be used any time you need to expose those features).
* </p>
*
* @author Dave Syer
* @author Helena Edelson
@@ -288,13 +306,13 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
public Map<String, String> getObjectNames() {
return Collections.unmodifiableMap(objectNamesByName);
}
public Statistics getHandlerDuration(String name) {
if (handlersByName.containsKey(name)) {
return handlersByName.get(name).getDuration();
}
logger.debug("No handler found for (" + name + ")");
return null;
return null;
}
public int getChannelReceiveCount(String name) {
@@ -355,8 +373,7 @@ public class IntegrationMBeanExporter extends MBeanExporter implements BeanPostP
}
}
private Object applyChannelInterceptor(Object bean, DirectChannelMonitor interceptor,
ClassLoader beanClassLoader) {
private Object applyChannelInterceptor(Object bean, DirectChannelMonitor interceptor, ClassLoader beanClassLoader) {
NameMatchMethodPointcutAdvisor channelsAdvice = new NameMatchMethodPointcutAdvisor(interceptor);
channelsAdvice.addMethodName("send");
channelsAdvice.addMethodName("receive");

View File

@@ -21,15 +21,19 @@ import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
/**
* A {@link MessageHandlerMonitor} that exposes in addition the {@link Lifecycle} interface. The lifecycle methods can
* be used to stop and start polling endpoints, for instance, in a live system.
*
* @author Dave Syer
*
* @since 2.0
*
*
*/
@ManagedResource
public class LifecycleMessageHandlerMonitor implements MessageHandlerMonitor {
public class LifecycleMessageHandlerMonitor implements MessageHandlerMonitor, Lifecycle {
private final Lifecycle lifecycle;
private final MessageHandlerMonitor delegate;
public LifecycleMessageHandlerMonitor(Lifecycle lifecycle, MessageHandlerMonitor delegate) {

View File

@@ -19,45 +19,89 @@ import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.support.MetricType;
/**
* @author dsyer
*
* Interface for all message channel monitors containing accessors for various useful metrics that are generic for all
* channel types.
*
* @author Dave Syer
*
* @since 2.0
*
*/
public interface MessageChannelMonitor {
/**
* @return the number of successful sends
*/
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Sends")
int getSendCount();
/**
* @return the number of failed sends (either throwing an exception or rejected by the channel)
*/
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "MessageChannel Send Errors")
int getSendErrorCount();
/**
* @return the time in seconds since the last send
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Time Since Last Send in Seconds")
double getTimeSinceLastSend();
/**
* @return the mean send rate (per second)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Send Rate per Second")
double getMeanSendRate();
/**
* @return the mean error rate (per second). Errors comprise all failed sends.
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Error Rate per Second")
double getMeanErrorRate();
/**
* @return the mean ratio of failed to successful sends in approximately the last minute
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Mean Channel Error Ratio per Minute")
double getMeanErrorRatio();
/**
* @return the mean send duration (milliseconds)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Send Mean Duration")
double getMeanSendDuration();
/**
* @return the minimum send duration (milliseconds) since startup
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Send Min Duration")
double getMinSendDuration();
/**
* @return the maximum send duration (milliseconds) since startup
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Send Max Duration")
double getMaxSendDuration();
/**
* @return the standard deviation send duration (milliseconds)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Channel Send Standard Deviation Duration")
double getStandardDeviationSendDuration();
/**
* @return summary statistics about the send duration (milliseconds)
*/
Statistics getSendDuration();
/**
* @return summary statistics about the send rates (per second)
*/
Statistics getSendRate();
/**
* @return summary statistics about the error rates (per second)
*/
Statistics getErrorRate();
}

View File

@@ -25,24 +25,42 @@ import org.springframework.jmx.support.MetricType;
*/
public interface MessageHandlerMonitor {
/**
* @return the number of successful handler calls
*/
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Handler Execution Count", description = "rate=1h")
int getHandleCount();
/**
* @return the number of failed handler calls
*/
@ManagedMetric(metricType = MetricType.COUNTER, displayName = "Handler Error Count", description = "rate=1h")
int getErrorCount();
/**
* @return the maximum handler duration (milliseconds)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Handler Mean Duration")
double getMeanDuration();
/**
* @return the minimum handler duration (milliseconds)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Handler Min Duration")
double getMinDuration();
/**
* @return the standard deviation handler duration (milliseconds)
*/
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Handler Max Duration")
double getMaxDuration();
@ManagedMetric(metricType = MetricType.GAUGE, displayName = "Handler Standard Deviation Duration")
double getStandardDeviationDuration();
/**
* @return summary statistics about the handler duration (milliseconds)
*/
Statistics getDuration();
String getName();

View File

@@ -18,6 +18,8 @@ package org.springframework.integration.monitor;
import java.util.Map;
/**
* Locator interface for mapping bean names to JMX object names.
*
* @author Dave Syer
*
* @since 2.0
@@ -25,8 +27,15 @@ import java.util.Map;
*/
public interface ObjectNameLocator {
/**
* @param beanName the bean name to query
* @return a String representation of the corresponding JMX object name (or null if there is none)
*/
String getObjectName(String beanName);
/**
* @return a map of all the known bean and object names
*/
Map<String, String> getObjectNames();
}