/* * JBoss, the OpenSource EJB server * * Distributable under LGPL license. * See terms of license at gnu.org. */ package javax.management.monitor; import javax.management.MBeanAttributeInfo; import javax.management.MBeanNotificationInfo; // REVIEW: Check synchronization /** * The gauge monitor service. * * @author Adrian Brock * @version $Revision: 1.2 $ * */ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean { // Constants ----------------------------------------------------- /** * The gauge high threshold exceeded has been notified. */ int THRESHOLD_HIGH_EXCEEDED_NOTIFIED = 16; /** * The gauge low threshold exceeded has been notified. */ int THRESHOLD_LOW_EXCEEDED_NOTIFIED = 32; /** * The threshold type error has been notified. */ int THRESHOLD_ERROR_NOTIFIED = 64; // Attributes ---------------------------------------------------- /** * The derived gauge. */ private Number derivedGauge = new Integer(0); /** * The last value. */ private Number lastValue = null; /** * The derived gauge timeStamp. */ private long derivedGaugeTimeStamp = 0; /** * Difference mode. */ boolean differenceMode = false; /** * The high threshold. */ Number highThreshold = new Integer(0); /** * The low threshold. */ Number lowThreshold = new Integer(0); /** * High Notify. */ boolean notifyHigh = false; /** * Low Notify. */ boolean notifyLow = false; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- /** * Default Constructor */ public GaugeMonitor() { dbgTag = "GaugeMonitor"; } // Public -------------------------------------------------------- public MBeanNotificationInfo[] getNotificationInfo() { MBeanNotificationInfo[] result = new MBeanNotificationInfo[1]; String[] types = new String[] { MonitorNotification.RUNTIME_ERROR, MonitorNotification.OBSERVED_OBJECT_ERROR, MonitorNotification.OBSERVED_ATTRIBUTE_ERROR, MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR, MonitorNotification.THRESHOLD_ERROR, MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED, MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED }; result[0] = new MBeanNotificationInfo(types, "javax.management.monitor.MonitorNotification", "Notifications sent by the Gauge Monitor Service MBean"); return result; } // GaugeMonitorMBean implementation ------------------------------ public Number getDerivedGauge() { return derivedGauge; } public long getDerivedGaugeTimeStamp() { return derivedGaugeTimeStamp; } public boolean getDifferenceMode() { return differenceMode; } public void setDifferenceMode(boolean value) { differenceMode = value; } public boolean getNotifyHigh() { return notifyHigh; } public void setNotifyHigh(boolean value) { notifyHigh = value; } public boolean getNotifyLow() { return notifyLow; } public void setNotifyLow(boolean value) { notifyLow = value; } public Number getHighThreshold() { return highThreshold; } public Number getLowThreshold() { return lowThreshold; } public void setThresholds(Number highValue, Number lowValue) throws IllegalArgumentException { if (highValue == null) throw new IllegalArgumentException("Null high threshold"); if (lowValue == null) throw new IllegalArgumentException("Null low threshold"); if (highValue.getClass() != lowValue.getClass()) throw new IllegalArgumentException("High and low different types"); if (highValue.doubleValue() < lowValue.doubleValue()) throw new IllegalArgumentException("High less than low threshold"); highThreshold = highValue; lowThreshold = lowValue; alreadyNotified = RESET_FLAGS_ALREADY_NOTIFIED; } // Override start to reset the last value for difference mode and // to get the initial gauge. public synchronized void start() { lastValue = null; derivedGauge = new Integer(0); derivedGaugeTimeStamp = System.currentTimeMillis(); super.start(); } // Package protected --------------------------------------------- // REVIEW: This works but needs tidying up! void monitor(MBeanAttributeInfo attributeInfo, Object value) throws Exception { // Wrong type of attribute if (!(value instanceof Number)) { sendAttributeTypeErrorNotification("Attribute is not a number"); return; } // Wrong threshold types if (highThreshold.getClass() != value.getClass() || lowThreshold.getClass() != value.getClass()) { sendThresholdErrorNotification(value); return; } // Cast the gauge to a Number Number number = (Number) value; // Get the gauge and record when we got it. if (differenceMode) { if (lastValue == null) derivedGauge = getZero(number); else derivedGauge = sub(number, lastValue); } else derivedGauge = number; derivedGaugeTimeStamp = System.currentTimeMillis(); // Fire the event if the low threshold has been exceeded if (derivedGauge.doubleValue() <= lowThreshold.doubleValue()) { if ((alreadyNotified & THRESHOLD_LOW_EXCEEDED_NOTIFIED) == 0) { // Reset high threshold alreadyNotified &= ~THRESHOLD_HIGH_EXCEEDED_NOTIFIED; // Send the notification once sendThresholdLowExceededNotification(derivedGauge); alreadyNotified |= THRESHOLD_LOW_EXCEEDED_NOTIFIED; } } // Fire the event if the high threshold has been exceeded if (derivedGauge.doubleValue() >= highThreshold.doubleValue()) { if ((alreadyNotified & THRESHOLD_HIGH_EXCEEDED_NOTIFIED) == 0) { // Reset low threshold alreadyNotified &= ~THRESHOLD_LOW_EXCEEDED_NOTIFIED; // Send the notification once sendThresholdHighExceededNotification(derivedGauge); alreadyNotified |= THRESHOLD_HIGH_EXCEEDED_NOTIFIED; } } // Remember the last value lastValue = number; } /** * Get zero for the type passed. * * @param the reference object * @return zero for the correct type */ Number getZero(Number value) { if (value instanceof Byte) return new Byte((byte) 0); if (value instanceof Integer) return new Integer(0); if (value instanceof Long) return new Long(0); if (value instanceof Short) return new Short((short) 0); if (value instanceof Float) return new Float((float) 0); return new Double((double) 0); } /** * Subtract two numbers. * @param value1 the first value. * @param value2 the second value. * @return value1 - value2 of the correct type */ Number sub(Number value1, Number value2) { if (value1 instanceof Byte) return new Byte((byte) (value1.byteValue() - value2.byteValue())); if (value1 instanceof Integer) return new Integer(value1.intValue() - value2.intValue()); if (value1 instanceof Long) return new Long((value1.longValue() - value2.longValue())); if (value1 instanceof Short) return new Short((short) (value1.shortValue() - value2.shortValue())); if (value1 instanceof Float) return new Float((value1.floatValue() - value2.floatValue())); return new Double(value1.doubleValue() - value2.doubleValue()); } /** * Send a threshold low exceeded event.
* * This is only performed when requested and it has not already been sent. * * @param value the attribute value. */ void sendThresholdLowExceededNotification(Object value) { if (notifyLow) { sendNotification(MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED, derivedGaugeTimeStamp, "low threshold exceeded", observedAttribute, value, lowThreshold); } } /** * Send a high threshold exceeded event.
* * This is only performed when requested and it has not already been sent. * * @param value the attribute value. */ void sendThresholdHighExceededNotification(Object value) { if (notifyHigh) { sendNotification(MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED, derivedGaugeTimeStamp, "high threshold exceeded", observedAttribute, value, highThreshold); } } /** * Send a threshold error event.
* * This is only performed when requested and it has not already been sent. * * @param value the attribute value. */ void sendThresholdErrorNotification(Object value) { if ((alreadyNotified & THRESHOLD_ERROR_NOTIFIED) == 0) { sendNotification(MonitorNotification.THRESHOLD_ERROR, derivedGaugeTimeStamp, "High or Low Threshold not the correct type", observedAttribute, null, null); alreadyNotified |= THRESHOLD_ERROR_NOTIFIED; } } // Protected ----------------------------------------------------- // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- }