 
 (defmacro log-time
   "Executes the body, timing the result. The elapsed time in milliseconds (as a double) is passed to the formatter function, which returns
-a string. The resulting string is logged at INFO priority."
+  a string. The resulting string is logged at INFO priority."
   [formatter & body]
   `(time-function #(do ~@body) #(l/info (~formatter %))))


(defmacro trace
  "Traces the execution of its body. trace-message may be a string, or a function that returns a string; execution of
the function is deferred until needed. If an exception occurs inside the body, then all trace messages leading up to the
point of exception will be logged (the logger is determined from the current namespace); this logging only occurs at the
most deeply nested trace."
  [trace-message & body]
  `(trace-function (get-logger ~*ns*) ~trace-message #(do ~@body)))


  "Checks to see if an exception (or any of the exception's causes) is an IExceptionInfo containing an :exception-trace."
  [^Throwable e]
  (cond
    (nil? e) false
    (some-> e ex-data :exception-trace) true
    :else (recur (.getCause e))))

(defn- log-trace [logger trace-messages message e]
  (.error logger "An exception has occurred:")
