package com.intrbiz.bergamot.model.message.result;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.function.BiPredicate;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.intrbiz.bergamot.model.message.Message;
import com.intrbiz.bergamot.model.message.ParameterMO;
import com.intrbiz.bergamot.model.message.ParameterisedMO;
/**
* The result of a check
*/
public abstract class ResultMO extends Message implements ParameterisedMO
{
@JsonProperty("ok")
private boolean ok;
@JsonProperty("status")
private String status;
@JsonProperty("executed")
private long executed;
@JsonProperty("processed")
private long processed;
@JsonProperty("runtime")
private double runtime;
@JsonProperty("output")
private String output;
@JsonProperty("parameters")
private List<ParameterMO> parameters = new LinkedList<ParameterMO>();
/**
* An id added to adhoc checks to correlate
* them with with the originator. This must
* be null for normal check executions
*/
@JsonProperty("adhoc_id")
private UUID adhocId;
public ResultMO()
{
super();
}
public boolean isOk()
{
return ok;
}
public void setOk(boolean ok)
{
this.ok = ok;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public long getExecuted()
{
return executed;
}
public void setExecuted(long executed)
{
this.executed = executed;
}
public long getProcessed()
{
return processed;
}
public void setProcessed(long processed)
{
this.processed = processed;
}
public double getRuntime()
{
return runtime;
}
public void setRuntime(double runtime)
{
this.runtime = runtime;
}
public String getOutput()
{
return output;
}
public void setOutput(String output)
{
this.output = output;
}
public List<ParameterMO> getParameters()
{
return parameters;
}
public void setParameters(List<ParameterMO> parameters)
{
this.parameters = parameters;
}
public void addParameter(String name, String value)
{
this.parameters.add(new ParameterMO(name, value));
}
public void setParameter(String name, String value)
{
this.removeParameter(name);
this.addParameter(name, value);
}
public void removeParameter(String name)
{
for (Iterator<ParameterMO> i = this.parameters.iterator(); i.hasNext();)
{
if (name.equals(i.next().getName()))
{
i.remove();
break;
}
}
}
public void clearParameters()
{
this.parameters.clear();
}
public String getParameter(String name)
{
return this.getParameter(name, null);
}
public String getParameter(String name, String defaultValue)
{
for (ParameterMO parameter : this.parameters)
{
if (name.equals(parameter.getName())) return parameter.getValue();
}
return defaultValue;
}
public UUID getAdhocId()
{
return adhocId;
}
public void setAdhocId(UUID adhocId)
{
this.adhocId = adhocId;
}
// constructor helpers
@JsonIgnore
public ResultMO runtime(double runtime)
{
this.runtime = runtime;
return this;
}
@JsonIgnore
public ResultMO pending(String output)
{
this.setOk(true);
this.setStatus("PENDING");
this.setOutput(output);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO info(String message)
{
this.setOk(true);
this.setStatus("INFO");
this.setOutput(message);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO ok(String output)
{
this.setOk(true);
this.setStatus("OK");
this.setOutput(output);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO warning(String output)
{
this.setOk(false);
this.setStatus("WARNING");
this.setOutput(output);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO critical(String output)
{
this.setOk(false);
this.setStatus("CRITICAL");
this.setOutput(output);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO unknown(String output)
{
this.setOk(false);
this.setStatus("UNKNOWN");
this.setOutput(output);
this.setRuntime(0);
return this;
}
/**
* Update this result with the error information
* @param t
* @return
*/
@JsonIgnore
public ResultMO error(Throwable t)
{
this.setOk(false);
this.setStatus("ERROR");
this.setOutput(t.getMessage());
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO error(String message)
{
this.setOk(false);
this.setStatus("ERROR");
this.setOutput(message);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO timeout(String message)
{
this.setOk(false);
this.setStatus("TIMEOUT");
this.setOutput(message);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO disconnected(String message)
{
this.setOk(false);
this.setStatus("DISCONNECTED");
this.setOutput(message);
this.setRuntime(0);
return this;
}
@JsonIgnore
public ResultMO action(String message)
{
this.setOk(false);
this.setStatus("ACTION");
this.setOutput(message);
this.setRuntime(0);
return this;
}
/**
* Apply a warning / critical threshold to determine the result state, this will
* result in either a ok, warning or critical state depending on the value and
* thresholds
*
* @param value the value to check
* @param match the BiPredicate which will apply the threshold comparison, EG: (v,t) -> v > t
* @param warning the warning threshold
* @param critical the critical threshold
* @param message the check output
*/
@JsonIgnore
public <V,T> ResultMO applyThreshold(V value, BiPredicate<V,T> match, T warning, T critical, String message)
{
if ( match.test(value, critical))
{
this.critical(message);
}
else if (match.test(value, warning))
{
this.warning(message);
}
else
{
this.ok(message);
}
return this;
}
/**
* Apply a warning / critical threshold to determine the result state, this will
* result in either a ok, warning or critical state depending on the values and
* thresholds.
*
* This applies a threshold check to a collection of values, with the worst status
* being the status of this result.
*
* @param values the values to check
* @param match the BiPredicate which will apply the threshold comparison, EG: (v,t) -> v > t
* @param warning the warning threshold
* @param critical the critical threshold
* @param message the check output
*/
@JsonIgnore
public <V,T> ResultMO applyThresholds(Iterable<V> values, BiPredicate<V,T> match, T warning, T critical, String message)
{
int state = 0;
for (V value : values)
{
if (match.test(value, critical))
{
state = Math.max(state, 2);
}
else if (match.test(value, warning))
{
state = Math.max(state, 1);
}
else
{
state = Math.max(state, 0);
}
}
switch (state)
{
case 0:
this.ok(message);
break;
case 1:
this.warning(message);
break;
case 2:
this.critical(message);
break;
}
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThreshold(Double value, Double warning, Double critical, String message)
{
this.applyThreshold(value, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThreshold(Double value, Double warning, Double critical, String message)
{
this.applyThreshold(value, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThreshold(Float value, Float warning, Float critical, String message)
{
this.applyThreshold(value, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThreshold(Float value, Float warning, Float critical, String message)
{
this.applyThreshold(value, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThreshold(Long value, Long warning, Long critical, String message)
{
this.applyThreshold(value, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThreshold(Long value, Long warning, Long critical, String message)
{
this.applyThreshold(value, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThreshold(Integer value, Integer warning, Integer critical, String message)
{
this.applyThreshold(value, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThreshold(Integer value, Integer warning, Integer critical, String message)
{
this.applyThreshold(value, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThresholds(Iterable<Double> values, Double warning, Double critical, String message)
{
this.applyThresholds(values, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThresholds(Iterable<Double> values, Double warning, Double critical, String message)
{
this.applyThresholds(values, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThresholds(Iterable<Float> values, Float warning, Float critical, String message)
{
this.applyThresholds(values, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThresholds(Iterable<Float> values, Float warning, Float critical, String message)
{
this.applyThresholds(values, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThresholds(Iterable<Long> values, Long warning, Long critical, String message)
{
this.applyThresholds(values, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThresholds(Iterable<Long> values, Long warning, Long critical, String message)
{
this.applyThresholds(values, (v,t) -> v < t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyGreaterThanThresholds(Iterable<Integer> values, Integer warning, Integer critical, String message)
{
this.applyThresholds(values, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyLessThanThresholds(Iterable<Integer> values, Integer warning, Integer critical, String message)
{
this.applyThresholds(values, (v,t) -> v < t, warning, critical, message);
return this;
}
/**
* Apply a warning / critical range to determine the result state, this will
* result in either a ok, warning or critical state depending on the value and
* ranges
*
* @param value the value to check
* @param lowerMatch the BiPredicate which will apply the range lower comparison, eg: (v,t) -> v < t
* @param upperMatch the BiPredicate which will apply the range upper comparison, eg: (v,t) -> v > t
* @param warning the warning range
* @param critical the critical range
* @param message the check output
*/
@JsonIgnore
public <V,T> ResultMO applyRange(V value, BiPredicate<V,T> lowerMatch, BiPredicate<V,T> upperMatch, T[] warning, T[] critical, String message)
{
if (lowerMatch.test(value, critical[0]) || upperMatch.test(value, critical[1]))
{
this.critical(message);
}
else if (lowerMatch.test(value, warning[0]) || upperMatch.test(value, warning[1]))
{
this.warning(message);
}
else
{
this.ok(message);
}
return this;
}
@JsonIgnore
public ResultMO applyRange(Long value, Long[] warning, Long[] critical, String message)
{
this.applyRange(value, (v,t) -> v < t, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyRange(Integer value, Integer[] warning, Integer[] critical, String message)
{
this.applyRange(value, (v,t) -> v < t, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyRange(Double value, Double[] warning, Double[] critical, String message)
{
this.applyRange(value, (v,t) -> v < t, (v,t) -> v > t, warning, critical, message);
return this;
}
@JsonIgnore
public ResultMO applyRange(Float value, Float[] warning, Float[] critical, String message)
{
this.applyRange(value, (v,t) -> v < t, (v,t) -> v > t, warning, critical, message);
return this;
}
}