Useful Clojure Asides - Logging and Exceptions
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#))))))