Custom Emails With Riemann

I’ve recently started alerting on expired events from Riemann via email. The default email alert looks something like this:

Riemann email alerts

It contains some useful information but it is pretty basic: the subject is the name of the alerted service and the body contains a basic printout of the event’s fields.

I decided I’d like to build some alternative emails and so I went digging into the mailer plug-in code to find out how.

You would normally configure the mailer plug-in something like this:

(def email (mailer {:from "reimann@example.com"}))

This defines a new function called email that passes events to the mailer plug-in. We’ve configured a single option for the plug-in: :from which controls the source address for emails, here riemann@example.com.

If we want to update the subject or body of the email we can pass in the :subject and :body options. These options take a collection of events and return a formatted string, for example the default subject is set by a function like:

(def email (mailer {:from "reimann@example.com"
                    :subject (fn [events]
                     (clojure.string/join ", "
                       (map :service events)))}))

The :subject option has a function with an argument of events, which is the collection of incoming events. The map function then extracts the value of the :service field in each event, if there is more than one event then joins the services in a comma separated list, and writes that as a string in the subject line of our email. Hence riemanna riemann server tcp 0.0.0.0:5555... as the subject in our example email above.

If instead I wanted to build a custom email subject, let’s say to notify me when specific host was down I could add the :subject option to my mailer function:

(def host_email (mailer {:from "reimann@example.com"
                        :subject (fn [events]
                        (apply str "Host " (get-in (first events) [:host]) " is down"))}))

Here we’ve passed the :subject options our events collection. We’ve then specified a string, “Host … is down”. We’ve replaced the ... in the string with the hostname of the event. We’ve taken the hostname by getting the contents of the :host field from the first event in our collection.

We can then trigger these alerts with something like:

(expired
  (by [:host]
    (host_email "james@example.com")))

Here we’re filtering on all expired events, splitting the streams by the :host field using the by function. This creates a new stream for event by host. We then call the host_email function to send the email.

The resulting email would look like:

Riemann new email alerts

We could do similar things to modify the body of the email using the :body option.

P.S. I am slowly teaching myself Clojure. I’ve thus far found the Try Clojure site, the Learn Clojure and Clojure from the ground up to be most useful for this.

comments powered by Disqus