Sure thing. Here's a minimal config that demonstrates this method:
;; Global setup stuff.
(logging/init {:console true})
(tcp-server {})
(instrumentation {:enabled? false})
(periodically-expire 5)
;; Actual config.
(let [index (index)]
(streams
;; Put events in the index so that they can expire later.
index
;; Log all events at info level.
(fn [event] (info event))
;; Warn on events that _change_ to the expired state.
(changed :state
(match :state "expired"
(fn [event] (warn event))))))
This config will emit an INFO log for every event received, and it will emit a WARN log when the trigger condition is met. To show the config working, here is a Ruby snippet that sends in some events:
require 'riemann/client'
c = Riemann::Client.new host: 'localhost', port: 5555, timeout: 5
20.downto(0).each do |age|
c.tcp << {
host: 'localhost',
service: 'doa',
state: 'ok',
time: Time.now.to_i - age,
ttl: 10,
}
end
This will send events with ttl=10, but the first one is 20 seconds old already, so it is "dead on arrival". If we simply triggered on expired events, then this event would trigger, but we don't want that. Instead, this event's expired state sets the initial condition of the "changed" stream. The stream will now only pass events that have a change state, that is, they are _not_ expired.
The next few events are also DOA, so nothing happens. The last few events are fresh enough to be "ok", so now, "changed" sees this and passes on the first "ok" event, then waits for more change. Eventually, the events stop coming in and we are starting to think about "real" expiry from the index. When the TTL of last indexed event expires, it emits a new event with state=expired. The changed stream sees this and passes the expired event downstream to the match/warn combination, which represent the trigger.