/*
* NOTE: This copyright doesnot cover user programs that use HQ program services
* by normal system calls through the application program interfaces provided as
* part of the Hyperic Plug-in Development Kit or the Hyperic Client Development
* Kit - this is merely considered normal use of the program, and doesnot fall
* under the heading of "derived work". Copyright (C) [2004, 2005, 2006],
* Hyperic, Inc. This file is part of HQ. HQ is free software; you can
* redistribute it and/or modify it under the terms version 2 of the GNU General
* Public License as published by the Free Software Foundation. This program is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details. You
* should have received a copy of the GNU General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package org.hyperic.hq.bizapp.server.trigger.conditional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.hq.bizapp.shared.ConditionalTriggerSchema;
import org.hyperic.hq.events.AbstractEvent;
import org.hyperic.hq.events.EventConstants;
import org.hyperic.hq.events.EventTypeException;
import org.hyperic.hq.events.InvalidTriggerDataException;
import org.hyperic.hq.events.TriggerFiredEvent;
import org.hyperic.hq.events.ext.AbstractTrigger;
import org.hyperic.hq.events.server.session.AlertConditionEvaluator;
import org.hyperic.hq.events.shared.AlertConditionValue;
import org.hyperic.hq.events.shared.RegisteredTriggerValue;
import org.hyperic.hq.measurement.ext.MeasurementEvent;
import org.hyperic.hq.product.MetricValue;
import org.hyperic.util.config.ConfigResponse;
import org.hyperic.util.config.ConfigSchema;
import org.hyperic.util.config.EncodingException;
import org.hyperic.util.config.InvalidOptionException;
import org.hyperic.util.config.InvalidOptionValueException;
/**
* A simple trigger which fires if a measurement event exceeds a threshold.
*/
public class MeasurementThresholdTrigger
extends AbstractTrigger implements ConditionalTriggerInterface
{
static {
// Register the trigger/condition
ConditionalTriggerInterface.MAP_COND_TRIGGER.put(new Integer(EventConstants.TYPE_THRESHOLD),
MeasurementThresholdTrigger.class);
}
private final Log log = LogFactory.getLog(getClass().getName());
private final int OPER_LE = ConditionalTriggerSchema.OPER_LE;
private final int OPER_LT = ConditionalTriggerSchema.OPER_LT;
private final int OPER_EQ = ConditionalTriggerSchema.OPER_EQ;
private final int OPER_GT = ConditionalTriggerSchema.OPER_GT;
private final int OPER_GE = ConditionalTriggerSchema.OPER_GE;
private final int OPER_NE = ConditionalTriggerSchema.OPER_NE;
private final String[] OPER_STRS = ConditionalTriggerSchema.OPER_STRS;
private int operator;
private double threshold;
private Integer metricId;
public ConfigResponse getConfigResponse() {
ConfigResponse resp = new ConfigResponse();
resp.setValue(CFG_ID, String.valueOf(getMeasurementID()));
resp.setValue(CFG_THRESHOLD, String.valueOf(getThreshold()));
resp.setValue(CFG_COMPARATOR, OPER_STRS[getOperator()]);
return resp;
}
public ConfigResponse getConfigResponse(AppdefEntityID id, AlertConditionValue cond) throws InvalidOptionException,
InvalidOptionValueException
{
if (cond.getType() != EventConstants.TYPE_THRESHOLD) {
throw new InvalidOptionValueException("Condition is not a Measurement Threshold");
}
return getSharedConfigResponse(cond);
}
/**
* @see org.hyperic.hq.events.ext.RegisterableTriggerInterface#getConfigSchema()
*/
public ConfigSchema getConfigSchema() {
return ConditionalTriggerSchema.getConfigSchema(EventConstants.TYPE_THRESHOLD);
}
/**
* @see org.hyperic.hq.events.ext.RegisterableTriggerInterface#getInterestedEventTypes()
*/
public Class[] getInterestedEventTypes() {
return new Class[] { MeasurementEvent.class };
}
/**
* @see org.hyperic.hq.events.ext.RegisterableTriggerInterface#getInterestedInstanceIDs(java.lang.Class)
*/
public Integer[] getInterestedInstanceIDs(Class c) {
return new Integer[] { metricId };
}
public Integer getMeasurementID() {
return metricId;
}
public int getOperator() {
return operator;
}
/**
* extracts the operator
*/
protected int getOperator(String soperator) throws InvalidTriggerDataException {
int operator = -1;
for (int i = 1; i < OPER_STRS.length; i++) {
if (soperator.equals(OPER_STRS[i])) {
operator = i;
break;
}
}
if (operator == -1) {
throw new InvalidTriggerDataException("Invalid operator, '" + soperator + "'");
}
return operator;
}
protected ConfigResponse getSharedConfigResponse(AlertConditionValue cond) throws InvalidOptionException,
InvalidOptionValueException
{
ConfigResponse resp = new ConfigResponse();
resp.setValue(CFG_ID, String.valueOf(cond.getMeasurementId()));
resp.setValue(CFG_THRESHOLD, String.valueOf(cond.getThreshold()));
resp.setValue(CFG_COMPARATOR, cond.getComparator());
return resp;
}
public double getThreshold() {
return threshold;
}
/**
* @see org.hyperic.hq.events.ext.RegisterableTriggerInterface#init(org.hyperic.hq.events.shared.RegisteredTriggerValue)
*/
public void init(RegisteredTriggerValue tval, AlertConditionEvaluator alertConditionEvaluator) throws InvalidTriggerDataException
{
ConfigResponse triggerData;
String soperator, sthreshold, smeasID;
Integer measID;
int oper;
double thresh;
setId(tval.getId());
setAlertConditionEvaluator(alertConditionEvaluator);
// Decode the configuration
try {
triggerData = ConfigResponse.decode(tval.getConfig());
soperator = triggerData.getValue(CFG_COMPARATOR);
sthreshold = triggerData.getValue(CFG_THRESHOLD);
smeasID = triggerData.getValue(CFG_ID);
} catch (EncodingException e) {
throw new InvalidTriggerDataException(e);
}
if ((soperator == null) || (sthreshold == null) || (smeasID == null)) {
throw new InvalidTriggerDataException(CFG_COMPARATOR + " = '" + soperator + "' " + CFG_THRESHOLD + " = '" +
sthreshold + "' " + CFG_ID + " = '" + smeasID + "'");
}
oper = getOperator(soperator);
try {
measID = new Integer(smeasID);
} catch (NumberFormatException exc) {
throw new InvalidTriggerDataException("Instance id, '" + smeasID + "' is not a valid number");
}
try {
thresh = Double.parseDouble(sthreshold);
} catch (NumberFormatException exc) {
throw new InvalidTriggerDataException("Threshold, '" + sthreshold + "' is not a valid number");
}
operator = oper;
threshold = thresh;
metricId = measID;
}
private void logComparison(String operator, double compVal) {
if (log.isDebugEnabled()) {
log.debug("Evaluating if " + compVal + " " + operator + " " + threshold);
}
}
public void processEvent(AbstractEvent e) throws EventTypeException {
if (!(e instanceof MeasurementEvent)) {
throw new EventTypeException("Invalid event type passed, " + "expected MeasurementEvent");
}
if (!e.getInstanceId().equals(metricId)) {
return;
}
boolean fire;
MeasurementEvent event = (MeasurementEvent) e;
MetricValue val = event.getValue();
double compVal = val.getValue();
if (operator == OPER_LE) {
fire = compVal <= threshold;
logComparison("<=", compVal);
} else if (operator == OPER_LT) {
fire = compVal < threshold;
logComparison("<", compVal);
} else if (operator == OPER_EQ) {
fire = compVal == threshold;
logComparison("==", compVal);
} else if (operator == OPER_GT) {
fire = compVal > threshold;
logComparison(">", compVal);
} else if (operator == OPER_GE) {
fire = compVal >= threshold;
logComparison(">=", compVal);
} else if (operator == OPER_NE) {
fire = compVal != threshold;
logComparison("!=", compVal);
} else {
// Wow -- we should never get here -- throw an assertion
throw new RuntimeException("Invalid threshold operation!");
}
// Don't do any more if condition was unmet
if (fire == false) {
notFired(e);
return;
}
TriggerFiredEvent tfe = prepareTriggerFiredEvent(event);
tfe.setMessage("Metric(" + metricId + ") value " + val + " " + OPER_STRS[operator] + " " + threshold);
fireActions(tfe);
}
public void setMeasurementID(Integer val) {
metricId = val;
}
public void setOperator(int val) {
operator = val;
}
public void setThreshold(double val) {
threshold = val;
}
}