Final hk?

This commit is contained in:
Peter Taoussanis 2015-05-26 14:28:07 +07:00
parent 6ab9c4ac59
commit 7c969ca0e6
11 changed files with 202 additions and 181 deletions

View File

@ -1,5 +1,44 @@
> This project uses [Break Versioning](https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md) as of **Aug 16, 2014**. > This project uses [Break Versioning](https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md) as of **Aug 16, 2014**.
## v4.0.0-beta1 / 2015 May 26
> This is a **MAJOR** update. Your custom appenders **WILL BREAK**. Your configuration **MIGHT BREAK**. Your call sites should be fine. I've updated all included appenders, but **haven't tested** any 3rd-party appenders.
* **New**: full **ClojureScript** support, including a default js/console appender [#51]
* **New**: support for compile-time ns filtering + elision (both Clj+Cljs)
* **New**: support for MDC-like contexts [#42]
* **New**: default :println appender has picked up a :stream opt [#49]
* **New**: create necessary spit appender paths [#93]
* **New**: full-power fn-level `log*` util [#99]
* **New**: added a reference appender example [here](https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre/appenders/example_appender.clj)
* **Implementation**: modernized + simplified codebase
* **Implementation**: significant performance improvements across the board
* **Implementation**: use delays to avoid unnecessarily producing unused arg msgs [#71]
* **Fix**: auto shutdown agents to prevent slow app shutdown [#61]
```clojure
[com.taoensso/timbre "4.0.0-beta1"]
```
### Migration checklist
* Removed vars: `timbre/config`, `timbre/level-atom`, `default-fmt-output-fn`
* The fn signature for `set-config!` has changed: `[ks val]` -> `[config]`
* Middleware now apply left->right, not right->left
* Renamed default appender: `:standard-out` -> `:println`
* Renamed config opts: `:timestamp-pattern`, `:timestamp-locale` -> `:timestamp-opts {:pattern _ :locale _ :timezone _}`
* Appender :rate-limit format has changed: `[ncalls ms]` -> `[[ncalls ms] <...>]`
* Renamed appender args: `:ns`->`:?ns-str`, `:file`->`:?file`, `:line`->`:?line`
* Appender args now wrapped with delays: `:throwable`->`:?err_`, `:message`->`:msg_`, `:timestamp`->`:timestamp_`, `:hostname`->`:hostname_`, `:args`->`:vargs_`
* Appender args removed: `:output`, `:ap-config`
* Appender args added: `:output-fn (fn [data])`, `:appender-opts`
* `stacktrace` util fn signature changed: `[throwable & [sep fonts]` -> `[err & [opts]]`
* All bundles 3rd-party appenders have moved to a new `3rd-party` ns
Apologies for the hassle in migrating. The changes made here all bring serious benefits (performance, simplicity, future extensibility, cross-platform support) and I'm confident that v4's the last time I'll need to touch the core design. Future work will be focused on polish, stability, and better+more bundled appenders.
/ Peter Taoussanis
## v3.4.0 / 2015 Feb 16 ## v3.4.0 / 2015 Feb 16
> This should be a **non-breaking** release that only bumps some old dependencies. > This should be a **non-breaking** release that only bumps some old dependencies.

View File

@ -133,79 +133,24 @@ This is the biggest win over Java logging IMO. Here's `timbre/example-config` (a
The `example-config` source code contains further settings and details. The `example-config` source code contains further settings and details.
See also `set-config!`, `merge-config!`, `set-level!`." See also `set-config!`, `merge-config!`, `set-level!`."
(merge {:level :debug ; e/o #{:trace :debug :info :warn :error :fatal :report}
{:level :debug ; e/o #{:trace :debug :info :warn :error :fatal :report}
;; Control log filtering by namespaces/patterns. Useful for turning off ;; Control log filtering by namespaces/patterns. Useful for turning off
;; logging in noisy libraries, etc.: ;; logging in noisy libraries, etc.:
:whitelist [] #_["my-app.foo-ns"] :whitelist [] #_["my-app.foo-ns"]
:blacklist [] #_["taoensso.*"] :blacklist [] #_["taoensso.*"]
:middleware [] ; (fns [data]) -> ?data, applied left->right :middleware [] ; (fns [data]) -> ?data, applied left->right
#+clj :timestamp-opts :appenders
#+clj default-timestamp-opts ; {:pattern _ :locale _ :timezone _} {:simple-println ; Appender id
;; Appender definition (just a map):
:output-fn default-output-fn ; (fn [data]) -> string {:min-level nil :enabled? true :async? false
:rate-limit [[1 250] [10 5000]] ; 1/250ms, 10/5s
:appenders :fn ; Appender's fn
#+clj (fn [data]
{:println ; Appender id (let [{:keys [output-fn]} data]
;; Appender <map>: (println (output-fn data))))}}})
{:doc "Prints to (:stream <appender-opts>) IO stream. Enabled by default."
:min-level nil :enabled? true :async? false :rate-limit nil
;; Any custom appender opts:
:opts {:stream :auto ; e/o #{:std-err :std-out :auto <stream>}
}
:fn
(fn [data]
(let [{:keys [output-fn error? appender-opts]} data
{:keys [stream]} appender-opts
stream (case stream
(nil :auto) (if error? default-err *out*)
:std-err default-err
:std-out default-out
stream)]
(binding [*out* stream] (println (output-fn data)))))}
:spit
{:doc "Spits to (:spit-filename <appender-opts>) file."
:min-level nil :enabled? false :async? false :rate-limit nil
:opts {:spit-filename "timbre-spit.log"}
:fn
(fn [data]
(let [{:keys [output-fn appender-opts]} data
{:keys [spit-filename]} appender-opts]
(when-let [fname (enc/as-?nblank spit-filename)]
(try (ensure-spit-dir-exists! fname)
(spit fname (str (output-fn data) "\n") :append true)
(catch java.io.IOException _)))))}}
#+cljs
{:console
{:doc "Logs to js/console when it exists. Enabled by default."
:min-level nil :enabled? true :async? false :rate-limit nil
:opts {}
:fn
(let [have-logger? (and (exists? js/console) (.-log js/console))
have-warn-logger? (and have-logger? (.-warn js/console))
have-error-logger? (and have-logger? (.-error js/console))
adjust-level {:fatal (if have-error-logger? :error :info)
:error (if have-error-logger? :error :info)
:warn (if have-warn-logger? :warn :info)}]
(if-not have-logger?
(fn [data] nil)
(fn [data]
(let [{:keys [level appender-opts output-fn]} data
{:keys []} appender-opts
output (output-fn data)]
(case (adjust-level level)
:error (.error js/console output)
:warn (.warn js/console output)
(.log js/console output))))))}}}))
``` ```
A few things to note: A few things to note:

View File

@ -12,11 +12,6 @@
[java.text SimpleDateFormat] [java.text SimpleDateFormat]
[java.io File])) [java.io File]))
;;;; TODO
;; - Try ease backward comp, update README, CHANGELOG
;; - Document shutdown-agents,
;; Ref. https://github.com/ptaoussanis/timbre/pull/100/files
;;;; Encore version check ;;;; Encore version check
#+clj #+clj
@ -105,79 +100,78 @@
The `example-config` source code contains further settings and details. The `example-config` source code contains further settings and details.
See also `set-config!`, `merge-config!`, `set-level!`." See also `set-config!`, `merge-config!`, `set-level!`."
(merge {:level :debug ; e/o #{:trace :debug :info :warn :error :fatal :report}
{:level :debug ; e/o #{:trace :debug :info :warn :error :fatal :report}
;; Control log filtering by namespaces/patterns. Useful for turning off ;; Control log filtering by namespaces/patterns. Useful for turning off
;; logging in noisy libraries, etc.: ;; logging in noisy libraries, etc.:
:whitelist [] #_["my-app.foo-ns"] :whitelist [] #_["my-app.foo-ns"]
:blacklist [] #_["taoensso.*"] :blacklist [] #_["taoensso.*"]
:middleware [] ; (fns [data]) -> ?data, applied left->right :middleware [] ; (fns [data]) -> ?data, applied left->right
#+clj :timestamp-opts #+clj :timestamp-opts
#+clj default-timestamp-opts ; {:pattern _ :locale _ :timezone _} #+clj default-timestamp-opts ; {:pattern _ :locale _ :timezone _}
:output-fn default-output-fn ; (fn [data]) -> string :output-fn default-output-fn ; (fn [data]) -> string
:appenders :appenders
#+clj #+clj
{:println ; Appender id {:println ; Appender id
;; Appender <map>: ;; Appender map:
{:doc "Prints to (:stream <appender-opts>) IO stream. Enabled by default." {:doc "Prints to (:stream <appender-opts>) IO stream. Enabled by default."
:min-level nil :enabled? true :async? false :rate-limit nil :min-level nil :enabled? true :async? false :rate-limit nil
;; Any custom appender opts: ;; Any custom appender opts:
:opts {:stream :auto ; e/o #{:std-err :std-out :auto <stream>} :opts {:stream :auto ; e/o #{:std-err :std-out :auto <stream>}
} }
:fn :fn
(fn [data] (fn [data]
(let [{:keys [output-fn error? appender-opts]} data (let [{:keys [output-fn error? appender-opts]} data
{:keys [stream]} appender-opts {:keys [stream]} appender-opts
stream (case stream stream (case stream
(nil :auto) (if error? default-err *out*) (nil :auto) (if error? default-err *out*)
:std-err default-err :std-err default-err
:std-out default-out :std-out default-out
stream)] stream)]
(binding [*out* stream] (println (output-fn data)))))} (binding [*out* stream] (println (output-fn data)))))}
:spit :spit
{:doc "Spits to (:spit-filename <appender-opts>) file." {:doc "Spits to (:spit-filename <appender-opts>) file."
:min-level nil :enabled? false :async? false :rate-limit nil :min-level nil :enabled? false :async? false :rate-limit nil
:opts {:spit-filename "timbre-spit.log"} :opts {:spit-filename "timbre-spit.log"}
:fn :fn
(fn [data] (fn [data]
(let [{:keys [output-fn appender-opts]} data (let [{:keys [output-fn appender-opts]} data
{:keys [spit-filename]} appender-opts] {:keys [spit-filename]} appender-opts]
(when-let [fname (enc/as-?nblank spit-filename)] (when-let [fname (enc/as-?nblank spit-filename)]
(try (ensure-spit-dir-exists! fname) (try (ensure-spit-dir-exists! fname)
(spit fname (str (output-fn data) "\n") :append true) (spit fname (str (output-fn data) "\n") :append true)
(catch java.io.IOException _)))))}} (catch java.io.IOException _)))))}}
#+cljs #+cljs
{:console {:console
{:doc "Logs to js/console when it exists. Enabled by default." {:doc "Logs to js/console when it exists. Enabled by default."
:min-level nil :enabled? true :async? false :rate-limit nil :min-level nil :enabled? true :async? false :rate-limit nil
:opts {} :opts {}
:fn :fn
(let [have-logger? (and (exists? js/console) (.-log js/console)) (let [have-logger? (and (exists? js/console) (.-log js/console))
have-warn-logger? (and have-logger? (.-warn js/console)) have-warn-logger? (and have-logger? (.-warn js/console))
have-error-logger? (and have-logger? (.-error js/console)) have-error-logger? (and have-logger? (.-error js/console))
adjust-level {:fatal (if have-error-logger? :error :info) adjust-level {:fatal (if have-error-logger? :error :info)
:error (if have-error-logger? :error :info) :error (if have-error-logger? :error :info)
:warn (if have-warn-logger? :warn :info)}] :warn (if have-warn-logger? :warn :info)}]
(if-not have-logger? (if-not have-logger?
(fn [data] nil) (fn [data] nil)
(fn [data] (fn [data]
(let [{:keys [level appender-opts output-fn]} data (let [{:keys [level appender-opts output-fn]} data
{:keys []} appender-opts {:keys []} appender-opts
output (output-fn data)] output (output-fn data)]
(case (adjust-level level) (case (adjust-level level)
:error (.error js/console output) :error (.error js/console output)
:warn (.warn js/console output) :warn (.warn js/console output)
(.log js/console output))))))}}})) (.log js/console output))))))}}})
(comment (comment
(set-config! example-config) (set-config! example-config)
@ -195,8 +189,8 @@
(defn set-config! [m] (swap-config! (fn [_old] m))) (defn set-config! [m] (swap-config! (fn [_old] m)))
(defn merge-config! [m] (swap-config! (fn [old] (enc/nested-merge old m)))) (defn merge-config! [m] (swap-config! (fn [old] (enc/nested-merge old m))))
(defn set-level! [level] (swap-config! (fn [m] (merge m {:level level})))) (defn set-level! [level] (swap-config! (fn [m] (merge m {:level level}))))
(defn with-level [level & body] (defmacro with-level [level & body]
`(binding [*config* (merge *config* {:level ~level})] ~@body)) `(binding [*config* (merge *config* {:level ~level})] ~@body))
(comment (set-level! :info) *config*) (comment (set-level! :info) *config*)
@ -205,11 +199,11 @@
(def ordered-levels [:trace :debug :info :warn :error :fatal :report]) (def ordered-levels [:trace :debug :info :warn :error :fatal :report])
(def ^:private scored-levels (zipmap ordered-levels (next (range)))) (def ^:private scored-levels (zipmap ordered-levels (next (range))))
(def ^:private valid-levels (set ordered-levels))
(def ^:private valid-level (def ^:private valid-level
(let [valid-level-set (set ordered-levels)] (fn [level]
(fn [level] (or (valid-levels level)
(or (valid-level-set level) (throw (ex-info (str "Invalid logging level: " level) {:level level})))))
(throw (ex-info (str "Invalid logging level: " level) {:level level}))))))
(comment (valid-level :info)) (comment (valid-level :info))
@ -220,7 +214,9 @@
#+clj (defn- env-val [id] (when-let [s (System/getenv id)] (enc/read-edn s))) #+clj (defn- env-val [id] (when-let [s (System/getenv id)] (enc/read-edn s)))
#+clj (def ^:private compile-time-level #+clj (def ^:private compile-time-level
(have [:or nil? valid-level] (keyword (env-val "TIMBRE_LEVEL")))) (have [:or nil? valid-level]
(keyword (or (env-val "TIMBRE_LEVEL")
(env-val "TIMBRE_LOG_LEVEL")))))
(defn get-active-level [& [config]] (or (:level (or config *config*)) :report)) (defn get-active-level [& [config]] (or (:level (or config *config*)) :report))
@ -307,7 +303,7 @@
(comment (def rf (get-rate-limiter :my-appender [[10 5000]]))) (comment (def rf (get-rate-limiter :my-appender [[10 5000]])))
;;;; Logging core ;;;; Internal logging core
(defn log? (defn log?
"Would Timbre currently log at the given logging level? "Would Timbre currently log at the given logging level?
@ -328,14 +324,15 @@
(declare get-hostname) (declare get-hostname)
(defn log* "Core fn-level logger. Implementation detail." (defn log1-fn
[config level ?ns-str ?file ?line msg-type vargs_ & [base-data]] "Core fn-level logger. Implementation detail!"
[config level ?ns-str ?file ?line msg-type vargs_ & [?base-data]]
(when (log? level ?ns-str config) (when (log? level ?ns-str config)
(let [instant (enc/now-dt) (let [instant (enc/now-dt)
vargs*_ (delay (vsplit-err1 (force vargs_))) vargs*_ (delay (vsplit-err1 (force vargs_)))
?err_ (delay (get @vargs*_ 0)) ?err_ (delay (get @vargs*_ 0))
vargs_ (delay (get @vargs*_ 1)) vargs_ (delay (get @vargs*_ 1))
data (merge base-data *context* data (merge ?base-data *context*
{:config config ; Entire config! {:config config ; Entire config!
;; :context *context* ; Extra destructure's a nuisance ;; :context *context* ; Extra destructure's a nuisance
:instant instant :instant instant
@ -352,9 +349,9 @@
(when-not (nil? msg-type) (when-not (nil? msg-type)
(when-let [vargs (have [:or nil? vector?] (force vargs_))] (when-let [vargs (have [:or nil? vector?] (force vargs_))]
(case msg-type (case msg-type
:print (enc/spaced-str vargs) :p (enc/spaced-str vargs)
:format (let [[fmt args] (enc/vsplit-first vargs)] :f (let [[fmt args] (enc/vsplit-first vargs)]
(enc/format* fmt args)))))) (enc/format* fmt args))))))
?data ?data
(reduce ; Apply middleware: data->?data (reduce ; Apply middleware: data->?data
(fn [acc mf] (fn [acc mf]
@ -418,41 +415,49 @@
nil) nil)
(comment (comment
(log* *config* :info nil nil nil :print (delay [(do (println "hi") :x) :y]))) (log1-fn *config* :info nil nil nil :p (delay [(do (println "hi") :x) :y]) nil))
;;;; Logging macros (defmacro log1-macro
"Core macro-level logger. Implementation detail!"
(defmacro log "Core macro-level logger." [config level msg-type args & [?base-data]]
[config level msg-type args & [base-data]]
;; Compile-time elision: ;; Compile-time elision:
(when (or (nil? compile-time-level) (level>= level compile-time-level)) (when (or (nil? compile-time-level)
(not (valid-levels level)) ; Not a compile-time level
(level>= level compile-time-level))
(when (compile-time-ns-filter (str *ns*)) (when (compile-time-ns-filter (str *ns*))
(let [ns-str (str *ns*) (let [ns-str (str *ns*)
?file (let [f *file*] (when (not= f "NO_SOURCE_PATH") f)) ?file (let [f *file*] (when (not= f "NO_SOURCE_PATH") f))
;; TODO Waiting on http://dev.clojure.org/jira/browse/CLJ-865: ;; TODO Waiting on http://dev.clojure.org/jira/browse/CLJ-865:
?line (:line (meta &form))] ?line (:line (meta &form))]
`(log* ~config ~level ~ns-str ~?file ~?line ~msg-type `(log1-fn ~config ~level ~ns-str ~?file ~?line ~msg-type
(delay [~@args]) ~base-data))))) (delay [~@args]) ~?base-data)))))
;;;; API-level stuff
;;; Log using print-style args ;;; Log using print-style args
(defmacro trace [& args] `(log *config* :trace :print ~args)) (defmacro log* [config level & args] `(log1-macro ~config ~level :p ~args))
(defmacro debug [& args] `(log *config* :debug :print ~args)) (defmacro log [level & args] `(log1-macro *config* ~level :p ~args))
(defmacro info [& args] `(log *config* :info :print ~args)) (defmacro trace [& args] `(log1-macro *config* :trace :p ~args))
(defmacro warn [& args] `(log *config* :warn :print ~args)) (defmacro debug [& args] `(log1-macro *config* :debug :p ~args))
(defmacro error [& args] `(log *config* :error :print ~args)) (defmacro info [& args] `(log1-macro *config* :info :p ~args))
(defmacro fatal [& args] `(log *config* :fatal :print ~args)) (defmacro warn [& args] `(log1-macro *config* :warn :p ~args))
(defmacro report [& args] `(log *config* :report :print ~args)) (defmacro error [& args] `(log1-macro *config* :error :p ~args))
(defmacro fatal [& args] `(log1-macro *config* :fatal :p ~args))
(defmacro report [& args] `(log1-macro *config* :report :p ~args))
;;; Log using format-style args ;;; Log using format-style args
(defmacro tracef [& args] `(log *config* :trace :format ~args)) (defmacro logf* [config level & args] `(log1-macro ~config ~level :f ~args))
(defmacro debugf [& args] `(log *config* :debug :format ~args)) (defmacro logf [level & args] `(log1-macro *config* ~level :f ~args))
(defmacro infof [& args] `(log *config* :info :format ~args)) (defmacro tracef [& args] `(log1-macro *config* :trace :f ~args))
(defmacro warnf [& args] `(log *config* :warn :format ~args)) (defmacro debugf [& args] `(log1-macro *config* :debug :f ~args))
(defmacro errorf [& args] `(log *config* :error :format ~args)) (defmacro infof [& args] `(log1-macro *config* :info :f ~args))
(defmacro fatalf [& args] `(log *config* :fatal :format ~args)) (defmacro warnf [& args] `(log1-macro *config* :warn :f ~args))
(defmacro reportf [& args] `(log *config* :report :format ~args)) (defmacro errorf [& args] `(log1-macro *config* :error :f ~args))
(defmacro fatalf [& args] `(log1-macro *config* :fatal :f ~args))
(defmacro reportf [& args] `(log1-macro *config* :report :f ~args))
(comment (comment
(infof "hello %s" "world") (infof "hello %s" "world")
@ -485,7 +490,7 @@
([config level name expr] ([config level name expr]
`(log-and-rethrow-errors `(log-and-rethrow-errors
(let [result# ~expr] (let [result# ~expr]
(log ~config ~level :print [~name "=>" result#]) (log* ~config ~level [~name "=>" result#])
result#)))) result#))))
#+clj #+clj
@ -540,7 +545,7 @@
(binding [aviso-ex/*fonts* fonts] (aviso-ex/format-exception err)) (binding [aviso-ex/*fonts* fonts] (aviso-ex/format-exception err))
(aviso-ex/format-exception err))) (aviso-ex/format-exception err)))
(comment (stacktrace (Exception. "Boo"))) (comment (stacktrace (Exception. "Boo") {:stacktrace-fonts {}}))
#+clj #+clj
(def ^:private ensure-spit-dir-exists! (def ^:private ensure-spit-dir-exists!
@ -556,9 +561,17 @@
`(do (assert (<= 0 ~probability 1) "Probability: 0 <= p <= 1") `(do (assert (<= 0 ~probability 1) "Probability: 0 <= p <= 1")
(when (< (rand) ~probability) ~@body))) (when (< (rand) ~probability) ~@body)))
;;;; Shutdown hook ; Workaround for http://dev.clojure.org/jira/browse/CLJ-124 ;;;; EXPERIMENTAL shutdown hook
;; Workaround for http://dev.clojure.org/jira/browse/CLJ-124
#+clj #+clj
(defonce ^:private shutdown-hook (defonce ^:private shutdown-hook
(.addShutdownHook (Runtime/getRuntime) (.addShutdownHook (Runtime/getRuntime)
(Thread. (fn [] (shutdown-agents))))) (Thread. (fn [] (shutdown-agents)))))
;;;; Deprecated
(defn str-println [& xs] (enc/spaced-str xs))
(defmacro with-log-level [level & body] `(with-level ~level ~@body))
(defmacro with-logging-config [config & body] `(with-config ~config ~@body))
(defn logging-enabled? [level compile-time-ns] (log? level (str compile-time-ns)))

View File

@ -42,3 +42,7 @@
:error (android.util.Log/e ns output) :error (android.util.Log/e ns output)
:fatal (android.util.Log/e ns output) :fatal (android.util.Log/e ns output)
:report (android.util.Log/i ns output)))))}))) :report (android.util.Log/i ns output)))))})))
;;;; Deprecated
(def make-logcat-appender make-appender)

View File

@ -73,3 +73,7 @@
:name "Lazylus Logus" :name "Lazylus Logus"
:chan "bob"}}}}) :chan "bob"}}}})
(timbre/error "A multiple\nline message\nfor you")) (timbre/error "A multiple\nline message\nfor you"))
;;;; Deprecated
(def make-irc-appender make-appender)

View File

@ -73,3 +73,7 @@
(let [default-appender-config {:enabled? true :min-level nil}] (let [default-appender-config {:enabled? true :min-level nil}]
(merge default-appender-config appender-config (merge default-appender-config appender-config
{:fn (make-appender-fn path pattern)}))) {:fn (make-appender-fn path pattern)})))
;;;; Deprecated
(def make-rolling-appender make-appender)

View File

@ -35,3 +35,7 @@
(zmq/register socket :pollout :pollerr))] (zmq/register socket :pollout :pollerr))]
(merge default-appender-config appender-config (merge default-appender-config appender-config
{:fn (make-appender-fn socket poller)}))) {:fn (make-appender-fn socket poller)})))
;;;; Deprecated
(def make-zmq-appender make-appender)

View File

@ -144,3 +144,7 @@
(count (query-entries {} :info 2)) (count (query-entries {} :info 2))
(count (query-entries {} :info 2 :asc))) (count (query-entries {} :info 2 :asc)))
;;;; Deprecated
(def make-carmine-appender make-appender)

View File

@ -6,7 +6,7 @@
[taoensso.timbre :as timbre] [taoensso.timbre :as timbre]
[taoensso.encore :as enc :refer (have have?)])) [taoensso.encore :as enc :refer (have have?)]))
(defn make-postal-appender (defn make-appender
"Returns a Postal email appender. "Returns a Postal email appender.
A Postal config map can be provided here as an argument, or as a :postal key A Postal config map can be provided here as an argument, or as a :postal key
in :shared-appender-config. in :shared-appender-config.
@ -44,3 +44,7 @@
(str/replace #"\s+" " ") (str/replace #"\s+" " ")
(enc/substr 0 subject-len)) (enc/substr 0 subject-len))
:body (body-fn output)))))))}))) :body (body-fn output)))))))})))
;;;; Deprecated
(def make-postal-appender make-appender)

View File

@ -78,7 +78,7 @@
[level id & body] [level id & body]
`(let [{result# :result stats# :stats} (with-pdata ~level ~@body)] `(let [{result# :result stats# :stats} (with-pdata ~level ~@body)]
(when stats# (when stats#
(timbre/log timbre/*config* ~level :format (timbre/log1-macro timbre/*config* ~level :f
["Profiling: %s\n%s" (fq-keyword ~id) (format-stats stats#)] ["Profiling: %s\n%s" (fq-keyword ~id) (format-stats stats#)]
{:profile-stats stats#})) {:profile-stats stats#}))
result#)) result#))

View File

@ -19,9 +19,9 @@
?ns-str nil ; No support ?ns-str nil ; No support
?file nil ; '' ?file nil ; ''
?line nil ; '' ?line nil ; ''
msg-type :print ; No support for pre-msg raw args msg-type :p ; No support for pre-msg raw args
] ]
(timbre/log* config level ?ns-str ?file ?line msg-type [message])))) (timbre/log1-fn config level ?ns-str ?file ?line msg-type [message]))))
(deftype LoggerFactory [] (deftype LoggerFactory []
clojure.tools.logging.impl/LoggerFactory clojure.tools.logging.impl/LoggerFactory