Contents

Custom emails with Riemann

Contents

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

/images/posts/2015/3/am210.png

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:

1
(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:

1
2
3
4
(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:

1
2
3
(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:

1
2
3
(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:

/images/posts/2015/3/am211.png

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.