mirror of https://github.com/status-im/timbre.git
Merge branch 'dev'
This commit is contained in:
commit
fb44efddd8
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
|||
> This project uses [Break Versioning](https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md) as of **Aug 16, 2014**.
|
||||
|
||||
## v3.3.0 / 2014 May 8
|
||||
|
||||
* **CHANGE**: Update IRC appender to Timbre v3 style (@crisptrutski).
|
||||
* **FIX** [#47]: correctly format nanosecond profiling times.
|
||||
* **FIX** [#77]: profile ids now use correct (compile-time rather than runtime) ns prefix.
|
||||
* **NEW**: Add zmq appender (@angusiguess).
|
||||
* **NEW** [#75]: Make defnp support multi-arity functions (@maurolopes)
|
||||
|
||||
|
||||
## v3.2.1 / 2014 May 7
|
||||
|
||||
* **FIX**: missing tools.reader upstream dependency (@ducky427).
|
||||
|
@ -5,7 +16,7 @@
|
|||
|
||||
## v3.2.0 / 2014 May 6
|
||||
|
||||
* [#60] **FIX**: `defnp` no longer generates an Eastwood warning (@ducky427).
|
||||
* **FIX** [#60]: `defnp` no longer generates an Eastwood warning (@ducky427).
|
||||
* **CHANGE**: Improved profiling memory efficiency (max memory use, was previously unbounded).
|
||||
* **CHANGE**: Profiling: make larger call numbers easier to read.
|
||||
* [#63]: **NEW**: Add support for thread-local configuration (@jameswarren).
|
||||
|
@ -13,19 +24,19 @@
|
|||
|
||||
## v3.1.6 / 2014 Mar 16
|
||||
|
||||
* [#56] FIX: `defnp`/`p` head retention issue (kyptin).
|
||||
* **FIX** [#56]: `defnp`/`p` head retention issue (@kyptin).
|
||||
|
||||
|
||||
## v3.1.5 / 2014 Mar 15
|
||||
|
||||
* FIX: `profiling/p*` was defined incorrectly (kyptin).
|
||||
* **FIX**: `profiling/p*` was defined incorrectly (@kyptin).
|
||||
|
||||
|
||||
## v3.1.4 / 2014 Mar 13
|
||||
|
||||
* NEW: Add `profiling/p*` macro.
|
||||
* CHANGE: Include `p`, `p*` in `refer-timbre` imports.
|
||||
* FIX: rotor appender not rotating (iantruslove, kurtharriger).
|
||||
* **NEW**: Add `profiling/p*` macro.
|
||||
* **CHANGE**: Include `p`, `p*` in `refer-timbre` imports.
|
||||
* **FIX**: rotor appender not rotating (@iantruslove, @kurtharriger).
|
||||
|
||||
|
||||
## v3.1.3 / 2014 Mar 11
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
**[API docs][]** | **[CHANGELOG][]** | [other Clojure libs][] | [Twitter][] | [contact/contributing](#contact--contributing) | current ([semantic][]) version:
|
||||
**[API docs][]** | **[CHANGELOG][]** | [other Clojure libs][] | [Twitter][] | [contact/contrib](#contact--contributing) | current [Break Version][]:
|
||||
|
||||
```clojure
|
||||
[com.taoensso/timbre "3.2.1"] ; Stable
|
||||
[com.taoensso/timbre "3.3.0"]
|
||||
```
|
||||
|
||||
v3 is a **major, backwards-compatible release**. Please see the [CHANGELOG][] for details. Appender authors: please see [here](https://github.com/ptaoussanis/timbre/issues/41) about migrating Timbre 2.x appenders to 3.x's recommended style.
|
||||
|
@ -34,7 +34,7 @@ Logging with Java can be maddeningly, unnecessarily hard. Particularly if all yo
|
|||
Add the necessary dependency to your [Leiningen][] `project.clj` and use the supplied ns-import helper:
|
||||
|
||||
```clojure
|
||||
[com.taoensso/timbre "3.2.1"] ; project.clj
|
||||
[com.taoensso/timbre "3.3.0"] ; project.clj
|
||||
|
||||
(ns my-app (:require [taoensso.timbre :as timbre])) ; Your ns
|
||||
(timbre/refer-timbre) ; Provides useful Timbre aliases in this ns
|
||||
|
@ -295,7 +295,8 @@ Copyright © 2012-2014 Peter Taoussanis. Distributed under the [Eclipse Publ
|
|||
[CHANGELOG]: <https://github.com/ptaoussanis/timbre/releases>
|
||||
[other Clojure libs]: <https://www.taoensso.com/clojure-libraries>
|
||||
[Twitter]: <https://twitter.com/ptaoussanis>
|
||||
[semantic]: <http://semver.org/>
|
||||
[SemVer]: <http://semver.org/>
|
||||
[Break Version]: <https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md>
|
||||
[Leiningen]: <http://leiningen.org/>
|
||||
[CDS]: <http://clojure-doc.org/>
|
||||
[ClojureWerkz]: <http://clojurewerkz.org/>
|
||||
|
|
35
project.clj
35
project.clj
|
@ -1,4 +1,4 @@
|
|||
(defproject com.taoensso/timbre "3.2.1"
|
||||
(defproject com.taoensso/timbre "3.3.0"
|
||||
:author "Peter Taoussanis <https://www.taoensso.com>"
|
||||
:description "Clojure logging & profiling library"
|
||||
:url "https://github.com/ptaoussanis/timbre"
|
||||
|
@ -9,42 +9,39 @@
|
|||
:min-lein-version "2.3.3"
|
||||
:global-vars {*warn-on-reflection* true
|
||||
*assert* true}
|
||||
|
||||
:dependencies
|
||||
[[org.clojure/clojure "1.4.0"]
|
||||
[com.taoensso/encore "1.5.1"]
|
||||
[io.aviso/pretty "0.1.10"]]
|
||||
[com.taoensso/encore "1.7.3"]
|
||||
[io.aviso/pretty "0.1.12"]]
|
||||
|
||||
:test-paths ["test" "src"]
|
||||
:profiles
|
||||
{;; :default [:base :system :user :provided :dev]
|
||||
:server-jvm {:jvm-opts ^:replace ["-server"]}
|
||||
:1.5 {:dependencies [[org.clojure/clojure "1.5.1"]]}
|
||||
:1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}
|
||||
:test {:dependencies [[expectations "1.4.56"]
|
||||
[org.clojure/test.check "0.5.7"]
|
||||
[com.taoensso/nippy "2.6.3"]
|
||||
[com.taoensso/carmine "2.6.2"]
|
||||
[com.draines/postal "1.11.1"]
|
||||
[org.clojure/tools.logging "0.2.6"]]
|
||||
:test {:dependencies [[expectations "2.0.9"]
|
||||
[org.clojure/test.check "0.5.9"]
|
||||
[com.taoensso/nippy "2.7.0-RC1"]
|
||||
[com.taoensso/carmine "2.7.0"]
|
||||
[com.draines/postal "1.11.1"]
|
||||
[org.clojure/tools.logging "0.3.0"]]
|
||||
:plugins [[lein-expectations "0.0.8"]
|
||||
[lein-autoexpect "1.2.2"]]}
|
||||
:dev* [:dev {:jvm-opts ^:replace ["-server"]
|
||||
;; :hooks [cljx.hooks leiningen.cljsbuild] ; cljx
|
||||
}]
|
||||
:dev
|
||||
[:1.6 :test
|
||||
{:dependencies []
|
||||
{:dependencies [[irclj "0.5.0-alpha4"]]
|
||||
:plugins [[lein-ancient "0.5.4"]
|
||||
[codox "0.6.7"]]}]}
|
||||
[codox "0.8.10"]]}]}
|
||||
|
||||
:test-paths ["test" "src"]
|
||||
|
||||
;; :codox {:sources ["target/classes"]} ; cljx
|
||||
:aliases
|
||||
{"test-all" ["with-profile" "default:+1.5:+1.6" "expectations"]
|
||||
;; "test-all" ["with-profile" "default:+1.6" "expectations"]
|
||||
"test-auto" ["with-profile" "+test" "autoexpect"]
|
||||
;; "build-once" ["do" "cljx" "once," "cljsbuild" "once"] ; cljx
|
||||
;; "deploy-lib" ["do" "build-once," "deploy" "clojars," "install"] ; cljx
|
||||
"deploy-lib" ["do" "deploy" "clojars," "install"]
|
||||
"start-dev" ["with-profile" "+dev*" "repl" ":headless"]}
|
||||
"start-dev" ["with-profile" "+server-jvm" "repl" ":headless"]}
|
||||
|
||||
:repositories
|
||||
{"sonatype"
|
||||
|
|
|
@ -283,6 +283,9 @@
|
|||
(let [juxtfn-args (if-not msg-type juxtfn-args ; tools.logging
|
||||
(-> juxtfn-args
|
||||
(dissoc :msg-type)
|
||||
;; TODO Consider a breaking change here to
|
||||
;; swap assoc'd message with a delay, as
|
||||
;; per http://goo.gl/7YVSfj:
|
||||
(assoc :message
|
||||
(when-not (empty? args)
|
||||
(case msg-type
|
||||
|
@ -403,6 +406,9 @@
|
|||
}))
|
||||
nil))
|
||||
|
||||
(defmacro get-compile-time-ns [] (str *ns*)) ; Nb need `str` to be readable
|
||||
(comment (macroexpand '(get-compile-time-ns)))
|
||||
|
||||
(defmacro log* "Implementation detail."
|
||||
{:arglists '([base-appender-args msg-type level & log-args]
|
||||
[base-appender-args msg-type config level & log-args])}
|
||||
|
@ -420,7 +426,7 @@
|
|||
default-config?# (levels-scored s1#)
|
||||
config# (if default-config?# (get-default-config) s1#)
|
||||
level# (if default-config?# s1# ~s2)
|
||||
compile-time-ns# ~(str *ns*)]
|
||||
compile-time-ns# (get-compile-time-ns)]
|
||||
;; (println "DEBUG: Runtime level check")
|
||||
(when (and (level-sufficient? level# config#)
|
||||
(ns-unfiltered? config# compile-time-ns#))
|
||||
|
|
|
@ -2,45 +2,74 @@
|
|||
"IRC appender. Depends on https://github.com/flatland/irclj."
|
||||
{:author "Emlyn Corrin"}
|
||||
(:require [clojure.string :as str]
|
||||
[irclj.core :as irclj]
|
||||
[irclj.core :as irc]
|
||||
[taoensso.timbre :as timbre]))
|
||||
|
||||
(def conn (atom nil))
|
||||
(defn default-fmt-output-fn
|
||||
[{:keys [level throwable message]}]
|
||||
(format "[%s] %s%s"
|
||||
(-> level name (str/upper-case))
|
||||
(or message "")
|
||||
(or (timbre/stacktrace throwable "\n") "")))
|
||||
|
||||
(defn connect [{:keys [host port pass nick user name chan]
|
||||
:or {:port 6667}}]
|
||||
(let [conn (irclj/connect host port nick
|
||||
:username user
|
||||
:real-name name
|
||||
:pass pass
|
||||
:callbacks {})]
|
||||
(irclj/join conn chan)
|
||||
(def default-appender-opts
|
||||
{:async? true
|
||||
:enabled? true
|
||||
:min-level :info})
|
||||
|
||||
(defn- connect [{:keys [host port pass nick user name chan]
|
||||
:or {port 6667}}]
|
||||
(let [conn (irc/connect host port nick
|
||||
:username user
|
||||
:real-name name
|
||||
:pass pass
|
||||
:callbacks {})]
|
||||
(irc/join conn chan)
|
||||
conn))
|
||||
|
||||
(defn ensure-conn [conf]
|
||||
(swap! conn #(or % (connect conf))))
|
||||
(defn- ensure-conn [conn conf]
|
||||
(if-not @conn
|
||||
(reset! conn @(connect conf))))
|
||||
|
||||
(defn send-message [{:keys [prefix throwable message chan] :as config}]
|
||||
(let [conn (ensure-conn config)
|
||||
lines (-> (str message (timbre/stacktrace throwable "\n"))
|
||||
(str/split #"\n"))]
|
||||
(irclj/message conn chan prefix (first lines))
|
||||
(doseq [line (rest lines)]
|
||||
(irclj/message conn chan ">" line))))
|
||||
(defn- send-message [conn chan output]
|
||||
(let [[fst & rst] (str/split output #"\n")]
|
||||
(irc/message conn chan fst)
|
||||
(doseq [line rst]
|
||||
(irc/message conn chan ">" line))))
|
||||
|
||||
(defn appender-fn [{:keys [ap-config prefix throwable message]}]
|
||||
(when-let [irc-config (:irc ap-config)]
|
||||
(send-message
|
||||
(assoc irc-config
|
||||
:prefix prefix
|
||||
:throwable throwable
|
||||
:message message))))
|
||||
(defn- make-appender-fn [irc-config conn]
|
||||
(fn [{:keys [ap-config] :as args}]
|
||||
(when-let [irc-config (or irc-config (:irc ap-config))]
|
||||
(ensure-conn conn irc-config)
|
||||
(let [fmt-fn (or (:fmt-output-fn irc-config)
|
||||
default-fmt-output-fn)]
|
||||
(send-message conn (:chan irc-config) (fmt-fn args))))))
|
||||
|
||||
(def irc-appender
|
||||
{:doc (str "Sends IRC messages using irclj.\n"
|
||||
"Needs :irc config map in :shared-appender-config, e.g.:
|
||||
{:host \"irc.example.org\" :port 6667 :nick \"logger\"
|
||||
:name \"My Logger\" :chan \"#logs\"")
|
||||
:min-level :info :enabled? true
|
||||
:prefix-fn (fn [{:keys [level]}] (-> level name str/upper-case))
|
||||
:fn appender-fn})
|
||||
;;; Public
|
||||
|
||||
(defn make-irc-appender
|
||||
"Sends IRC messages using irc.
|
||||
Needs :irc config map in :shared-appender-config, e.g.:
|
||||
{:host \"irc.example.org\" :port 6667 :nick \"logger\"
|
||||
:name \"My Logger\" :chan \"#logs\"}"
|
||||
[& [appender-opts {:keys [irc-config]}]]
|
||||
(let [conn (atom nil)]
|
||||
(merge default-appender-opts
|
||||
appender-opts
|
||||
{:conn conn
|
||||
:doc (:doc (meta #'make-irc-appender))
|
||||
:fn (make-appender-fn irc-config conn)})))
|
||||
|
||||
(def irc-appender "DEPRECATED: Use `make-irc-appender` instead."
|
||||
(make-irc-appender))
|
||||
|
||||
(comment
|
||||
(timbre/set-config!
|
||||
[:shared-appender-config :irc]
|
||||
{:host "127.0.0.1"
|
||||
:nick "lazylog"
|
||||
:user "lazare"
|
||||
:name "Lazylus Logus"
|
||||
:chan "bob"})
|
||||
(timbre/set-config! [:appenders :irc] (make-irc-appender))
|
||||
(timbre/log :error "A multiple\nline message\nfor you"))
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
(ns taoensso.timbre.appenders.zmq
|
||||
"ØMQ appender. Requires https://github.com/zeromq/cljzmq"
|
||||
{:author "Angus Fletcher"}
|
||||
(:require [zeromq.zmq :as zmq]
|
||||
[taoensso.timbre :as timbre]))
|
||||
|
||||
(defn make-zmq-socket [context transport address port]
|
||||
(doto (zmq/socket context :push)
|
||||
(zmq/connect (format "%s://%s:%d" transport address port))))
|
||||
|
||||
(defn appender-fn [socket poller {:keys [ap-config output]}]
|
||||
(loop []
|
||||
(zmq/poll poller 500)
|
||||
(cond
|
||||
(zmq/check-poller poller 0 :pollout) (zmq/send-str socket output)
|
||||
(zmq/check-poller poller 0 :pollerr) (System/exit 1)
|
||||
:else (recur))))
|
||||
|
||||
(defn make-zmq-appender
|
||||
"Returns a ØMQ appender. Takes appender options and a map consisting of:
|
||||
transport: a string representing transport type: tcp, ipc, inproc, pgm/epgm
|
||||
address: a string containing an address to connect to.
|
||||
port: a number representing the port to connect to."
|
||||
[& [appender-opts {:keys [transport address port]}]]
|
||||
(let [default-appender-opts {:enabled? true
|
||||
:min-level :error
|
||||
:async? true}
|
||||
context (zmq/zcontext)
|
||||
socket (make-zmq-socket context transport address port)
|
||||
poller (doto (zmq/poller context)
|
||||
(zmq/register socket :pollout :pollerr))]
|
||||
(merge default-appender-opts
|
||||
appender-opts
|
||||
{:fn (partial appender-fn socket poller)})))
|
|
@ -9,7 +9,7 @@
|
|||
(defmacro fq-keyword "Returns namespaced keyword for given id."
|
||||
[id]
|
||||
`(if (and (keyword? ~id) (namespace ~id)) ~id
|
||||
(keyword (str *ns*) (name ~id))))
|
||||
(keyword (timbre/get-compile-time-ns) (name ~id))))
|
||||
|
||||
(comment (map #(fq-keyword %) ["foo" :foo :foo/bar]))
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
|||
(declare ^:private format-stats)
|
||||
|
||||
(defmacro with-pdata [level & body]
|
||||
`(if-not (timbre/logging-enabled? ~level ~(str *ns*))
|
||||
`(if-not (timbre/logging-enabled? ~level (timbre/get-compile-time-ns))
|
||||
{:result (do ~@body)}
|
||||
(binding [*pdata* (atom {})]
|
||||
{:result (pspy ::clock-time ~@body)
|
||||
|
@ -85,20 +85,6 @@
|
|||
(if-not (< (rand) ~probability) (do ~@body)
|
||||
(profile ~level ~id ~@body))))
|
||||
|
||||
(defmacro defnp "Like `defn` but wraps body in `p` macro."
|
||||
{:arglists '([name ?doc-string ?attr-map [params] ?prepost-map body])}
|
||||
[name & sigs]
|
||||
(let [[name [params & sigs]] (encore/name-with-attrs name sigs)
|
||||
prepost-map (when (and (map? (first sigs)) (next sigs)) (first sigs))
|
||||
body (if prepost-map (next sigs) sigs)]
|
||||
`(defn ~name ~params ~prepost-map
|
||||
(pspy ~(clojure.core/name name)
|
||||
~@body))))
|
||||
|
||||
(comment (defnp foo "Docstring "[x] "boo" (* x x))
|
||||
(macroexpand '(defnp foo "Docstring "[x] "boo" (* x x)))
|
||||
(profile :info :defnp-test (foo 5)))
|
||||
|
||||
;;;; Data capturing & aggregation
|
||||
|
||||
(def ^:private ^:constant stats-gc-n 111111)
|
||||
|
@ -193,7 +179,8 @@
|
|||
s-pattern (str "%" max-id-width "s %11s %9s %10s %9s %9s %7s %1s%n")
|
||||
perc #(Math/round (/ %1 %2 0.01))
|
||||
ft (fn [nanosecs]
|
||||
(let [pow #(Math/pow 10 %)
|
||||
(let [nanosecs (long nanosecs) ; Truncate any fractional nanosecs
|
||||
pow #(Math/pow 10 %)
|
||||
ok-pow? #(>= nanosecs (pow %))
|
||||
to-pow #(encore/round (/ nanosecs (pow %1)) :round %2)]
|
||||
(cond (ok-pow? 9) (str (to-pow 9 1) "s")
|
||||
|
@ -213,19 +200,39 @@
|
|||
(printf s-pattern "Accounted Time" "" "" "" "" ""
|
||||
(perc accounted clock-time) (ft accounted)))))
|
||||
|
||||
(defmacro defnp "Like `defn` but wraps body in `p` macro."
|
||||
{:arglists '([name ?doc-string ?attr-map [params] ?prepost-map body])}
|
||||
[name & sigs]
|
||||
(let [[name [params & sigs]] (encore/name-with-attrs name sigs)
|
||||
prepost-map (when (and (map? (first sigs)) (next sigs)) (first sigs))
|
||||
body (if prepost-map (next sigs) sigs)]
|
||||
`(defn ~name ~params ~(or prepost-map {})
|
||||
(pspy ~(clojure.core/name name)
|
||||
~@body))))
|
||||
;;;;
|
||||
|
||||
(comment (defnp foo "Docstring "[x] "boo" (* x x))
|
||||
(macroexpand '(defnp foo "Docstring "[x] "boo" (* x x)))
|
||||
(profile :info :defnp-test (foo 5)))
|
||||
(defmacro defnp "Like `defn` but wraps fn bodies with `p` macro."
|
||||
{:arglists
|
||||
'([name doc-string? attr-map? [params*] prepost-map? body]
|
||||
[name doc-string? attr-map? ([params*] prepost-map? body)+ attr-map?])}
|
||||
[name' & sigs]
|
||||
(let [[name' sigs] (encore/name-with-attrs name' sigs)
|
||||
single-arity? (vector? (first sigs))
|
||||
[sigs func->str]
|
||||
(if single-arity?
|
||||
[(list sigs) (fn [name' _params] (name name'))]
|
||||
[sigs (fn [name' params] (str (name name') \_ (count params)))])
|
||||
|
||||
new-sigs
|
||||
(map (fn [[params & others]]
|
||||
(let [has-prepost-map? (and (map? (first others)) (next others))
|
||||
[prepost-map & body]
|
||||
(if has-prepost-map?
|
||||
others
|
||||
(cons {} others))]
|
||||
`(~params ~prepost-map (pspy ~(func->str name' params) ~@body))))
|
||||
sigs)]
|
||||
`(defn ~name' ~@new-sigs)))
|
||||
|
||||
(comment
|
||||
(defnp foo "Docstring "[x] "boo" (* x x))
|
||||
(macroexpand '(defnp foo "Docstring" [x] "boo" (* x x)))
|
||||
(macroexpand '(defnp foo "Docstring" ([x] (* x x))
|
||||
([x y] (* x y))))
|
||||
(profile :info :defnp-test (foo 5)))
|
||||
|
||||
;;;;
|
||||
|
||||
(comment
|
||||
(profile :info :sleepy-threads
|
||||
|
|
Loading…
Reference in New Issue