mirror of
https://github.com/status-im/timbre.git
synced 2025-01-29 05:07:07 +00:00
Added time-format and locale shared-config options.
* Also updated README. Signed-off-by: Peter Taoussanis <p.taoussanis@gmail.com>
This commit is contained in:
parent
5fbbe9bfb5
commit
dde1b89b03
14
README.md
14
README.md
@ -8,7 +8,7 @@ Timbre is an attempt to make **simple logging simple** and more **complex loggin
|
|||||||
|
|
||||||
## What's In The Box?
|
## What's In The Box?
|
||||||
* Small, uncomplicated **all-Clojure** library.
|
* Small, uncomplicated **all-Clojure** library.
|
||||||
* **Map-based config**: no arcane XML or properties files.
|
* **Super-simple map-based config**: no arcane XML or properties files.
|
||||||
* Decent performance (**low overhead**).
|
* Decent performance (**low overhead**).
|
||||||
* Flexible **fn-centric appender model**.
|
* Flexible **fn-centric appender model**.
|
||||||
* Sensible built-in appenders including simple **email appender**.
|
* Sensible built-in appenders including simple **email appender**.
|
||||||
@ -71,6 +71,15 @@ Easily adjust the current logging level:
|
|||||||
(timbre/set-level! :warn)
|
(timbre/set-level! :warn)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And the default instant formatting for log messages:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
(timbre/set-config! [:shared-appender-config :instant-pattern]
|
||||||
|
"yyyy-MMM-dd HH:mm:ss ZZ")
|
||||||
|
(timbre/set-config! [:shared-appender-config :locale]
|
||||||
|
(java.util.Locale/GERMAN))
|
||||||
|
```
|
||||||
|
|
||||||
Enable the standard [Postal](https://github.com/drewr/postal)-based email appender:
|
Enable the standard [Postal](https://github.com/drewr/postal)-based email appender:
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
@ -105,7 +114,8 @@ Writing a custom appender is easy:
|
|||||||
:enabled? true
|
:enabled? true
|
||||||
:async? false
|
:async? false
|
||||||
:max-message-per-msecs nil ; No rate limiting
|
:max-message-per-msecs nil ; No rate limiting
|
||||||
:fn (fn [{:keys [ap-config level error? instant ns message more] :as args}]
|
:fn (fn [{:keys [ap-config level error? instant instant-formatter
|
||||||
|
ns message more] :as args}]
|
||||||
(when-not (:production-mode? ap-config)
|
(when-not (:production-mode? ap-config)
|
||||||
(apply println instant "Hello world!" message more)))
|
(apply println instant "Hello world!" message more)))
|
||||||
```
|
```
|
||||||
|
@ -3,23 +3,18 @@
|
|||||||
{:author "Peter Taoussanis"}
|
{:author "Peter Taoussanis"}
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[clj-stacktrace.repl :as stacktrace]
|
[clj-stacktrace.repl :as stacktrace]
|
||||||
[postal.core :as postal]))
|
[postal.core :as postal])
|
||||||
|
(:import [java.util Date Locale]
|
||||||
;;;; Appender-fn helpers
|
[java.text SimpleDateFormat]))
|
||||||
|
|
||||||
(defn instant-str
|
|
||||||
"2012-May-26 15:26:06:081 +0700"
|
|
||||||
[instant]
|
|
||||||
(format "%1$tY-%1$tb-%1$td %1$tH:%1$tM:%1$tS:%1$tL %1tz" instant))
|
|
||||||
|
|
||||||
(defn prefixed-message
|
|
||||||
"2012-May-26 15:26:06:081 +0700 LEVEL [ns] - message"
|
|
||||||
[level instant ns message]
|
|
||||||
(str (instant-str instant) " " (-> level name str/upper-case)
|
|
||||||
" [" ns "] - " message))
|
|
||||||
|
|
||||||
;;;; Default configuration and appenders
|
;;;; Default configuration and appenders
|
||||||
|
|
||||||
|
(defn prefixed-message
|
||||||
|
"<formatted-instant> LEVEL [ns] - message"
|
||||||
|
[{:keys [level instant instant-formatter ns message]}]
|
||||||
|
(str (instant-formatter instant) " " (-> level name str/upper-case)
|
||||||
|
" [" ns "] - " message))
|
||||||
|
|
||||||
(def config
|
(def config
|
||||||
"This map atom controls everything about the way Timbre operates. In
|
"This map atom controls everything about the way Timbre operates. In
|
||||||
particular note the flexibility to add arbitrary appenders.
|
particular note the flexibility to add arbitrary appenders.
|
||||||
@ -28,7 +23,8 @@
|
|||||||
:doc, :min-level, :enabled?, :async?, :max-message-per-msecs, :fn?
|
:doc, :min-level, :enabled?, :async?, :max-message-per-msecs, :fn?
|
||||||
|
|
||||||
An appender's fn takes a single map argument with keys:
|
An appender's fn takes a single map argument with keys:
|
||||||
:ap-config, :level, :error?, :instant, :ns, :message, :more
|
:ap-config, :level, :error?, :instant, :instant-formatter, :ns,
|
||||||
|
:message, :more
|
||||||
|
|
||||||
See source code for examples."
|
See source code for examples."
|
||||||
(atom {:current-level :debug
|
(atom {:current-level :debug
|
||||||
@ -38,36 +34,37 @@
|
|||||||
{:doc "Prints everything to *out*."
|
{:doc "Prints everything to *out*."
|
||||||
:min-level :debug :enabled? false :async? false
|
:min-level :debug :enabled? false :async? false
|
||||||
:max-message-per-msecs nil
|
:max-message-per-msecs nil
|
||||||
:fn (fn [{:keys [level instant ns message more]}]
|
:fn (fn [{:keys [level instant ns message more] :as args}]
|
||||||
(apply println (prefixed-message level instant ns message)
|
(apply println (prefixed-message args) more))}
|
||||||
more))}
|
|
||||||
|
|
||||||
:standard-out-or-err
|
:standard-out-or-err
|
||||||
{:doc "Prints to *out* or *err* as appropriate. Enabled by default."
|
{:doc "Prints to *out* or *err* as appropriate. Enabled by default."
|
||||||
:min-level :debug :enabled? true :async? false
|
:min-level :debug :enabled? true :async? false
|
||||||
:max-message-per-msecs nil
|
:max-message-per-msecs nil
|
||||||
:fn (fn [{:keys [level error? instant ns message more]}]
|
:fn (fn [{:keys [level error? instant ns message more] :as args}]
|
||||||
(binding [*out* (if error? *err* *out*)]
|
(binding [*out* (if error? *err* *out*)]
|
||||||
(apply println (prefixed-message level instant ns message)
|
(apply println (prefixed-message args) more)))}
|
||||||
more)))}
|
|
||||||
|
|
||||||
:postal
|
:postal
|
||||||
{:doc (str "Sends an email using com.draines/postal.\n"
|
{:doc (str "Sends an email using com.draines/postal.\n"
|
||||||
"Needs :postal config map in :shared-appender-config.")
|
"Needs :postal config map in :shared-appender-config.")
|
||||||
:min-level :error :enabled? false :async? true
|
:min-level :error :enabled? false :async? true
|
||||||
:max-message-per-msecs (* 60 60 2)
|
:max-message-per-msecs (* 60 60 2)
|
||||||
:fn (fn [{:keys [ap-config level instant ns message more]}]
|
:fn (fn [{:keys [ap-config level instant ns message more] :as args}]
|
||||||
(when-let [postal-config (:postal ap-config)]
|
(when-let [postal-config (:postal ap-config)]
|
||||||
(postal/send-message
|
(postal/send-message
|
||||||
(assoc postal-config
|
(assoc postal-config
|
||||||
:subject (prefixed-message level instant ns message)
|
:subject (prefixed-message args)
|
||||||
:body (if (seq more) (str/join " " more)
|
:body (if (seq more) (str/join " " more)
|
||||||
"<no additional arguments>")))))}}
|
"<no additional arguments>")))))}}
|
||||||
|
|
||||||
;; Example :postal map:
|
:shared-appender-config
|
||||||
|
{:instant-pattern "yyyy-MMM-dd HH:mm:ss ZZ" ; SimpleDateFormat pattern
|
||||||
|
:locale nil ; A Locale object, or nil
|
||||||
|
;; A Postal message map, or nil.
|
||||||
;; ^{:host "mail.isp.net" :user "jsmith" :pass "sekrat!!1"}
|
;; ^{:host "mail.isp.net" :user "jsmith" :pass "sekrat!!1"}
|
||||||
;; {:from "me@draines.com" :to "foo@example.com"}
|
;; {:from "me@draines.com" :to "foo@example.com"}
|
||||||
:shared-appender-config {:postal nil}}))
|
:postal nil}}))
|
||||||
|
|
||||||
(defn set-config! [ks val] (swap! config assoc-in ks val))
|
(defn set-config! [ks val] (swap! config assoc-in ks val))
|
||||||
(defn set-level! [level] (set-config! [:current-level] level))
|
(defn set-level! [level] (set-config! [:current-level] level))
|
||||||
@ -83,16 +80,32 @@
|
|||||||
(defn sufficient-level?
|
(defn sufficient-level?
|
||||||
[level] (>= (compare-levels level (:current-level @config)) 0))
|
[level] (>= (compare-levels level (:current-level @config)) 0))
|
||||||
|
|
||||||
;;;; Appender-fn decoration: flood control, async, etc.
|
;;;; Appender-fn decoration
|
||||||
|
|
||||||
|
(defn- make-instant-formatter
|
||||||
|
"Returns unary fn to format an instant using given pattern string and optional
|
||||||
|
locale."
|
||||||
|
[^String pattern ^Locale locale]
|
||||||
|
(let [format (if locale
|
||||||
|
(SimpleDateFormat. pattern locale)
|
||||||
|
(SimpleDateFormat. pattern))]
|
||||||
|
(fn [^Date instant] (.format ^SimpleDateFormat format instant))))
|
||||||
|
|
||||||
|
(comment ((make-instant-formatter "yyyy-MMM-dd" nil) (Date.)))
|
||||||
|
|
||||||
(defn- wrap-appender-fn
|
(defn- wrap-appender-fn
|
||||||
"Wraps compile-time appender fn with additional capabilities controlled by
|
"Wraps compile-time appender fn with additional capabilities controlled by
|
||||||
compile-time config."
|
compile-time config."
|
||||||
[appender-id {apfn :fn :keys [async? max-message-per-msecs] :as appender}]
|
[appender-id {apfn :fn :keys [async? max-message-per-msecs] :as appender}]
|
||||||
(->
|
(->
|
||||||
;; Wrap to add shared appender config to args
|
;; Wrap to add compile-time stuff to runtime appender arguments
|
||||||
(fn [apfn-args]
|
(fn [apfn-args]
|
||||||
(apfn (assoc apfn-args :ap-config (@config :shared-appender-config))))
|
(let [{:keys [instant-pattern locale] :as ap-config}
|
||||||
|
(@config :shared-appender-config)]
|
||||||
|
(apfn (assoc apfn-args
|
||||||
|
:ap-config ap-config ; Shared appender config map
|
||||||
|
:instant-formatter
|
||||||
|
(make-instant-formatter instant-pattern locale)))))
|
||||||
|
|
||||||
;; Wrap for asynchronicity support
|
;; Wrap for asynchronicity support
|
||||||
((fn [apfn]
|
((fn [apfn]
|
||||||
@ -189,7 +202,7 @@
|
|||||||
appender-args#
|
appender-args#
|
||||||
{:level level#
|
{:level level#
|
||||||
:error? (>= (compare-levels level# :error) 0)
|
:error? (>= (compare-levels level# :error) 0)
|
||||||
:instant (java.util.Date.)
|
:instant (Date.)
|
||||||
:ns (str ~*ns*)
|
:ns (str ~*ns*)
|
||||||
:message (if has-throwable?# (or (first xs#) x1#) x1#)
|
:message (if has-throwable?# (or (first xs#) x1#) x1#)
|
||||||
:more (if has-throwable?#
|
:more (if has-throwable?#
|
||||||
|
Loading…
x
Reference in New Issue
Block a user