Skip to content

Commit 0a8891f

Browse files
committed
Merge branch 'log-readably'
2 parents a5e31ee + 4be7af9 commit 0a8891f

2 files changed

Lines changed: 392 additions & 0 deletions

File tree

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
;; Copyright (c) Alex Taggart. All rights reserved. The use
2+
;; and distribution terms for this software are covered by the Eclipse
3+
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4+
;; which can be found in the file epl-v10.html at the root of this
5+
;; distribution. By using this software in any fashion, you are
6+
;; agreeing to be bound by the terms of this license. You must not
7+
;; remove this notice, or any other, from this software.
8+
9+
(ns ^{:author "Alex Taggart"
10+
:doc "Logging macros that support printing message arguments readably.
11+
12+
Examples:
13+
14+
(require '[clojure.tools.logging :as log]
15+
'[clojure.tools.logging.readable :as logr])
16+
17+
(def x \"bar\")
18+
; Logged as...
19+
(log/debug \"foo\" x \"baz\") ; foo bar baz
20+
(logr/debug \"foo\" x \"baz\") ; foo \"bar\" baz
21+
(log/debugf \"foo %s %s\" x \"baz\") ; foo bar baz
22+
(logr/debugf \"foo %s %s\" x \"baz\") ; foo \"bar\" \"baz\"
23+
"}
24+
clojure.tools.logging.readable
25+
(:require [clojure.tools.logging :as log]
26+
[clojure.tools.logging.impl :as impl]))
27+
28+
(defn- readable-print-args [args]
29+
(for [arg args]
30+
(if (string? arg)
31+
arg
32+
`(pr-str ~arg))))
33+
34+
(defmacro logp
35+
"Logs a message using print style args, where message args that are not
36+
literal strings will be printed readably. Can optionally take a throwable as
37+
its second arg. See level-specific macros, e.g., debug."
38+
{:arglists '([level message & more] [level throwable message & more])}
39+
[level x & more]
40+
; Why bind `*print-readably*` to true?
41+
; The `pr` functions do not bind `*print-readably*`, which defaults to true;
42+
; instead the `print` functions bind `*print-readably*` to nil, then invoke
43+
; `pr` functions.
44+
; As such, absent explicit binding, if this code happened to be invoked in a
45+
; context where `*print-readably*` was nil, then the non-string message args
46+
; passed to pr-str would still not be printed readably.
47+
(if (or (string? x) (nil? more)) ; optimize for non-exception case
48+
`(log/log ~level (binding [*print-readably* true]
49+
(print-str ~@(readable-print-args (cons x more)))))
50+
`(let [logger# (impl/get-logger log/*logger-factory* ~*ns*)]
51+
(if (impl/enabled? logger# ~level)
52+
(let [x# ~x]
53+
(if (instance? Throwable x#)
54+
(log/log* logger# ~level x#
55+
(binding [*print-readably* true]
56+
(print-str ~@(readable-print-args more))))
57+
(log/log* logger# ~level nil
58+
(binding [*print-readably* true]
59+
(print-str (pr-str x#) ; x is not a literal string, so pr-str x#
60+
~@(readable-print-args more))))))))))
61+
62+
(defn- readable-format-args [args]
63+
(for [arg args]
64+
`(pr-str ~arg)))
65+
66+
(defmacro logf
67+
"Logs a message using a format string and args, where all format args will be
68+
printed readably. Can optionally take a throwable as its second arg. See
69+
level-specific macros, e.g., debugf."
70+
{:arglists '([level fmt & fmt-args] [level throwable fmt & fmt-args])}
71+
[level x & more]
72+
(if (or (instance? String x) (nil? more)) ; optimize for non-exception case
73+
`(log/log ~level (binding [*print-readably* true]
74+
(format ~x ~@(readable-format-args more))))
75+
`(let [logger# (impl/get-logger log/*logger-factory* ~*ns*)]
76+
(if (impl/enabled? logger# ~level)
77+
(let [x# ~x]
78+
(if (instance? Throwable x#) ; type check only when enabled
79+
(log/log* logger# ~level x# (binding [*print-readably* true]
80+
(format ~(first more) ; not applied to the format string
81+
~@(readable-format-args (rest more)))))
82+
(log/log* logger# ~level nil (binding [*print-readably* true]
83+
(format x# ~@(readable-format-args more))))))))))
84+
85+
;; level-specific macros
86+
87+
(defmacro trace
88+
"Trace level logging using print-style args. See logp for details."
89+
{:arglists '([message & more] [throwable message & more])}
90+
[& args]
91+
`(logp :trace ~@args))
92+
93+
(defmacro debug
94+
"Debug level logging using print-style args. See logp for details."
95+
{:arglists '([message & more] [throwable message & more])}
96+
[& args]
97+
`(logp :debug ~@args))
98+
99+
(defmacro info
100+
"Info level logging using print-style args. See logp for details."
101+
{:arglists '([message & more] [throwable message & more])}
102+
[& args]
103+
`(logp :info ~@args))
104+
105+
(defmacro warn
106+
"Warn level logging using print-style args. See logp for details."
107+
{:arglists '([message & more] [throwable message & more])}
108+
[& args]
109+
`(logp :warn ~@args))
110+
111+
(defmacro error
112+
"Error level logging using print-style args. See logp for details."
113+
{:arglists '([message & more] [throwable message & more])}
114+
[& args]
115+
`(logp :error ~@args))
116+
117+
(defmacro fatal
118+
"Fatal level logging using print-style args. See logp for details."
119+
{:arglists '([message & more] [throwable message & more])}
120+
[& args]
121+
`(logp :fatal ~@args))
122+
123+
(defmacro tracef
124+
"Trace level logging using format. See logf for details."
125+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
126+
[& args]
127+
`(logf :trace ~@args))
128+
129+
(defmacro debugf
130+
"Debug level logging using format. See logf for details."
131+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
132+
[& args]
133+
`(logf :debug ~@args))
134+
135+
(defmacro infof
136+
"Info level logging using format. See logf for details."
137+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
138+
[& args]
139+
`(logf :info ~@args))
140+
141+
(defmacro warnf
142+
"Warn level logging using format. See logf for details."
143+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
144+
[& args]
145+
`(logf :warn ~@args))
146+
147+
(defmacro errorf
148+
"Error level logging using format. See logf for details."
149+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
150+
[& args]
151+
`(logf :error ~@args))
152+
153+
(defmacro fatalf
154+
"Fatal level logging using format. See logf for details."
155+
{:arglists '([fmt & fmt-args] [throwable fmt & fmt-args])}
156+
[& args]
157+
`(logf :fatal ~@args))
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
(ns clojure.tools.logging.test-readable
2+
(:use clojure.test)
3+
(:require
4+
[clojure.set :as set]
5+
[clojure.tools.logging.readable :refer :all]
6+
[clojure.tools.logging.test :as log-test :refer [logged? with-log]]))
7+
8+
(deftest logp-single-eval
9+
(with-log
10+
(let [cnt (atom 0)]
11+
(logp :debug (str (swap! cnt inc)))
12+
(logp :debug (str (swap! cnt inc)) :foo)
13+
(logp :debug (Exception. (str (swap! cnt inc))) (str (swap! cnt inc)))
14+
(logp :debug (Exception. (str (swap! cnt inc))) (str (swap! cnt inc)) :foo)
15+
(is (== 6 @cnt)))))
16+
17+
(deftest logf-single-eval
18+
(with-log
19+
(let [cnt (atom 0)]
20+
(logf :debug (str (swap! cnt inc)))
21+
(logf :debug (str (swap! cnt inc)) :foo)
22+
(logf :debug (Exception. (str (swap! cnt inc))) (str (swap! cnt inc)))
23+
(logf :debug (Exception. (str (swap! cnt inc))) (str (swap! cnt inc)) :foo)
24+
(is (== 6 @cnt)))))
25+
26+
(deftest logp-msg1
27+
(with-log
28+
(logp :debug "hello")
29+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello")))
30+
(with-log
31+
(let [hello "hello"]
32+
(logp :debug hello))
33+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\"")))
34+
(with-log
35+
(let [hello "hello"]
36+
(binding [*print-readably* nil]
37+
(logp :debug hello)))
38+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\"")))
39+
(with-log
40+
(logp :debug (pr-str "hello"))
41+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"\\\"hello\\\"\"")))
42+
(with-log
43+
(logp :debug (print-str "hello"))
44+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\""))))
45+
46+
(deftest logp-msg2
47+
(let [hello "hello"
48+
world "world"]
49+
(with-log
50+
(logp :debug "hello" "world")
51+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello world")))
52+
(with-log
53+
(logp :debug "hello" world)
54+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))
55+
(with-log
56+
(logp :debug hello "world")
57+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\" world")))
58+
(with-log
59+
(logp :debug hello world)
60+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\" \"world\"")))
61+
(with-log
62+
(binding [*print-readably* nil]
63+
(logp :debug hello world))
64+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\" \"world\"")))))
65+
66+
(deftest logp-ex0
67+
(let [e (Exception.)]
68+
(with-log
69+
(logp :debug e)
70+
(is (logged? "clojure.tools.logging.test-readable" :debug nil (print-str (pr-str e)))))
71+
(with-log
72+
(binding [*print-readably* nil]
73+
(logp :debug e))
74+
(is (logged? "clojure.tools.logging.test-readable" :debug nil (print-str (pr-str e)))))))
75+
76+
(deftest logp-ex1
77+
(let [e (Exception.)
78+
hello "hello"]
79+
(with-log
80+
(logp :debug e "hello")
81+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello")))
82+
(with-log
83+
(logp :debug e hello)
84+
(is (logged? "clojure.tools.logging.test-readable" :debug e "\"hello\"")))
85+
(with-log
86+
(binding [*print-readably* nil]
87+
(logp :debug e hello))
88+
(is (logged? "clojure.tools.logging.test-readable" :debug e "\"hello\"")))))
89+
90+
(deftest logp-ex2
91+
(let [e (Exception.)
92+
hello "hello"
93+
world "world"]
94+
(with-log
95+
(logp :debug e "hello" "world")
96+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello world")))
97+
(with-log
98+
(logp :debug e "hello" world)
99+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))
100+
(with-log
101+
(logp :debug e hello "world")
102+
(is (logged? "clojure.tools.logging.test-readable" :debug e "\"hello\" world")))
103+
(with-log
104+
(logp :debug e hello world)
105+
(is (logged? "clojure.tools.logging.test-readable" :debug e "\"hello\" \"world\"")))
106+
(with-log
107+
(binding [*print-readably* nil]
108+
(logp :debug e hello world))
109+
(is (logged? "clojure.tools.logging.test-readable" :debug e "\"hello\" \"world\"")))))
110+
111+
112+
(deftest logf-msg1
113+
(with-log
114+
(logf :debug "hello")
115+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello")))
116+
(with-log
117+
(let [hello "hello"]
118+
(logf :debug hello))
119+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello")))
120+
(with-log
121+
(let [hello "hello"]
122+
(binding [*print-readably* nil]
123+
(logf :debug hello)))
124+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello")))
125+
(with-log
126+
(logf :debug (pr-str "hello"))
127+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "\"hello\"")))
128+
(with-log
129+
(logf :debug (print-str "hello"))
130+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello"))))
131+
132+
(deftest logf-msg2
133+
(let [hello "hello %s"
134+
world "world"]
135+
(with-log
136+
(logf :debug "hello %s" "world")
137+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))
138+
(with-log
139+
(logf :debug "hello %s" world)
140+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))
141+
(with-log
142+
(logf :debug hello "world")
143+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))
144+
(with-log
145+
(logf :debug hello world)
146+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))
147+
(with-log
148+
(binding [*print-readably* nil]
149+
(logf :debug hello world))
150+
(is (logged? "clojure.tools.logging.test-readable" :debug nil "hello \"world\"")))))
151+
152+
(deftest logf-ex0
153+
(is (thrown? ClassCastException (logf :debug (Exception.)))))
154+
155+
(deftest logf-ex1
156+
(let [e (Exception.)
157+
hello "hello"]
158+
(with-log
159+
(logf :debug e "hello")
160+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello")))
161+
(with-log
162+
(logf :debug e hello)
163+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello")))
164+
(with-log
165+
(binding [*print-readably* nil]
166+
(logf :debug e hello))
167+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello")))))
168+
169+
(deftest logf-ex2
170+
(let [e (Exception.)
171+
hello "hello %s"
172+
world "world"]
173+
(with-log
174+
(logf :debug e "hello %s" "world")
175+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))
176+
(with-log
177+
(logf :debug e "hello %s" world)
178+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))
179+
(with-log
180+
(logf :debug e hello "world")
181+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))
182+
(with-log
183+
(logf :debug e hello world)
184+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))
185+
(with-log
186+
(binding [*print-readably* nil]
187+
(logf :debug e hello world))
188+
(is (logged? "clojure.tools.logging.test-readable" :debug e "hello \"world\"")))))
189+
190+
191+
(deftest println-style
192+
(are [f kw] (with-log
193+
(f "hello" "world")
194+
(logged? "clojure.tools.logging.test-readable" kw nil "hello world"))
195+
trace :trace
196+
debug :debug
197+
info :info
198+
warn :warn
199+
error :error
200+
fatal :fatal))
201+
202+
(deftest println-style-ex
203+
(let [e (Exception.)]
204+
(are [f kw] (with-log
205+
(f e "hello" "world")
206+
(logged? "clojure.tools.logging.test-readable" kw e "hello world"))
207+
trace :trace
208+
debug :debug
209+
info :info
210+
warn :warn
211+
error :error
212+
fatal :fatal)))
213+
214+
(deftest format-style
215+
(are [f kw] (with-log
216+
(f "%s %s" "hello" "world")
217+
(logged? "clojure.tools.logging.test-readable" kw nil "\"hello\" \"world\""))
218+
tracef :trace
219+
debugf :debug
220+
infof :info
221+
warnf :warn
222+
errorf :error
223+
fatalf :fatal))
224+
225+
(deftest format-style-ex
226+
(let [e (Exception.)]
227+
(are [f kw] (with-log
228+
(f e "%s %s" "hello" "world")
229+
(logged? "clojure.tools.logging.test-readable" kw e "\"hello\" \"world\""))
230+
tracef :trace
231+
debugf :debug
232+
infof :info
233+
warnf :warn
234+
errorf :error
235+
fatalf :fatal)))

0 commit comments

Comments
 (0)