Clojurescript/Node-friendly Rollbar client
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore Yeah Mar 3, 2016


A client for Rollbar currently geared towards Clojurescript running on Node. It'd be trivial to extend it to browser environments, or the JVM, though the initial target was Clojurescript AWS Lambda functions. Features intrinsic support for Timbre.

Clojars Project


The model ought to be fairly familiar - there's a function rollbar!, which takes a map & transforms it before issuing it as a POST request to the Rollbar API, returning a promesa promise.

There are environment-specific modules (currently only cljs-rollbar.node) which provide default maps containing information about the runtime environment.

  (:require [cljs-rollbar.core :as rollbar]

(def report!
  (-> rollbar/rollbar!
      (rollbar/defaulting cljs-rollbar.node/default-payload)
      (rollbar/defaulting {:token "SECRET"})))

The simplest possible request:

(report! {:info "Hello"})

In a Node REPL on my laptop with the report! definition above, I get the following sent to Rollbar:

{:access_token "SECRET"
  {:code_version "0.1.0"
   :host         "brinstar.local"
   :argv         ["/usr/local/Cellar/node/6.3.1/bin/node"]
   :pid          69652}

  :level       :info
  :language    "clojurescript"
  :notifier    {:name "rollbar-cljs-node" :version "0.1.0"}
  :environment "unspecified"
  :timestamp   1470412615834
  :body        {:message {:body "Hello"}}
  :framework   "node-js"
  :platform    "darwin"}}

If I don't like any of those values, I can specify them when I define my reporter, or when I emit the message, e.g:

(def report!
  (-> rollbar/rollbar!
      (rollbar/defaulting {:env "prod"})))

;; `:env` is a supported abbreviation, as are `:host` & `:version`:

(report! {:info "Hello" :env "prod" :version "0.0.0"})

Similarly, it's easy to emit messages at different levels:

;; Report an error, attach a `person` to the error
(report! {:error (ex-info "Oops" {:x 1}) :person {:id "boss"}})
;; Log an error instance without using the `error` level
  (report! {:debug (js/Error. "Oops")})
;; => {:err 0, :result {:id nil, :uuid "dbd8081e330b4abf8c6f86586d26d863"}}


Aside from the keys expected by Rollbar, ad-hoc data can be put into the map passed to the reporting function.

Additionally, the map attached to an ExceptionInfo instance (i.e. as in the ex-info example above) will be merged into the toplevel Rollbar map and associated with the error item.


If you're using Timbre, it's straightforward to configure a cljs-rollbar appender.

  {:appenders {:rollbar (rollbar/timbre-appender report!)}})
;; (Where report! is the function we defined above - rollbar! + some defaults)

We can then proceed to log as normal:

(timbre/info "Hello" {:x 1})

Any map arguments which are passed to a Timbre logging call are merged into the map supplied to the appender's reporting function & will become attributes of the resulting Rollbar item. Additionally, line and file toplevel attributes are set to the information received from Timbre, when not reporting an error (errors have their own designated line/file attrs in the Rollbar API -- non errors do not, AFAICT)

(timbre/error (js/Error. "Oops") {:version "0.2.0-final"})
(timbre/info {:env "dev"} "Stuff seems pretty good"     )


If you're using cljs-lambda, connecting its error handling mechanism to cljs-rollbar is straightforward:

  (:require [cljs-lambda.util :refer [async-lambda-fn]]

(def ^:export blow-up
    (fn [event ctx]
      (throw (ex-info "Sorry" {::x 2})))
    {:error-handler (cljs-rollbar.lambda/reporting-errors report!)}))

This'll cause errors thrown inside blow-up (or asynchronously realized errors) to be sent via our Rollbar reporting function report!. The Lambda function won't return to the caller until the error is acknowledged by Rollbar. In the event of a successful Rollbar API response, the underlying error will be passed through to the caller as if the error handler wasn't in between.