Liking cljdoc? Tell your friends :D

Taoensso open source
API | Slack channel | Latest release: v1.2.0 (2026-07-26)

Clj tests Cljs tests Graal tests bb tests

Trove

Modern logging facade for Clojure/Script

Trove is a minimal, modern alternative to tools.logging that supports:

  • Both traditional and structured logging.
  • Both Clojure and ClojureScript.
  • Richer filtering capabilities (by namespace, id, level, data, etc.).
  • Dynamic context for correlating related logs, etc.

It's intended mostly for library authors that want to emit rich logging without forcing their users to adopt any particular backend (Telemere, Timbre, μ/log, tools.logging, SLF4J, etc.).

Trove is tiny (0 deps, ~250 loc), fast, and highly flexible.

Why structured logging?

  • Traditional logging outputs strings (messages).
  • Structured logging in contrast outputs data. It retains rich data types and (nested) structures throughout the logging pipeline from logging callsite → filters → middleware → handlers.

A data-oriented pipeline allows easier filtering, transformation, and analysis. It's also often faster since it helps avoid unnecessary serialization, and is well suited to the tools and idioms offered by Clojure and ClojureScript.

Usage for end users

Trove just works out the box: if a library you use depends on Trove, you'll automatically get sensible library logging to *out* or the JS console. No need for any config, or even a logging library.

But you may prefer to configure Trove to instead direct logs to your preferred backend by calling trove/set-log-fn!:

(ns my-ns
  (:require
   [taoensso.trove.x] ; x ∈ #{console telemere timbre mulog tools-logging slf4j} (default console)
   [taoensso.trove :as trove]))

(trove/set-log-fn! (taoensso.trove.x/get-log-fn {:bridge-ctx? true/false}))
(trove/set-log-fn! nil) ; To noop all `trove/log!` calls

Use {:bridge-ctx? true} if you'd like to allow library authors to update your backend's native context when relevant. Requires Telemere, Timbre (except on Babashka), μ/log, or SLF4J with an MDC-capable provider.

You can also easily write your own log-fn - see trove/*log-fn* for details.

Usage for library authors

Logging

Include Trove in your library deps, then use trove/log! to make your logging calls:

(ns my-ns (:require [taoensso.trove :as trove]))

(trove/log! {:level :info, :id :auth/login, :data {:user-id 1234}, :msg "User logged in!"})

Trove uses the same map-based logging API as Telemere. The above expands to roughly:

(when-let [log-fn trove/*log-fn*] ; Chosen backend fn
  (log-fn "my-ns" [line column] :info :auth/login ; Callsite info
    {:msg "User logged in!", :data {:user-id 1234}})) ; Payload

The end user's chosen backend takes care of filtering and output.

What about expensive data?

Structured logging sometimes involves expensive data collection or transformation, e.g.:

(trove/log! {:id ::my-event, :data (expensive) ...})

That's why Trove automatically delays payload values that need runtime evaluation, allowing the backend to apply filtering before paying realization costs. See *log-fn* for payload details.

Dynamic context

The trove/*ctx* context map may be attached to trove/log! output:

(trove/with-ctx+ {:workflow/step "fetch-page"}
  (trove/log! {:id :ingest/fetched, :data {:n 42}}))

Utils:

log! also takes :ctx and :ctx+ options to replace or update the context for a single call.

Bridging context to the backend (advanced)

The above context belongs to Trove, so affects only trove/log! calls.

Some backends have their own equivalent context, which you can also update for end-users that choose to opt-in:

(trove/with-ctx+ {:workflow/step "fetch-page"}
  (trove/with-ctx-bridge ; Merge Trove context into native backend context
    (fetch-page)))

Custom backends can add bridge support with trove/add-ctx-bridge.

Funding

You can help support continued work on this project and others, thank you!! 🙏

License

Copyright © 2026 Peter Taoussanis.
Licensed under EPL 1.0 (same as Clojure).

Can you improve this documentation? These fine people already did:
Peter Taoussanis & Michiel Borkent
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close