package se.l4.vibe.trigger; import java.util.concurrent.TimeUnit; import se.l4.vibe.internal.MergedTrigger; import se.l4.vibe.probes.Average; import se.l4.vibe.probes.Change; import se.l4.vibe.probes.Probe; import se.l4.vibe.probes.Range; import se.l4.vibe.probes.Sum; import se.l4.vibe.probes.Sampler; /** * Triggers that can be used together with monitoring. * * @author Andreas Holstenson * */ public class Triggers { private Triggers() { } /** * Get a trigger that will return the exact value of a probe. * * @return */ public static <T> Trigger<T, T> value() { return new Trigger<T, T>() { @Override public Probe<T> forSampler(Sampler<T> series) { return series.getProbe(); } @Override public String toString() { return "value"; } }; } /** * Get a trigger that will return the exact value of a probe as a number. * * @return */ public static <T extends Number> Trigger<T, Number> numericValue() { return new Trigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) series.getProbe(); } @Override public String toString() { return "value"; } }; } /** * Calculate the average for a specific duration and check conditions * against the specified value. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> averageOver(final long duration, final TimeUnit unit) { return new TimedTrigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Average.forSampler(series, duration, unit); } @Override public long getDefaultRepeatTime() { return unit.toMillis(duration); } @Override public String toString() { return "average over " + duration + " " + toReadable(unit, duration); } }; } /** * Calculate the minimum value over a specific duration. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> minimumOver(final long duration, final TimeUnit unit) { return new TimedTrigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Range.minimum(series, duration, unit); } @Override public long getDefaultRepeatTime() { return unit.toMillis(duration); } @Override public String toString() { return "minimum over " + duration + " " + toReadable(unit, duration); } }; } /** * Calculate the maximum value over a specific duration. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> maximumOver(final long duration, final TimeUnit unit) { return new TimedTrigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Range.maximum(series, duration, unit); } @Override public long getDefaultRepeatTime() { return unit.toMillis(duration); } @Override public String toString() { return "maximum over " + duration + " " + toReadable(unit, duration); } }; } /** * Calculate the change between sample values. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> change() { return new Trigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return Change.forSampler(series); } @Override public String toString() { return "change"; } }; } /** * Calculate the change between sample values and return it as a fraction. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> changeAsFraction() { return new Trigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Change.asFraction(series); } @Override public String toString() { return "change as fraction"; } }; } /** * Calculate the sum. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> sum() { return new Trigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Sum.forSamplerAsDouble(series); } @Override public String toString() { return "sum"; } }; } /** * Calculate the sum for a specific duration and check conditions * against the specified value. * * @param duration * @param unit * @return */ public static <T extends Number> Trigger<T, Number> sumOver(final long duration, final TimeUnit unit) { return new TimedTrigger<T, Number>() { @Override public Probe<Number> forSampler(Sampler<T> series) { return (Probe) Sum.forSamplerAsDouble(series, duration, unit); } @Override public long getDefaultRepeatTime() { return unit.toMillis(duration); } @Override public String toString() { return "sum over " + duration + " " + toReadable(unit, duration); } }; } /** * Create a middle value to perform triggering on. This allows one to * to create triggers on values returned by other triggers. * * <p> * Example: * <pre> * when(change(), on(sum()), above(0.8)) * </pre> * * @param trigger * @return */ public static <Input, Output> On<Input, Output> on( final Trigger<Input, Output> trigger ) { return new On<Input, Output>() { @Override public <T> Trigger<Input, T> build(Trigger<Output, T> second) { return new MergedTrigger<Input, T>(trigger, second); } }; } private static String toReadable(TimeUnit unit, long duration) { boolean one = duration == 1; switch(unit) { case DAYS: return one ? "day" : "days"; case HOURS: return one ? "hour" : "hours"; case MICROSECONDS: return one ? "microsecond" : "microseconds"; case MILLISECONDS: return one ? "millisecond" : "milliseconds"; case MINUTES: return one ? "minute" : "minutes"; case NANOSECONDS: return one ? "nanosecond" : "nanoseconds"; case SECONDS: return one ? "second" : "seconds"; } return unit.toString(); } }