diff --git a/src/taoensso/telemere.cljc b/src/taoensso/telemere.cljc index 580aaaa..b498c97 100644 --- a/src/taoensso/telemere.cljc +++ b/src/taoensso/telemere.cljc @@ -10,8 +10,7 @@ [taoensso.encore :as enc :refer [have have?]] [taoensso.encore.signals :as sigs] [taoensso.telemere.impl :as impl] - #?(:clj [taoensso.telemere.streams :as streams]) - + #?(:clj [taoensso.telemere.streams :as streams]) #?(:clj [clj-commons.format.exceptions :as fmt-ex]) #?(:clj [clj-commons.ansi :as fmt-ansi]))) @@ -76,7 +75,7 @@ impl/msg-splice impl/msg-skip - #?(:clj impl/with-signal) + #?(:clj impl/with-signals) #?(:clj impl/signal!)) ;;;; Context diff --git a/src/taoensso/telemere/impl.cljc b/src/taoensso/telemere/impl.cljc index cd48c11..b7f7591 100644 --- a/src/taoensso/telemere/impl.cljc +++ b/src/taoensso/telemere/impl.cljc @@ -76,7 +76,7 @@ uid-form)))) (comment - (enc/qb 1e6 ; [164.72 184.51 301.8 539.49] + (enc/qb 1e6 ; [161.36 184.69 274.53 468.67] (enc/uuid) (enc/uuid-str) (enc/nanoid) @@ -84,11 +84,32 @@ ;;;; Messages -(deftype MsgSplice [args]) (deftype MsgSkip []) +(deftype MsgSplice [args]) -(defn ^:public msg-splice "TODO Docstring" [args] (MsgSplice. args)) -(defn ^:public msg-skip "TODO Docstring" [] (MsgSkip.)) +(def ^:public msg-skip + "For use within signal message vectors. + Special value that will be ignored (no-op) when creating message. + Useful for conditionally skipping parts of message content, etc.: + + (signal! {:msg [\"Hello\" (if msg-skip) \"world\"] <...>}) or + (log! [\"Hello\" (if msg-skip) \"world\"]), etc. + + %> {:msg_ \"Hello world\" <...>}" + + (MsgSkip.)) + +(defn ^:public msg-splice + "For use within signal message vectors. + Wraps given arguments so that they're spliced when creating message. + Useful for conditionally splicing in extra message content, etc.: + + (signal! {:msg [(when (msg-splice [\"Username:\" \"Steve\"])) <...>]}) or + (log! [(when (msg-splice [\"Username:\" \"Steve\"]))]) + + %> {:msg_ \"Username: Steve\"}" + + [args] (MsgSplice. args)) (let [;; xform (map #(if (nil? %) "nil" %)) xform @@ -108,15 +129,21 @@ ([acc in] (rf* acc in)))))] (defn signal-msg - "Returns string formed by joining all args without separator, - rendering nils as \"nil\"." + "Returns string formed by joining all args with \" \" separator, + rendering nils as \"nil\". Supports `msg-skip`, `msg-splice`. + + API intended to be usefully different to `str`: + - `str`: no spacers, skip nils, no splicing + - `signal-msg`: auto spacers, show nils, opt-in splicing" + {:tag #?(:clj 'String :cljs 'string)} - [args] (enc/str-join nil xform args))) + [args] (enc/str-join " " xform args))) (comment - (enc/qb 2e6 ; [280.29 408.3] - (str "a" "b" "c" nil :kw) - (signal-msg ["a" "b" "c" nil :kw (msg-splice ["d" "e"])]))) + (enc/qb 2e6 ; [305.61 625.35] + (str "a" "b" "c" nil :kw) ; "abc:kw" + (signal-msg ["a" "b" "c" nil :kw (msg-splice ["d" "e"])]) ; "a b c nil :kw d e" + )) #?(:clj (defn- parse-msg-form [msg-form] @@ -195,60 +222,71 @@ ;;;; Handlers -(enc/defonce ^:dynamic *sig-spy* "To support `with-signal`" nil) -(enc/defonce ^:dynamic *sig-handlers* "?[]" nil) +(enc/defonce ^:dynamic *sig-spy* "To support `with-signals`" nil) +(enc/defonce ^:dynamic *sig-handlers* "?[]" nil) -(defn -with-signal - "Private util to support `with-signal` macro." +(defn- force-msg [sig] + (if-not (map? sig) + sig + (if-let [e (find sig :msg_)] + (assoc sig :msg_ (force (val e))) + (do sig)))) + +(defn -with-signals + "Private util to support `with-signals` macro." [form-fn - {:keys [return trap-errors? stop-propagation? force-msg?] - :or {return :vec}}] + {:keys [handle? force-msg? trap-errors?] + :or {handle? true}}] - (let [sv_ (volatile! nil)] - (binding [*sig-spy* [sv_ stop-propagation?]] + (let [sigs_ (volatile! nil)] + (binding [*sig-spy* [sigs_ (not handle?)]] (let [form-result - (if trap-errors? - (enc/try* {:okay (form-fn)} (catch :any t t {:error t})) - (do (form-fn))) + (if-not trap-errors? + (form-fn) + (enc/try* + (do [(form-fn) nil]) + (catch :any t t [nil t])))] - signal - (when-let [sv @sv_] - (if-not force-msg? - sv - (if-let [e (find sv :msg_)] - (assoc sv :msg_ (force (val e))) - (do sv))))] - - (case return - :vec [form-result signal] - :form-result form-result - :signal signal - (enc/unexpected-arg! - {:context `with-signal - :param 'return - :expected #{:vec :form-result :signal}})))))) + [form-result + (when-let [sigs @sigs_] + (if force-msg? + (mapv force-msg sigs) + (do sigs)))])))) #?(:clj - (defmacro ^:public with-signal - "Util for tests/debugging. - Executes given form and returns [ ]. - If `trap-errors?` is true, form result will be wrapped by {:keys [okay error]}." + (defmacro ^:public with-signals + "Executes given form and records any signals triggered by it. + Return value depends on options. Useful for tests/debugging. + + Options: + + `trap-errors?` + If true: returns [[form-value form-error] signals], trapping any form error. + If false: returns [ form-value signals], throwing on form error. + Default: false. + + `handle?` + Should registered handlers receive signals triggered by form, as usual? + Default: true. + + `force-msg?` + Should delayed `:msg_` fields in signals be replaced with realized strings? + Default: false." {:arglists - '([form] - [{:keys [return trap-errors? stop-propagation? force-msg?]} - form])} + '([ form] + [{:keys [handle? force-msg? trap-errors?]} form])} - ([ form] `(-with-signal (fn [] ~form) nil)) - ([opts form] `(-with-signal (fn [] ~form) ~opts)))) + ([ form] `(-with-signals (fn [] ~form) nil)) + ([opts form] `(-with-signals (fn [] ~form) ~opts)))) (defn dispatch-signal! - "Dispatches given signal to registered handlers, supports `with-signal`." + "Dispatches given signal to registered handlers, supports `with-signals`." [signal] (or - (when-let [[v stop-propagation?] *sig-spy*] - (vreset! v (sigs/signal-value signal nil)) - stop-propagation?) + (when-let [[sigs_ skip-handlers?] *sig-spy*] + (vswap! sigs_ #(conj (or % []) (sigs/signal-value signal nil))) + skip-handlers?) (sigs/call-handlers! *sig-handlers* signal))) @@ -407,10 +445,13 @@ - Mention ability to delay-wrap :data - Mention combo `:sample-rate` stuff (call * handler) + - Document Signal fields + - Link to signal-flow diagram + - If :run => returns body run-result (re-throwing) Otherwise returns true iff call allowed - [1] Ref. " + [1] Ref. " {:arglists (signal-arglists :signal!)} [opts] (have? map? opts) ; We require const map keys, but vals may require eval @@ -518,7 +559,7 @@ true)))))))) (comment - (with-signal (signal! {:level :warn :let [x :x] :msg ["Test" "message" x] :data {:a :A :x x} :run (+ 1 2)})) + (with-signals (signal! {:level :warn :let [x :x] :msg ["Test" "message" x] :data {:a :A :x x} :run (+ 1 2)})) (macroexpand '(signal! {:level :warn :let [x :x] :msg ["Test" "message" x] :data {:a :A :x x} :run (+ 1 2)})) (do @@ -564,9 +605,9 @@ (defn test-interop! [msg test-fn] (let [msg (str "Interop test: " msg " (" (enc/uuid-str) ")") - signal + [_ [signal]] (binding [*rt-sig-filter* nil] ; without runtime filters - (-with-signal (fn [] (test-fn msg)) - {:stop-propagation? true, :return :signal}))] + (-with-signals (fn [] (test-fn msg)) + {:handle? false}))] (= (force (get signal :msg_)) msg))) diff --git a/src/taoensso/telemere/streams.clj b/src/taoensso/telemere/streams.clj index 472550e..4a16e7d 100644 --- a/src/taoensso/telemere/streams.clj +++ b/src/taoensso/telemere/streams.clj @@ -71,7 +71,7 @@ *err* (if-let [err# ~err] (osw (telemere-print-stream err#)) *err*)] ~form))) -(comment (impl/with-signal (with-out->telemere (println "hello")))) +(comment (impl/with-signals (with-out->telemere (println "hello")))) (enc/defonce ^:private orig-out_ "Original `System/out`, or nil" (atom nil)) (enc/defonce ^:private orig-err_ "Original `System/err`, or nil" (atom nil)) diff --git a/test/taoensso/telemere_tests.cljc b/test/taoensso/telemere_tests.cljc index 5a2cc3d..05b2123 100644 --- a/test/taoensso/telemere_tests.cljc +++ b/test/taoensso/telemere_tests.cljc @@ -10,7 +10,7 @@ #?(:cljs (:require-macros - [taoensso.telemere-tests :refer [sig! ws ws*]]))) + [taoensso.telemere-tests :refer [sig! ws ws! ws1]]))) (comment (remove-ns 'taoensso.telemere-tests) @@ -22,15 +22,15 @@ #?(:clj {:alias sig! :src impl/signal!}) #?(:default {:alias sm? :src enc/submap?})) -#?(:clj (defmacro ws [form] `(impl/-with-signal (fn [] ~form) {}))) -#?(:clj (defmacro ws* [form] `(impl/-with-signal (fn [] ~form) {:trap-errors? true}))) -#?(:clj (defmacro wsv [form] `(impl/-with-signal (fn [] ~form) {:force-msg? true, :return :signal}))) +#?(:clj + (do + (defmacro ws [form] `(impl/-with-signals (fn [] ~form) {})) + (defmacro ws! [form] `(impl/-with-signals (fn [] ~form) {:trap-errors? true})) + (defmacro ws1 [form] `(let [[_# [s1#]] (impl/-with-signals (fn [] ~form) {:force-msg? true})] s1#)))) (do - (def ex1 (ex-info "TestEx" {})) - (def ex1? #(= % ex1)) - (def ex1-rv? #(= (:error %) ex1)) - (def ex1-pred (enc/pred ex1?))) + (def ex1 (ex-info "TestEx" {})) + (def ex1-pred (enc/pred #(= % ex1)))) (def ^:dynamic *dynamic-var* nil) @@ -47,11 +47,11 @@ ;; Note lots of low-level signal/filtering tests in `taoensso.encore` [(is (= (impl/signal-msg ["x" "y" nil ["z1" nil "z2" "z3"] - (impl/msg-splice ["s1" nil "s2" "s3" (impl/msg-skip) "s4"]) + (impl/msg-splice ["s1" nil "s2" "s3" impl/msg-skip "s4"]) (impl/msg-splice nil) - (impl/msg-skip) :kw]) + impl/msg-skip :kw]) - "xynil[\"z1\" nil \"z2\" \"z3\"]s1nils2s3s4:kw"))]) + "x y nil [\"z1\" nil \"z2\" \"z3\"] s1 nil s2 s3 s4 :kw"))]) (deftest _signal-macro [(is (= (ws (sig! {:level :info, :elide? true })) [nil nil]) "With compile-time elision") @@ -62,25 +62,25 @@ (is (->> (sig! {:level :info, :elide? true, :run (throw ex1)}) (throws? :ex-info "TestEx")) "With compile-time elision, throwing run-form") (is (->> (sig! {:level :info, :allow? false, :run (throw ex1)}) (throws? :ex-info "TestEx")) "With runtime suppression, throwing run-form") - (let [[rv1 sv1] (ws (sig! {:level :info })) - [rv2 sv2] (ws (sig! {:level :info, :run (+ 1 2)}))] + (let [[rv1 [sv1]] (ws (sig! {:level :info })) + [rv2 [sv2]] (ws (sig! {:level :info, :run (+ 1 2)}))] [(is (= rv1 true)) (is (sm? sv1 {:ns "taoensso.telemere-tests", :level :info, :run-form nil, :run-value nil, :runtime-nsecs nil})) (is (= rv2 3)) (is (sm? sv2 {:ns "taoensso.telemere-tests", :level :info, :run-form '(+ 1 2), :run-value 3, :runtime-nsecs (enc/pred nat-int?)}))]) (testing "Nested signals" - (let [[[inner-rv inner-sv] outer-sv] (ws (sig! {:level :info, :run (ws (sig! {:level :warn, :run "inner-run"}))}))] + (let [[[inner-rv [inner-sv]] [outer-sv]] (ws (sig! {:level :info, :run (ws (sig! {:level :warn, :run "inner-run"}))}))] [(is (= inner-rv "inner-run")) (is (sm? inner-sv {:level :warn, :run-value "inner-run"})) - (is (sm? outer-sv {:level :info :run-value [inner-rv inner-sv]}))])) + (is (sm? outer-sv {:level :info :run-value [inner-rv [inner-sv]]}))])) (testing "Instants" - (let [[_ sv1] (ws (sig! {:level :info })) - [_ sv2] (ws (sig! {:level :info, :run (reduce + (range 1e6))})) - [_ sv3] (ws (sig! {:level :info, :run (reduce + (range 1e6)) - :instant ; Allow custom instant - #?(:clj java.time.Instant/EPOCH - :cljs (js/Date. 0))}))] + (let [[_ [sv1]] (ws (sig! {:level :info })) + [_ [sv2]] (ws (sig! {:level :info, :run (reduce + (range 1e6))})) + [_ [sv3]] (ws (sig! {:level :info, :run (reduce + (range 1e6)) + :instant ; Allow custom instant + #?(:clj java.time.Instant/EPOCH + :cljs (js/Date. 0))}))] [(let [{start :instant, end :end-instant} sv1] [(is (enc/inst? start)) @@ -100,34 +100,34 @@ (is (< (inst-ms end) 1e6) "End instant is start + runtime-nsecs")])])) (testing "User opts assoced directly to signal" - (let [[rv sv] (ws (sig! {:level :info, :my-opt1 "v1", :my-opt2 "v2"}))] - (is (sm? sv {:level :info, :my-opt1 "v1", :my-opt2 "v2"})))) + (let [[rv [sv]] (ws (sig! {:level :info, :my-opt1 "v1", :my-opt2 "v2"}))] + (is (sm? sv {:level :info, :my-opt1 "v1", :my-opt2 "v2"})))) (testing "`:msg` basics" - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), :msg "msg1"})) ; No delay - [rv2 sv2] (ws (sig! {:level :info, :run (c), :msg [ "msg2:" (c)]})) ; Auto delay - [rv3 sv3] (ws (sig! {:level :info, :run (c), :msg (delay (str "msg3:" (c)))})) ; Manual delay - [rv4 sv4] (ws (sig! {:level :info, :run (c), :msg (str "msg4:" (c))})) ; No delay - [rv5 sv5] (ws (sig! {:level :info, :run (c), :msg (str "msg5:" (c)), :allow? false}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), :msg "msg1"})) ; No delay + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), :msg [ "msg2:" (c)]})) ; Auto delay + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), :msg (delay (str "msg3: " (c)))})) ; Manual delay + [rv4 [sv4]] (ws (sig! {:level :info, :run (c), :msg (str "msg4: " (c))})) ; No delay + [rv5 [sv5]] (ws (sig! {:level :info, :run (c), :msg (str "msg5: " (c)), :allow? false}))] [(is (= rv1 0)) (is (= (:msg_ sv1) "msg1")) - (is (= rv2 1)) (is (= @(:msg_ sv2) "msg2:6")) - (is (= rv3 2)) (is (= @(:msg_ sv3) "msg3:7")) - (is (= rv4 3)) (is (= (:msg_ sv4) "msg4:4")) + (is (= rv2 1)) (is (= @(:msg_ sv2) "msg2: 6")) + (is (= rv3 2)) (is (= @(:msg_ sv3) "msg3: 7")) + (is (= rv4 3)) (is (= (:msg_ sv4) "msg4: 4")) (is (= rv5 5)) (is (= (:msg_ sv5) nil)) (is (= @c 8) "5x run + 3x message (1x suppressed)")])) (testing "`:data` basics" (vec (for [dk [:data :my-opt]] ; User opts share same behaviour as data - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), dk {:c1 (c)}})) - [rv2 sv2] (ws (sig! {:level :info, :run (c), dk (delay {:c2 (c)})})) - [rv3 sv3] (ws (sig! {:level :info, :run (c), dk {:c3 (c)}, :allow? false})) - [rv4 sv4] (ws (sig! {:level :info, :run (c), dk (delay {:c4 (c)}), :allow? false})) - [rv5 sv5] (ws (sig! {:level :info, :run (c), dk [:c5 (c)]})) - [rv6 sv6] (ws (sig! {:level :info, :run (c), dk (delay [:c6 (c)])}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), dk {:c1 (c)}})) + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), dk (delay {:c2 (c)})})) + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), dk {:c3 (c)}, :allow? false})) + [rv4 [sv4]] (ws (sig! {:level :info, :run (c), dk (delay {:c4 (c)}), :allow? false})) + [rv5 [sv5]] (ws (sig! {:level :info, :run (c), dk [:c5 (c)]})) + [rv6 [sv6]] (ws (sig! {:level :info, :run (c), dk (delay [:c6 (c)])}))] [(is (= rv1 0)) (is (= (get sv1 dk) {:c1 1})) (is (= rv2 2)) (is (= (force (get sv2 dk)) {:c2 8})) @@ -138,10 +138,10 @@ (is (= @c 10) "6x run + 4x data (2x suppressed)")])))) (testing "`:let` basics" - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), :let [_ (c)]})) - [rv2 sv2] (ws (sig! {:level :info, :run (c), :let [_ (c)], :allow? false})) - [rv3 sv3] (ws (sig! {:level :info, :run (c), :let [_ (c)]}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), :let [_ (c)]})) + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), :let [_ (c)], :allow? false})) + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), :let [_ (c)]}))] [(is (= rv1 0)) (is (= rv2 2)) @@ -149,30 +149,30 @@ (is (= @c 5) "3x run + 2x let (1x suppressed)")])) (testing "`:let` + `:msg`" - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg "msg1"})) ; No delay - [rv2 sv2] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg [ "msg2:" n ":" (c)]})) ; Auto delay - [rv3 sv3] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (delay (str "msg3:" n ":" (c)))})) ; Manual delay - [rv4 sv4] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (str "msg4:" n ":" (c))})) ; No delay - [rv5 sv5] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (str "msg5:" n ":" (c)), :allow? false}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg "msg1"})) ; No delay + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg [ "msg2:" n (c)]})) ; Auto delay + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (delay (str "msg3: " n " " (c)))})) ; Manual delay + [rv4 [sv4]] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (str "msg4: " n " " (c))})) ; No delay + [rv5 [sv5]] (ws (sig! {:level :info, :run (c), :let [n (c)], :msg (str "msg5: " n " " (c)), :allow? false}))] [(is (= rv1 0)) (is (= (:msg_ sv1) "msg1")) - (is (= rv2 2)) (is (= @(:msg_ sv2) "msg2:3:10")) - (is (= rv3 4)) (is (= @(:msg_ sv3) "msg3:5:11")) - (is (= rv4 6)) (is (= (:msg_ sv4) "msg4:7:8")) + (is (= rv2 2)) (is (= @(:msg_ sv2) "msg2: 3 10")) + (is (= rv3 4)) (is (= @(:msg_ sv3) "msg3: 5 11")) + (is (= rv4 6)) (is (= (:msg_ sv4) "msg4: 7 8")) (is (= rv5 9)) (is (= (:msg_ sv5) nil)) (is (= @c 12) "5x run + 4x let (1x suppressed) + 3x msg (1x suppressed)")])) (testing "`:do` + `:let` + `:data`/`:my-opt`" (vec (for [dk [:data :my-opt]] - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk {:n n, :c1 (c)}})) - [rv2 sv2] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay {:n n, :c2 (c)})})) - [rv3 sv3] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk {:n n, :c3 (c)}, :allow? false})) - [rv4 sv4] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay {:n n, :c4 (c)}), :allow? false})) - [rv5 sv5] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk [:n n, :c5 (c)]})) - [rv6 sv6] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay [:n n, :c6 (c)])}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk {:n n, :c1 (c)}})) + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay {:n n, :c2 (c)})})) + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk {:n n, :c3 (c)}, :allow? false})) + [rv4 [sv4]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay {:n n, :c4 (c)}), :allow? false})) + [rv5 [sv5]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk [:n n, :c5 (c)]})) + [rv6 [sv6]] (ws (sig! {:level :info, :run (c), :do (c), :let [n (c)], dk (delay [:n n, :c6 (c)])}))] [(is (= rv1 0)) (is (= (get sv1 dk) {:n 2, :c1 3})) (is (= rv2 4)) (is (= (force (get sv2 dk)) {:n 6, :c2 16})) @@ -185,13 +185,13 @@ (testing "Manual `let` (unconditional) + `:data`/`:my-opt`" (vec (for [dk [:data :my-opt]] - (let [c (enc/counter) - [rv1 sv1] (ws (let [n (c)] (sig! {:level :info, :run (c), dk {:n n, :c1 (c)}}))) - [rv2 sv2] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay {:n n, :c2 (c)})}))) - [rv3 sv3] (ws (let [n (c)] (sig! {:level :info, :run (c), dk {:n n, :c3 (c)}, :allow? false}))) - [rv4 sv4] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay {:n n, :c4 (c)}), :allow? false}))) - [rv5 sv5] (ws (let [n (c)] (sig! {:level :info, :run (c), dk [:n n, :c5 (c)]}))) - [rv6 sv6] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay [:n n, :c6 (c)])})))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk {:n n, :c1 (c)}}))) + [rv2 [sv2]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay {:n n, :c2 (c)})}))) + [rv3 [sv3]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk {:n n, :c3 (c)}, :allow? false}))) + [rv4 [sv4]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay {:n n, :c4 (c)}), :allow? false}))) + [rv5 [sv5]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk [:n n, :c5 (c)]}))) + [rv6 [sv6]] (ws (let [n (c)] (sig! {:level :info, :run (c), dk (delay [:n n, :c6 (c)])})))] [(is (= rv1 1)) (is (= (get sv1 dk) {:n 0, :c1 2})) (is (= rv2 4)) (is (= (force (get sv2 dk)) {:n 3, :c2 14})) @@ -202,11 +202,11 @@ (is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")])))) (testing "Call middleware" - (let [c (enc/counter) - [rv1 sv1] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))]})) - [rv2 sv2] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))], :allow? false})) - [rv3 sv3] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))]})) - [rv4 sv4] (ws (sig! {:level :info, :middleware [(fn [_] "signal-value")]}))] + (let [c (enc/counter) + [rv1 [sv1]] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))]})) + [rv2 [sv2]] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))], :allow? false})) + [rv3 [sv3]] (ws (sig! {:level :info, :run (c), :middleware [#(assoc % :m1 (c)) #(assoc % :m2 (c))]})) + [rv4 [sv4]] (ws (sig! {:level :info, :middleware [(fn [_] "signal-value")]}))] [(is (= rv1 0)) (is (sm? sv1 {:m1 1 :m2 2})) (is (= rv2 3)) (is (nil? sv2)) @@ -331,33 +331,33 @@ (is (= (tel/with-ctx "my-ctx1" (tel/with-ctx+ (fn [old] [old "my-ctx2"]) tel/*ctx*)) ["my-ctx1" "my-ctx2"]) "fn update => apply") (is (= (tel/with-ctx {:a :A1 :b :B1} (tel/with-ctx+ {:a :A2 :c :C2} tel/*ctx*)) {:a :A2 :b :B1 :c :C2}) "map update => merge") - (let [[_ sig] (ws (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sig {:ctx "my-ctx"}) "Can be set via call opt"))])) + (let [[_ [sv]] (ws (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt"))])) (deftest _tracing (testing "Tracing" - [(let [[_ sv] (ws (sig! {:level :info }))] (is (sm? sv {:parent nil}))) - (let [[_ sv] (ws (sig! {:level :info, :parent {:id :id0}}))] (is (sm? sv {:parent {:id :id0 :uid :submap/nx}}) "`:parent/id` can be set via call opt")) - (let [[_ sv] (ws (sig! {:level :info, :parent {:uid :uid0}}))] (is (sm? sv {:parent {:id :submap/nx :uid :uid0}}) "`:parent/uid` can be set via call opt")) + [(let [[_ [sv]] (ws (sig! {:level :info }))] (is (sm? sv {:parent nil}))) + (let [[_ [sv]] (ws (sig! {:level :info, :parent {:id :id0}}))] (is (sm? sv {:parent {:id :id0 :uid :submap/nx}}) "`:parent/id` can be set via call opt")) + (let [[_ [sv]] (ws (sig! {:level :info, :parent {:uid :uid0}}))] (is (sm? sv {:parent {:id :submap/nx :uid :uid0}}) "`:parent/uid` can be set via call opt")) (testing "Auto call id, uid" - (let [[_ sv] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :run impl/*trace-parent*, :data impl/*trace-parent*}))] + (let [[_ [sv]] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :run impl/*trace-parent*, :data impl/*trace-parent*}))] [(is (sm? sv {:parent {:id :id0, :uid :uid0}})) (is (sm? sv {:run-value {:id nil, :uid (get sv :uid ::nx)}}) "`*trace-parent*` visible to run-form, bound to call's auto {:keys [id uid]}") (is (sm? sv {:data nil}) "`*trace-parent*` not visible to data-form ")])) (testing "Manual call id, uid" - (let [[_ sv] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :id :id1, :uid :uid1, :run impl/*trace-parent*, :data impl/*trace-parent*}))] + (let [[_ [sv]] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :id :id1, :uid :uid1, :run impl/*trace-parent*, :data impl/*trace-parent*}))] [(is (sm? sv {:parent {:id :id0, :uid :uid0}})) (is (sm? sv {:run-value {:id :id1, :uid :uid1}}) "`*trace-parent*` visible to run-form, bound to call's auto {:keys [id uid]}") (is (sm? sv {:data nil}) "`*trace-parent*` not visible to data-form ")])) (testing "Tracing can be disabled via call opt" - (let [[_ sv] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :id :id1, :uid :uid1, :run impl/*trace-parent*, :data impl/*trace-parent*, :trace? false}))] + (let [[_ [sv]] (ws (sig! {:level :info, :parent {:id :id0, :uid :uid0}, :id :id1, :uid :uid1, :run impl/*trace-parent*, :data impl/*trace-parent*, :trace? false}))] [(is (sm? sv {:parent {:id :id0, :uid :uid0}})) (is (sm? sv {:run-value nil}))])) (testing "Signal nesting" - (let [[[inner-rv inner-sv] outer-sv] + (let [[[inner-rv [inner-sv]] [outer-sv]] (ws (sig! { :level :info, :id :id1, :uid :uid1, :run (ws (sig! {:level :info, :id :id2, :uid :uid2, :run impl/*trace-parent*}))}))] @@ -405,47 +405,47 @@ (is (= (impl/signal-opts :msg, :level, {:level :info} :warn "msg") {:defaults {:level :info}, :msg "msg", :level :warn}))])) (testing "log!" ; msg + ?level => allowed? - [(let [[rv sv] (ws (tel/log! "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :info}))]) - (let [[rv sv] (ws (tel/log! :warn "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :warn}))]) - (let [[rv sv] (ws (tel/log! {:level :warn} "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :warn}))]) - (let [[rv sv] (ws (tel/log! {:allow? false} "msg"))] [(is (= rv nil)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/log! "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :info}))]) + (let [[rv [sv]] (ws (tel/log! :warn "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :warn}))]) + (let [[rv [sv]] (ws (tel/log! {:level :warn} "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/ex, :msg_ "msg", :level :warn}))]) + (let [[rv [sv]] (ws (tel/log! {:allow? false} "msg"))] [(is (= rv nil)) (is (nil? sv))])]) (testing "event!" ; id + ?level => allowed? - [(let [[rv sv] (ws (tel/event! :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :info, :id :id1}))]) - (let [[rv sv] (ws (tel/event! :warn :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :warn, :id :id1}))]) - (let [[rv sv] (ws (tel/event! {:level :warn} :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :warn, :id :id1}))]) - (let [[rv sv] (ws (tel/event! {:allow? false} :id1))] [(is (= rv nil)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/event! :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :info, :id :id1}))]) + (let [[rv [sv]] (ws (tel/event! :warn :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :warn, :id :id1}))]) + (let [[rv [sv]] (ws (tel/event! {:level :warn} :id1))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/ex, :level :warn, :id :id1}))]) + (let [[rv [sv]] (ws (tel/event! {:allow? false} :id1))] [(is (= rv nil)) (is (nil? sv))])]) (testing "error!" ; error + ?id => error - [(let [[rv sv] (ws (tel/error! ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) - (let [[rv sv] (ws (tel/error! :id1 ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) - (let [[rv sv] (ws (tel/error! {:id :id1} ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) - (let [[rv sv] (ws (tel/error! {:allow? false} ex1))] [(is (= rv ex1)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/error! ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) + (let [[rv [sv]] (ws (tel/error! :id1 ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) + (let [[rv [sv]] (ws (tel/error! {:id :id1} ex1))] [(is (= rv ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) + (let [[rv [sv]] (ws (tel/error! {:allow? false} ex1))] [(is (= rv ex1)) (is (nil? sv))])]) (testing "trace!" ; run + ?id => run result (value or throw) - [(let [[rv sv] (ws (tel/trace! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id nil}))]) - (let [[rv sv] (ws (tel/trace! :id1 (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1}))]) - (let [[rv sv] (ws (tel/trace! {:id :id1} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1}))]) - (let [[rv sv] (ws* (tel/trace! :id1 (throw ex1)))] [(is (ex1-rv? rv)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1, :error ex1-pred}))]) - (let [[rv sv] (ws (tel/trace! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/trace! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id nil}))]) + (let [[rv [sv]] (ws (tel/trace! :id1 (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1}))]) + (let [[rv [sv]] (ws (tel/trace! {:id :id1} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1}))]) + (let [[[_ re] [sv]] (ws! (tel/trace! :id1 (throw ex1)))] [(is (= re ex1)) (is (sm? sv {:kind :trace, :line :submap/ex, :level :info, :id :id1, :error ex1-pred}))]) + (let [[rv [sv]] (ws (tel/trace! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) (testing "spy" ; run + ?level => run result (value or throw) - [(let [[rv sv] (ws (tel/spy! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :info}))]) - (let [[rv sv] (ws (tel/spy! :warn (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn}))]) - (let [[rv sv] (ws (tel/spy! {:level :warn} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn}))]) - (let [[rv sv] (ws* (tel/spy! :warn (throw ex1)))] [(is (ex1-rv? rv)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn, :error ex1-pred}))]) - (let [[rv sv] (ws (tel/spy! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/spy! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :info}))]) + (let [[rv [sv]] (ws (tel/spy! :warn (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn}))]) + (let [[rv [sv]] (ws (tel/spy! {:level :warn} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn}))]) + (let [[[_ re] [sv]] (ws! (tel/spy! :warn (throw ex1)))] [(is (= re ex1)) (is (sm? sv {:kind :spy, :line :submap/ex, :level :warn, :error ex1-pred}))]) + (let [[rv [sv]] (ws (tel/spy! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) (testing "catch->error!" ; form + ?id => run value or ?return - [(let [[rv sv] (ws (tel/catch->error! (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) - (let [[rv sv] (ws (tel/catch->error! (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) - (let [[rv sv] (ws (tel/catch->error! :id1 (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) - (let [[rv sv] (ws (tel/catch->error! {:id :id1} (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) - (let [[rv sv] (ws* (tel/catch->error! {:rethrow? true} (throw ex1)))] [(is (ex1-rv? rv)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) - (let [[rv sv] (ws (tel/catch->error! {:catch-val :foo} (throw ex1)))] [(is (= rv :foo)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) - (let [[rv sv] (ws (tel/catch->error! {:catch-val :foo} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) - (let [[rv sv] (ws (tel/catch->error! {:catch-val :foo ; Overrides `:rethrow?` - :rethrow? true} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) + [(let [[rv [sv]] (ws (tel/catch->error! (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) + (let [[rv [sv]] (ws (tel/catch->error! (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) + (let [[rv [sv]] (ws (tel/catch->error! :id1 (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) + (let [[rv [sv]] (ws (tel/catch->error! {:id :id1} (throw ex1)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id :id1}))]) + (let [[[_ re] [sv]] (ws! (tel/catch->error! {:rethrow? true} (throw ex1)))] [(is (= re ex1)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) + (let [[rv [sv]] (ws (tel/catch->error! {:catch-val :foo} (throw ex1)))] [(is (= rv :foo)) (is (sm? sv {:kind :error, :line :submap/ex, :level :error, :error ex1-pred, :id nil}))]) + (let [[rv [sv]] (ws (tel/catch->error! {:catch-val :foo} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) + (let [[rv [sv]] (ws (tel/catch->error! {:catch-val :foo ; Overrides `:rethrow?` + :rethrow? true} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) #?(:clj (testing "uncaught->error!" @@ -471,9 +471,9 @@ (deftest _interop [(testing "`clojure.tools.logging` -> Telemere" [(is (sm? (tel/check-interop) {:tools-logging {:present? true, :sending->telemere? true, :telemere-receiving? true}})) - (is (sm? (wsv (ctl/info "Hello" "x" "y")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y"})) - (is (sm? (wsv (ctl/warn "Hello" "x" "y")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y"})) - (is (sm? (wsv (ctl/error ex1 "An error")) {:level :error, :error ex1}) "Errors")]) + (is (sm? (ws1 (ctl/info "Hello" "x" "y")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y"})) + (is (sm? (ws1 (ctl/warn "Hello" "x" "y")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y"})) + (is (sm? (ws1 (ctl/error ex1 "An error")) {:level :error, :error ex1}) "Errors")]) (testing "Standard out/err streams -> Telemere" [(is (sm? (tel/check-interop) {:system/out {:sending->telemere? false, :telemere-receiving? false}, @@ -488,42 +488,42 @@ :system/err {:sending->telemere? false, :telemere-receiving? false}})) (is - (sm? (wsv (tel/with-out->telemere (println "Hello" "x" "y"))) + (sm? (ws1 (tel/with-out->telemere (println "Hello" "x" "y"))) {:level :info, :location nil, :ns nil, :kind :system/out, :msg_ "Hello x y"}))]) (testing "SLF4J -> Telemere" [(is (sm? (tel/check-interop) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}})) (let [^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "MyTelemereSLF4JLogger")] [(testing "Basics" - [(is (sm? (wsv (.info sl "Hello")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Legacy API: info basics") - (is (sm? (wsv (.warn sl "Hello")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Legacy API: warn basics") - (is (sm? (wsv (-> (.atInfo sl) (.log "Hello"))) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Fluent API: info basics") - (is (sm? (wsv (-> (.atWarn sl) (.log "Hello"))) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Fluent API: warn basics")]) + [(is (sm? (ws1 (.info sl "Hello")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Legacy API: info basics") + (is (sm? (ws1 (.warn sl "Hello")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Legacy API: warn basics") + (is (sm? (ws1 (-> (.atInfo sl) (.log "Hello"))) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Fluent API: info basics") + (is (sm? (ws1 (-> (.atWarn sl) (.log "Hello"))) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello"}) "Fluent API: warn basics")]) (testing "Message formatting" (let [msgp "X is {} and Y is {}", expected {:msg_ "X is x and Y is y", :data {:slf4j/args ["x" "y"]}}] - [(is (sm? (wsv (.info sl msgp "x" "y")) expected) "Legacy API: formatted message, raw args") - (is (sm? (wsv (-> (.atInfo sl) (.setMessage msgp) (.addArgument "x") (.addArgument "y") (.log))) expected) "Fluent API: formatted message, raw args")])) + [(is (sm? (ws1 (.info sl msgp "x" "y")) expected) "Legacy API: formatted message, raw args") + (is (sm? (ws1 (-> (.atInfo sl) (.setMessage msgp) (.addArgument "x") (.addArgument "y") (.log))) expected) "Fluent API: formatted message, raw args")])) - (is (sm? (wsv (-> (.atInfo sl) (.addKeyValue "k1" "v1") (.addKeyValue "k2" "v2") (.log))) {:data {:slf4j/kvs {"k1" "v1", "k2" "v2"}}}) "Fluent API: kvs") + (is (sm? (ws1 (-> (.atInfo sl) (.addKeyValue "k1" "v1") (.addKeyValue "k2" "v2") (.log))) {:data {:slf4j/kvs {"k1" "v1", "k2" "v2"}}}) "Fluent API: kvs") (testing "Markers" (let [m1 (slf4j/est-marker! "M1") m2 (slf4j/est-marker! "M2") cm (slf4j/est-marker! "Compound" "M1" "M2")] - [(is (sm? (wsv (.info sl cm "Hello")) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Legacy API: markers") - (is (sm? (wsv (-> (.atInfo sl) (.addMarker m1) (.addMarker cm) (.log))) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Fluent API: markers")])) + [(is (sm? (ws1 (.info sl cm "Hello")) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Legacy API: markers") + (is (sm? (ws1 (-> (.atInfo sl) (.addMarker m1) (.addMarker cm) (.log))) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Fluent API: markers")])) (testing "Errors" - [(is (sm? (wsv (.warn sl "An error" ^Throwable ex1)) {:level :warn, :error ex1}) "Legacy API: errors") - (is (sm? (wsv (-> (.atWarn sl) (.setCause ex1) (.log))) {:level :warn, :error ex1}) "Fluent API: errors")]) + [(is (sm? (ws1 (.warn sl "An error" ^Throwable ex1)) {:level :warn, :error ex1}) "Legacy API: errors") + (is (sm? (ws1 (-> (.atWarn sl) (.setCause ex1) (.log))) {:level :warn, :error ex1}) "Fluent API: errors")]) (testing "MDC (Mapped Diagnostic Context)" (with-open [_ (org.slf4j.MDC/putCloseable "k1" "v1")] (with-open [_ (org.slf4j.MDC/putCloseable "k2" "v2")] - [(is (sm? (wsv (-> sl (.info "Hello"))) {:level :info, :ctx {"k1" "v1", "k2" "v2"}}) "Legacy API: MDC") - (is (sm? (wsv (-> (.atInfo sl) (.log "Hello"))) {:level :info, :ctx {"k1" "v1", "k2" "v2"}}) "Fluent API: MDC")])))])])])) + [(is (sm? (ws1 (-> sl (.info "Hello"))) {:level :info, :ctx {"k1" "v1", "k2" "v2"}}) "Legacy API: MDC") + (is (sm? (ws1 (-> (.atInfo sl) (.log "Hello"))) {:level :info, :ctx {"k1" "v1", "k2" "v2"}}) "Fluent API: MDC")])))])])])) ;;;;