camdez.com

Rule #1: There are no rules.

Project: Honeybadger for Clojure

| Comments

TLDR: I’ve just released a pair of libraries which I believe constitute the best way to use the Honeybadger exception reporting service from Clojure—camdez/honeybadger and camdez/ring-honeybadger.

I’ve been using weavejester’s ring-honeybadger in my projects, and while it has served me well, I end up rewriting the Ring integration every time because it’s not particularly open for extension. I also feel that Honeybadger has a lot of utility beyond just reporting exceptions from web servers, and towards that end I wanted to write one library that encapsulates all of the features of Honeybadger, atop which something like a Ring reporter could be written. I’ve tried to consider what the appropriate extension points are, and how to make common things easy.

Anyway, it’s a simple library, so I won’t prattle on. Here’s a list of features from the README:

  • À la carte Honeybadger reporting.
  • Ability to report (informational) non-exceptions.
  • No implicit suppression by environment or exception type.
  • No deprecation warnings.
  • Honeybadger fault IDs are returned.
  • Set of reportable objects open to extension (by protocol).
  • Supports all known (to me) Honeybadger attributes.
  • Asynchronous reporting (doesn’t block the calling thread while the exception is being reported).
  • Custom filtering of reported errors.
  • Custom transformation of reported errors.
  • Helpers for common filter / transformation operations (e.g. filtering by environment / exception class, redacting of sensitive parameters).

For standalone usage, add [camdez/honeybadger "0.2.0"] to your project dependencies and use something like this:

1
2
3
4
5
6
7
8
9
10
11
(require '[honeybadger.core :as hb]
         '[honeybadger.filter :as hbf])

(def hb-config
  {:api-key "d34db33f"
   :env     "development"
   :filters [(hbf/only   (hbf/env? :production))
             (hbf/except (hbf/instance? ArithmeticException))]})

(hb/notify hb-config "Something happened")
(hb/notify hb-config (Exception. "Things ain't good"))

Note that you can report both strings and Throwable objects (like Exceptions). But the interesting part is the filters, which let us control not only when to report, but exactly what to report (as we’ll see in the next example).

If you’re using Ring, pull [camdez/ring-honeybadger "0.2.0"] into your project. The interface is identical to weavejester’s ring-honeybadger, allowing you to trivially migrate by changing your project file, but the config map supports some new tricks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(require '[honeybadger.filter :as hbf]
         '[ring.middleware.honeybadger :refer [wrap-honeybadger]])

(def hb-config
  {:api-key "d34db33f"
   :env     "development"
   :filters [(hbf/only (hbf/env? :production))
             (hbf/obscure-params [[:config :password] ; replace these params with
                                  [:secret-id]])]     ;   "[FILTERED]" (if present)
   :callback (fn [_ex id]
               (println (when id
                          (str "Reported error to Honeybadger with ID " id)
                          "Error reporting suppressed by filter")))})

(def app
  (wrap-honeybadger handler hb-config))

It’s also very easy to define your own custom filters.

I’d love to hear any thoughts or feedback on the libraries (these are my first public Clojure libraries!). And while they are new projects, we are running them in production at OrgSync, so I do believe that they are ready for primetime. Of course you should draw your own conclusions for something as important as exception reporting.

Lastly, I’d like to thank weavejester for his ring-honeybadger library; it did the trick for me for a quite a while, and served as a great inspiration for what I ended up building.

Comments