CHANGELOG | API | current Break Version:
[com.taoensso/timbre "5.0.0-RC1"] ; Dev, please see CHANGELOG for details
[com.taoensso/timbre "4.10.0"] ; Stable
See here if you're interested in helping support my open-source work, thanks! - Peter Taoussanis
Java logging can be a Kafkaesque mess of complexity that buys you little. Getting even the simplest logging working can be comically hard, and it often gets worse at scale as your needs become more sophisticated.
Timbre offers an all Clojure/Script alternative that's fast, deeply flexible, easy to configure with pure Clojure data, and that just works out the box. No XML.
Supports optional interop with tools.logging and log4j/logback/slf4j.
Happy hacking!
Link | Description |
---|---|
@fzakaria/slf4j-timbre | Route log4j/logback/sfl4j log output to Timbre |
@palletops/log-config | Library to help manage Timbre logging config |
Your link here? | PR's welcome! |
Add the necessary dependency to your project:
[com.taoensso/timbre "4.10.0"]
And setup your namespace imports:
(ns my-clj-ns ; Clojure namespace
(:require
[taoensso.timbre :as timbre
:refer [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]))
(ns my-cljs-ns ; ; ClojureScript namespace
(:require
[taoensso.timbre :as timbre
:refer-macros [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]))
You can also call
(timbre/refer-timbre)
to configure Clj ns referrals automatically.
By default, Timbre gives you basic println
and js/console
(v4+) output at a :debug
log level:
(info "This will print") => nil
%> 15-Jun-13 19:18:33 localhost INFO [my-app.core] - This will print
(spy :info (* 5 4 3 2 1)) => 120
%> 15-Jun-13 19:19:13 localhost INFO [my-app.core] - (* 5 4 3 2 1) => 120
(defn my-mult [x y] (info "Lexical env:" (get-env)) (* x y)) => #'my-mult
(my-mult 4 7) => 28
%> 15-Jun-13 19:21:53 localhost INFO [my-app.core] - Lexical env: {x 4, y 7}
(trace "This won't print due to insufficient log level") => nil
First-argument exceptions generate a nicely cleaned-up stack trace using io.aviso.exception (Clj only):
(info (Exception. "Oh noes") "arg1" "arg2")
%> 15-Jun-13 19:22:55 localhost INFO [my-app.core] - arg1 arg2
java.lang.Exception: Oh noes
<Stacktrace>
Other utils include: log-errors
, log-and-rethrow-errors
, logged-future
, and handle-uncaught-jvm-exceptions!
(please see the API for details).
ANSI colors are enabled by default for stacktraces. To turn these off (e.g. for log files or emails), you can add the following entry to your top-level config or individual appender map/s:
:output-fn (partial timbre/default-output-fn {:stacktrace-fonts {}})
And/or you can set the TIMBRE_DEFAULT_STACKTRACE_FONTS
environment variable (supports edn).
Timbre's inherently a simple design, no magic. It's just Clojure data and functions:
{:level _ :?ns-str _ ...}
(fn [data]) -> ?data
(fn [data]) -> ?effects
This is the biggest win over Java logging IMO. Timbre's behaviour is entirelly controlled through a single Clojure map fully documented in about 100 lines of docstring:
Sophisticated behaviour is easily achieved through regular fn composition and the power of arbitrary Clojure fns: e.g. write to your database, send a message over the network, check some other state (e.g. environment config) before making a choice, etc.
Timbre logging calls will be disabled (noop) when:
:info
) is < the active :min-level
(e.g. :warn
).:ns-filter
(e.g. {:allow #{"*"} :deny #{"taoensso.*"}}
.:min-level
can also be a vector mapping namespaces to minimum levels, e.g.: [[#{\"taoensso.*\"} :error] ... [#{\"*\"} :debug]]
.:min-level
.With all of the above, it's possible to easily enable/disable logging based on any combination of:
By setting the relevant JVM properties or environment variables, Timbre can actually entirely exclude the code for disabled logging calls at compile-time, e.g.:
#!/bin/bash
# Elide all lower-level logging calls:
export TAOENSSO_TIMBRE_MIN_LEVEL_EDN=':warn'
# Elide all other ns logging calls:
export TAOENSSO_TIMBRE_NS_PATTERN_EDN='{:allow #{"my-app.*"} :deny #{"my-app.foo" "my-app.bar.*"}}'
lein cljsbuild once # Compile js with appropriate logging calls excluded
lein uberjar # Compile jar ''
;; (:require [taoensso.timbre.appenders.core :as appenders]) ; Add to ns
(timbre/merge-config!
{:appenders {:spit (appenders/spit-appender {:fname "/path/my-file.log"})}})
;; (timbre/merge-config! {:appenders {:spit {:enabled? false}}} ; To disable
;; (timbre/merge-config! {:appenders {:spit nil}} ; To remove entirely
;; [com.taoensso/carmine <latest-version>] ; Add to project.clj deps
;; (:require [taoensso.timbre.appenders (carmine :as car-appender)]) ; Add to ns
(timbre/merge-config! {:appenders {:carmine (car-appender/carmine-appender)}})
This gives us a high-performance Redis appender:
Clojure has a rich selection of built-in and 3rd party tools for querying values like this.
See also car-appender/query-entries
.
;; [com.draines/postal <latest-version>] ; Add to project.clj deps
;; (:require [taoensso.timbre.appenders (postal :as postal-appender)]) ; Add to ns
(timbre/merge-config!
{:appenders
{:postal
(postal-appender/postal-appender
^{:host "mail.isp.net" :user "jsmith" :pass "sekrat!!1"}
{:from "me@draines.com" :to "foo@example.com"})}})
A number of 3rd-party appenders are included out-the-box here. Please see the relevant docstring for details. Thanks goes to the respective authors!
Just give me a shout if you've got an appender you'd like to have added.
ClojureWerkz is a growing collection of open-source, batteries-included Clojure libraries that emphasise modern targets, great documentation, and thorough testing.
Please use the project's GitHub issues page for all questions, ideas, etc. Pull requests welcome. See the project's GitHub contributors page for a list of contributors.
Otherwise, you can reach me at Taoensso.com. Happy hacking!
Distributed under the EPL v1.0 (same as Clojure).
Copyright © 2015-2020 Peter Taoussanis.
Can you improve this documentation? These fine people already did:
Peter Taoussanis, Emlyn Corrin, Noel, ken restivo, MerelyAPseudonym, Aaron France, Farid Zakaria, Matthew Batema, Rick Moynihan, Matt Lee, whodidthis, Matthias Nehlsen & Daniel ComptonEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close