taoensso.timbre

Simple, flexible logging for Clojure/Script. No XML.

*config*

dynamic

clj

cljs

This config map controls all Timbre behaviour including:
  - When to log (via min-level and namespace filtering)
  - How  to log (which appenders to use, etc.)
  - What to log (how log data will be transformed to final
                 output for use by appenders)

Initial config value will be (in descending order of preference):

  1. `taoensso.timbre.config.edn`   JVM property  (read as EDN)
  2. `TAOENSSO_TIMBRE_CONFIG_EDN`   Env var       (read as EDN)
  3. `./taoensso.timbre.config.edn` resource file (read as EDN)
  4. Value of `default-config`

For all EDN cases (1-3): the EDN can represent either a Clojure map
to merge into `default-config`, or a qualified symbol that'll
resolve to a Clojure map to merge into `default-config`.

See `default-config` for more info on the base/default config.

You can modify the config value with standard `alter-var-root`,
or `binding`.

For convenience, there's also some dedicated helper utils:

  - `set-config!`, `merge-config!`        ; Mutate *config*
  - `set-min-level!`, `set-ns-min-level!` ; Mutate *config* :min-level
  - `with-config`, `with-merged-config`   ; Bind *config*
  - `with-min-level`                      ; Bind *config* :min-level

MAIN CONFIG OPTIONS
  :min-level
    Logging will occur only if a logging call's level is >= this
    min-level. Possible values, in order:

      :trace  = level 0
      :debug  = level 1 ; Default min-level
      :info   = level 2
      :warn   = level 3
      :error  = level 4 ; Error type
      :fatal  = level 5 ; Error type
      :report = level 6 ; High general-purpose (non-error) type

    It's also possible to set a namespace-specific min-level by
    providing a vector that maps `ns-pattern`s to min-levels, e.g.:
    `[[#{"taoensso.*"} :error] ... [#{"*"} :debug]]`.

    Example `ns-pattern`s:
      #{}, "*", "foo.bar", "foo.bar.*", #{"foo" "bar.*"},
      {:allow #{"foo" "bar.*"} :deny #{"foo.*.bar.*"}}.

    See also `set-ns-min-level!` for a helper tool.

  :ns-filter
    Logging will occur only if a logging call's namespace is permitted
    by this ns-filter. Possible values:

      - Arbitrary (fn may-log-ns? [ns]) predicate fn.
      - An `ns-pattern` (see :min-level docs above).

    Useful for turning off logging in noisy libraries, etc.

  :middleware
    Vector of simple (fn [data]) -> ?new-data fns (applied left->right)
    that transform the data map dispatched to appender fns. If any middleware
    returns nil, NO dispatch will occur (i.e. the event will be filtered).

    Useful for layering advanced functionality. Similar to Ring middleware.

  :timestamp-opts ; Config map, see `default-timestamp-opts`
  :output-fn      ; (fn [data]) -> final output for use by appenders,
                  ; see `default-output-fn` for example
  :output-opts    ; Optional map added to data sent to output-fn

  :appenders ; {<appender-id> <appender-map>}

    Where each appender-map has keys:
      :enabled?        ; Must be truthy to log
      :min-level       ; Optional *additional* appender-specific min-level
      :ns-filter       ; Optional *additional* appender-specific ns-filter

      :async?          ; Dispatch using agent? Useful for slow appenders (Clj only)
                       ; Tip: consider calling (shutdown-agents) as part of your
                       ; application shutdown if you have this enabled for any
                       ; appenders.

      :rate-limit      ; [[<ncalls-limit> <window-msecs>] ...], or nil
                       ; Appender will noop a call after exceeding given number
                       ; of the "same" calls within given rolling window/s.
                       ;
                       ; Example:
                       ;   [[100  (encore/ms :mins  1)]
                       ;    [1000 (encore/ms :hours 1)]] will noop a call after:
                       ;
                       ;   - >100  "same" calls in 1 rolling minute, or
                       ;   - >1000 "same" calls in 1 rolling hour
                       ;
                       ; "Same" calls are identified by default as the
                       ; combined hash of:
                       ;   - Callsite (i.e. each individual Timbre macro form)
                       ;   - Logging level
                       ;   - All arguments provided for logging
                       ;
                       ; You can manually override call identification:
                       ;   (timbre/infof ^:meta {:id "my-limiter-call-id"} ...)
                       ;

      :timestamp-opts  ; Optional appender-specific override for top-level option
      :output-fn       ; Optional appender-specific override for top-level option
      :output-opts     ; Optional appender-specific override for top-level option

      :fn              ; (fn [data]) -> side-effects, with keys described below

LOG DATA
  A single map with keys:
    :config          ; Entire active config map
    :context         ; `*context*` value at log time (see `with-context`)
    :appender-id     ; Id of appender currently dispatching
    :appender        ; Entire map of appender currently dispatching
    :instant         ; Platform date (java.util.Date or js/Date)
    :level           ; Call's level keyword (e.g. :info) (>= active min-level)
    :error-level?    ; Is level e/o #{:error :fatal}?
    :spying?         ; Is call occuring via the `spy` macro?
    :?ns-str         ; String,  or nil
    :?file           ; String,  or nil
    :?line           ; Integer, or nil
    :?column         ; Integer, or nil
    :?err            ; First-arg platform error, or nil
    :?meta           ; First-arg map when it has ^:meta metadata, used as a
                       way of passing advanced per-call options to appenders
    :vargs           ; Vector of raw args provided to logging call
    :timestamp_      ; Forceable - string
    :hostname_       ; Forceable - string (Clj only)
    :output-fn       ; (fn [data]) -> final output for use by appenders
    :output_         ; Forceable result of calling (output-fn <this-data-map>)

    **NB** - any keys not specifically documented here should be
    considered private / subject to change without notice.

COMPILE-TIME LEVEL/NS ELISION
  To control :min-level and :ns-filter at compile-time, use:

    - `taoensso.timbre.min-level.edn`  JVM property (read as EDN)
    - `taoensso.timbre.ns-pattern.edn` JVM property (read as EDN)

    - `TAOENSSO_TIMBRE_MIN_LEVEL_EDN`  env var      (read as EDN)
    - `TAOENSSO_TIMBRE_NS_PATTERN_EDN` env var      (read as EDN)

  Note that compile-time options will OVERRIDE options in `*config*`.

DEBUGGING INITIAL CONFIG
  See `:_init-config` for information re: Timbre's config on initial load.

*context*

dynamic

clj

cljs

General-purpose dynamic logging context

ansi-color

clj

(ansi-color color)

color-str

clj

(color-str color)(color-str color x)(color-str color x y)(color-str color x y & more)

debug

macro

clj

cljs

(debug & args)

debugf

macro

clj

cljs

(debugf & args)

default-config

clj

cljs

Default/example Timbre `*config*` value:

{:min-level :debug #_[["taoensso.*" :error] ["*" :debug]]
 :ns-filter #{"*"} #_{:deny #{"taoensso.*"} :allow #{"*"}}

 :middleware [] ; (fns [data]) -> ?data, applied left->right

 :timestamp-opts default-timestamp-opts ; {:pattern _ :locale _ :timezone _}
 :output-fn default-output-fn ; (fn [data]) -> final output for use by appenders

 :appenders
 #?(:clj
    {:println (println-appender {:stream :auto})
     ;; :spit (spit-appender    {:fname "./timbre-spit.log"})
     }

    :cljs
    (if (exists? js/window)
      {:console (console-appender {})}
      {:println (println-appender {})}))}

See `*config*` for more info.

default-err

clj

default-out

clj

default-output-error-fn

clj

cljs

(default-output-error-fn {:keys [?err output-opts], :as data})
Default (fn [data]) -> string, used by `default-output-fn` to
generate output for `:?err` value in log data.

For Clj:
   Uses `org.clj-commons/pretty` to return an attractive stacktrace.
   Options:
     :stacktrace-fonts ; See `clj-commons.format.exceptions/*fonts*`

For Cljs:
   Returns simple stacktrace string.

default-output-fn

clj

cljs

(default-output-fn base-output-opts data)(default-output-fn data)
Default (fn [data]) -> final output string, used to produce
final formatted output_ string from final log data.

Options (included as `:output-opts` in data sent to fns below):

  :error-fn ; When present and (:?err data) present,
            ; (error-fn data) will be called to generate output
            ; (e.g. a stacktrace) for the error.
            ;
            ; Default value: `default-output-error-fn`.
            ; Use `nil` value to exclude error output.

  :msg-fn   ; When present, (msg-fn data) will be called to
            ; generate a message from `vargs` (vector of raw
            ; logging arguments).
            ;
            ; Default value: `default-output-msg-fn`.
            ; Use `nil` value to exclude message output.

default-output-msg-fn

clj

cljs

(default-output-msg-fn {:keys [msg-type ?msg-fmt vargs output-opts], :as data})
(fn [data]) -> string, used by `default-output-fn` to generate output
for `:vargs` value (vector of raw logging arguments) in log data.

default-timestamp-opts

clj

cljs

Controls (:timestamp_ data)

error

macro

clj

cljs

(error & args)

errorf

macro

clj

cljs

(errorf & args)

fatal

macro

clj

cljs

(fatal & args)

fatalf

macro

clj

cljs

(fatalf & args)

get-hostname

clj

(get-hostname)
Returns cached local hostname string.

handle-uncaught-jvm-exceptions!

clj

(handle-uncaught-jvm-exceptions! & [handler])
Sets JVM-global DefaultUncaughtExceptionHandler.

info

macro

clj

cljs

(info & args)

infof

macro

clj

cljs

(infof & args)

keep-callsite

macro

clj

cljs

added in Encore v3.61.0 (2023-07-07)

(keep-callsite form)
The long-standing CLJ-865 means that it's not possible for an inner
macro to access the `&form` metadata of a wrapping outer macro. This
means that wrapped macros lose calsite info, etc.

This util offers a workaround for macro authors:
  (defmacro inner [] (meta &form))
  (defmacro outer [] (keep-callsite `(inner)))
  (outer) => {:keys [line column ...]}

level>=

clj

cljs

(level>= x y)
Implementation detail.

log

macro

clj

cljs

(log level & args)

log!

macro

clj

cljs

(log! {:as opts, :keys [loc level msg-type args vargs config ?err ?base-data spying?], :or {config (quote taoensso.timbre/*config*), ?err :auto}})(log! level msg-type args & [opts])
Core low-level log macro. Useful for tooling/library authors, etc.

  * `level`    - must eval to a valid logging level
  * `msg-type` - must eval to e/o #{:p :f nil}
  * `args`     - arguments seq (ideally vec) for logging call
  * `opts`     - ks e/o #{:config ?err ?base-data spying?
                          :?ns-str :?file :?line :?column}

Supports compile-time elision when compile-time const vals
provided for `level` and/or `?ns-str`.

Logging wrapper examples:

  (defn     log-wrapper-fn    [& args]                        (timbre/log! :info :p  args))
  (defmacro log-wrapper-macro [& args] (timbre/keep-callsite `(timbre/log! :info :p ~args)))

log*

macro

clj

cljs

(log* config level & args)

log-and-rethrow-errors

macro

clj

cljs

(log-and-rethrow-errors & body)

log-errors

macro

clj

cljs

(log-errors & body)

logf

macro

clj

cljs

(logf level & args)

logf*

macro

clj

cljs

(logf* config level & args)

logged-future

macro

clj

cljs

(logged-future & body)

merge-config!

clj

cljs

(merge-config! config)

println-appender

clj

cljs

(println-appender & [{:keys [stream], :or {stream :auto}}])
Returns a simple `println` appender for Clojure/Script.
Use with ClojureScript requires that `cljs.core/*print-fn*` be set.

:stream (clj only) - e/o #{:auto :*out* :*err* :std-err :std-out <io-stream>}.

refer-timbre

macro

clj

cljs

(refer-timbre)
(require
'[taoensso.timbre :as timbre
  :refer [log  trace  debug  info  warn  error  fatal  report
          logf tracef debugf infof warnf errorf fatalf reportf
          spy]])

report

macro

clj

cljs

(report & args)

reportf

macro

clj

cljs

(reportf & args)

set-config!

clj

cljs

(set-config! config)

set-min-level

clj

cljs

(set-min-level config min-level)

set-min-level!

clj

cljs

(set-min-level! min-level)

set-ns-min-level

clj

cljs

(set-ns-min-level config ?min-level)(set-ns-min-level config ns ?min-level)
Returns given Timbre `config` with its `:min-level` modified so that
the given namespace has the specified minimum logging level.

When no namespace is provided, `*ns*` will be used.
When `?min-level` is nil, any minimum level specifications for the
*exact* given namespace will be removed.

See `*config*` docstring for more about `:min-level`.
See also `set-min-level!` for a util to directly modify `*config*`.

set-ns-min-level!

macro

clj

cljs

(set-ns-min-level! ?min-level)(set-ns-min-level! ns ?min-level)
Like `set-ns-min-level` but directly modifies `*config*`.

Can conveniently set the minimum log level for the current ns:
 (set-ns-min-level! :info) => Sets min-level for current *ns*

See `set-ns-min-level` for details.

shutdown-appenders!

clj

cljs

(shutdown-appenders!)(shutdown-appenders! config)
Alpha, subject to change.

Iterates through all appenders in config (enabled or not), and
calls (:shutdown-fn appender) whenever that fn exists.

This signals to these appenders that they should immediately
close/release any resources that they may have open/acquired,
and permanently noop on future logging requests.

Returns the set of appender-ids that had a shutdown-fn called.

This fn is called automatically on JVM shutdown, but can also
be called manually.

sometimes

macro

clj

cljs

(sometimes probability & body)
Handy for sampled logging, etc.

spit-appender

clj

(spit-appender & [{:keys [fname append? locking?], :or {fname "./timbre-spit.log", append? true, locking? true}}])
Returns a simple `spit` file appender for Clojure.

spy

macro

clj

cljs

(spy form)(spy level form)(spy level name form)(spy config level name form)
Evaluates named form and logs its result. Always returns the result.
Defaults to `:debug` logging level, and unevaluated form as name:
  (spy (+ 3 2)) => (timbre/debug '(+ 3 2) "=>" 5)

swap-config!

clj

cljs

(swap-config! f & args)

trace

macro

clj

cljs

(trace & args)

tracef

macro

clj

cljs

(tracef & args)

warn

macro

clj

cljs

(warn & args)

warnf

macro

clj

cljs

(warnf & args)

with-config

macro

clj

cljs

(with-config config & body)

with-context

macro

clj

cljs

(with-context context & body)
Executes body so that given arbitrary data will be passed (as `:context`)
to appenders for any enclosed logging calls.

(with-context
  {:user-name "Stu"} ; Will be incl. in data dispatched to appenders
  (info "User request"))

See also `with-context+`.

with-context+

macro

clj

cljs

(with-context+ context & body)
Like `with-context`, but merges given context into current context.

with-default-outs

macro

clj

cljs

(with-default-outs & body)

with-merged-config

macro

clj

cljs

(with-merged-config config & body)

with-min-level

macro

clj

cljs

(with-min-level min-level & body)