Refactor valid logging-level checks, support non-const logging levels

The `assert-valid-logging-level` macro had the unfortunate side effect of
preventing the use of runtime-evaluated logging-levels.

To get around this without impacting performance, `assert-valid-logging-level`
has been removed and the validty checking moved to the (memoized) level
comparator.

This is cleaner, more flexible, and no slower.
This commit is contained in:
Peter Taoussanis 2012-10-26 16:15:08 +07:00
parent 074f44f407
commit fc51884472
2 changed files with 10 additions and 12 deletions

View File

@ -81,15 +81,16 @@
;;;; Define and sort logging levels ;;;; Define and sort logging levels
(def ^:private ordered-levels [:trace :debug :info :warn :error :fatal :report]) (def ^:private ordered-levels [:trace :debug :info :warn :error :fatal :report])
(def ^:private scored-levels (zipmap ordered-levels (range))) (def ^:private scored-levels (assoc (zipmap ordered-levels (range)) nil 0))
(defn assert-valid-level
[x] (when-not (some #{x} ordered-levels)
(throw (Exception. (str "Invalid logging level: " x)))))
(defn error-level? [x] (boolean (#{:error :fatal} x))) (defn error-level? [level] (boolean (#{:error :fatal} level)))
(defn- checked-level-score [level]
(or (scored-levels level)
(throw (Exception. (str "Invalid logging level: " level)))))
(def compare-levels (def compare-levels
(memoize (fn [x y] (- (scored-levels x) (scored-levels y))))) (memoize (fn [x y] (- (checked-level-score x) (checked-level-score y)))))
(defn sufficient-level? (defn sufficient-level?
[level] (>= (compare-levels level (:current-level @config)) 0)) [level] (>= (compare-levels level (:current-level @config)) 0))
@ -179,8 +180,7 @@
[level] [level]
(->> (:appenders @config) (->> (:appenders @config)
(filter #(let [{:keys [enabled? min-level]} (val %)] (filter #(let [{:keys [enabled? min-level]} (val %)]
(and enabled? (or (nil? min-level) (and enabled? (>= (compare-levels level min-level) 0))))
(>= (compare-levels level min-level) 0)))))
(into {}))) (into {})))
(comment (relevant-appenders :debug) (comment (relevant-appenders :debug)
@ -241,14 +241,12 @@
"Returns true when current logging level is sufficient and current namespace "Returns true when current logging level is sufficient and current namespace
is unfiltered." is unfiltered."
[level] [level]
(assert-valid-level level)
`(and (sufficient-level? ~level) (@ns-filter-cache ~*ns*))) `(and (sufficient-level? ~level) (@ns-filter-cache ~*ns*)))
(defmacro log* (defmacro log*
"Prepares given arguments for, and then dispatches to all relevant "Prepares given arguments for, and then dispatches to all relevant
appender-fns." appender-fns."
[level base-args & sigs] [level base-args & sigs]
(assert-valid-level level)
`(when-let [juxt-fn# (@appenders-juxt-cache ~level)] ; Any relevant appenders? `(when-let [juxt-fn# (@appenders-juxt-cache ~level)] ; Any relevant appenders?
(let [[x1# & xs#] (list ~@sigs) (let [[x1# & xs#] (list ~@sigs)
@ -274,7 +272,6 @@
appender-fns. Generic form of standard level-loggers (trace, info, etc.)." appender-fns. Generic form of standard level-loggers (trace, info, etc.)."
{:arglists '([level message & more] [level throwable message & more])} {:arglists '([level message & more] [level throwable message & more])}
[level & sigs] [level & sigs]
(assert-valid-level level)
`(when (logging-enabled? ~level) `(when (logging-enabled? ~level)
(log* ~level {} ~@sigs))) (log* ~level {} ~@sigs)))
@ -313,6 +310,8 @@
(log :debug (Exception.)) (log :debug (Exception.))
(log :trace "arg1") (log :trace "arg1")
(log (or nil :info) "Booya")
(set-config! [:ns-blacklist] []) (set-config! [:ns-blacklist] [])
(set-config! [:ns-blacklist] ["taoensso.timbre*"]) (set-config! [:ns-blacklist] ["taoensso.timbre*"])

View File

@ -110,7 +110,6 @@
for db appenders to check for this special key and to log profiling stats to for db appenders to check for this special key and to log profiling stats to
db in a queryable manner." db in a queryable manner."
[level name & body] [level name & body]
(timbre/assert-valid-level level)
`(if (timbre/logging-enabled? ~level) `(if (timbre/logging-enabled? ~level)
(profile* (profile*
(fn [name# stats#] (fn [name# stats#]