Deforester: librería de logging para Clojure que apuesta por eventos estructurados
Deforester permite configurar un logger desde la primera línea, con procesadores y formatos flexibles, y exportar logs en NDJSON o texto plano, ideal para infraestructuras y pruebas.
Deforester es una librería de logging para Clojure que se instala con una llamada a set-logger! antes de cualquier evento. El paquete ofrece un logger posicional, con niveles (:debug, :info, :warn, :error) y permite enviar los logs a stdout, a un fichero o a cualquier cierre de escritura. Por defecto escribe en formato JSON, pero con text-format se puede usar formato plano.
Configuración básica
(set-logger! {:write (file-writer "log.txt")
:format text-format})
Con esto, cada llamada a log produce una línea con time, level y msg. Se puede personalizar el nombre de los campos mediante el procesador key-renamer:
(set-logger! {:processors [(key-renamer {:time "@timestamp" :msg "message"})]})
Ahora log :warn "cat" emite {"@timestamp":"2026-07-11T08:14:16.968Z","level":"warn","message":"cat"}.
Procesadores y contextos
Deforester incluye varios procesadores útiles:
- with-duration-ctx agrega una clave
duration-msa cada evento, envolviendo el código entre llamadas. - with-log-ctx permite anotar un contexto (por ejemplo
:job-ido:ticker) que se propaga a través de hilos. - sampler devuelve solo cada n‑ésimo evento de un par
:level :msg. - reporter envía eventos que cumplan una condición (p.ej. nivel
:error) a un destino externo, como Sentry.
Un ejemplo completo de uso con contextos y procesadores:
(with-log-ctx {:job-id 5}
(def done (ev/chan))
(def tickers ["WAL" "EQX" "SODI"])
(each ticker tickers
(ev/spawn
(with-log-ctx {:ticker ticker}
(def [ok r] (protect (fetch-quote ticker)))
(if ok
(log :info "quote" :price r)
(log :error r))
(ev/give done ok))))
(def oks (seq [ _ :range [ 0 (length tickers)]] (ev/take done))))
(log :info "job" :total (length tickers) :failed (count not oks)))
Pruebas y captura de logs
Para pruebas se puede redirigir la salida a un buffer con with-config:
(with-config {:write | (array/push captured $)}
(log :info "caught"))
Esto permite comparar logs sin depender de archivos.
Por qué importa
Deforester ofrece una alternativa ligera a las bibliotecas de logging tradicionales, con un enfoque en eventos estructurados y extensibilidad vía procesadores. Su API es sencilla, pero permite integrar con sistemas de agregación (ELK, Sentry) y adaptar el formato de salida a las necesidades de producción o pruebas locales.
El soporte para NDJSON y la posibilidad de añadir procesadores personalizados lo hacen apto para pipelines de datos y microservicios donde la trazabilidad y el rendimiento son críticos.

