Skip to content

Instantly share code, notes, and snippets.

@aphyr
Created December 23, 2014 20:53
Show Gist options
  • Save aphyr/6f0923c508e8741d59a5 to your computer and use it in GitHub Desktop.
Save aphyr/6f0923c508e8741d59a5 to your computer and use it in GitHub Desktop.
Riemann hysterisis
(defn hysteresis?
"Returns an event predicate which tests the metric of an event and allows
for hysteresis. Requires two predicates to test metrics: a trigger?
predicate and a hold? predicate. trigger? and hold? should be defined
such that if trigger? is true, then hold? is true (and, conversely, if
hold? is false, then trigger? is false).
If the metric is true for trigger?, hyesteresis? will return true. If
the metric returns false for hold?, hystersis? will return false. If
hold? is true and trigger? is false, hysteresis? will return the value
it returned for the previous invocation of hysteresis?. That is,
when in the hold? state (hold? true and trigger? false), hystersis?
holds the previous value. (hystersis? is initially assumed to be false.)
As an example, if trigger? is defined as #(> (:metric %) threshold-hi)
and hold? is defined as (> (:metic %) threshold-lo), then the diagram
below demonstrated the behavior of hysteresis?
| /\\
| / \\ /\\
+------------------/----\\--- /--\\------------ threshold-hi
| /\\ / \\ / \\
| / \\ / \\/ \\
+-------/----\\--/------------------\\--------- threshold-lo
| / \\/ \\
| ___/ \\_____ metric
|
+--------------------------------------------
FFFFFFFFFFFFFFFFFFFTTTTTTTTTTTTTTTTFF hysteresis?
This is useful for providing simple filtering of the metric, so that,
for example, actions are triggered only once as a metric climbs or falls.
Because hysteresis? relies on previous state, it is normally used within
a (by [:host :service] ...) clause to ensure that each host and service
gets its own copy of the predicate."
[trigger? hold?]
(let [trigger? (if (number? trigger?) #(> (:metric %) trigger?) trigger?)
hold? (if (number? hold? ) #(> (:metric %) hold? ) hold?)
hyst? (fn [acc-hyst event]
(or (trigger? event) (and (hold? event) acc-hyst)))
acc-hyst (atom false)]
(fn pred-stream [event]
(when (alive? event) (swap! acc-hyst hyst? event))
@acc-hyst)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment