Useful Clojure Asides - Logging and Exceptions

It's always useful to have some nice logging when writing code. Simple logging and exception handling samples to make it a bit easier for the developer.

Logging and exception handling are such core requirements in any application which are rarely, if ever, discussed. At least in the initial phases of any application. But as any developer would vouch (when asked, not voluntarily, I think), logging right is a very crucial aspect of any application. Not only does it help you understand the (then-) current state of the application, they also help folks trace causes of various problems when done right.

Leaving aside the generally broad topic of logging, and exceptions-handling, let’s look at a very simple setup one can use, especially in a new, nascent application written in Clojure.

A couple of small functions, placed in some utils namespace

  (ns msync-blog.utils
    (:require [taoensso.timbre :as timbre :refer [log info debug error warn
                                                  trace fatal report]]
              [clojure.string :as string]))

  ;; https://groups.google.com/forum/#!topic/clojure/ORRhWgYd2Dk
  ;; Modified slightly since contribs has now changed forms (as of 1.7)
  (defn unmangle
    "Given the name of a class that implements a Clojure function,
        returns the function's name in Clojure.
        Note: If the true Clojure function name contains any underscores
        (a rare occurrence), the unmangled name will contain hyphens
        at those locations instead."
    [class-name]
    (.replace
     (string/replace class-name #"^(.+)\$(.+)__\d+$" "$1/$2")
     \_ \-))

  ;; https://gist.github.com/alexpw/2166820
  ;; And some minor modifications
  (defmacro try-catch [log-level & body]
    `(try
       ~@body
       (catch Exception e#
         (~log-level
          (timbre/color-str :red (str "Exception thrown trying to execute '"
                                      (-> e#
                                          .getStackTrace
                                          first
                                          .getClassName
                                          unmangle)
                                      "' - Message/exception: "
                                      e#))))))