diff --git a/src/taoensso/telemere.cljc b/src/taoensso/telemere.cljc index 3c1eacd..4ad1061 100644 --- a/src/taoensso/telemere.cljc +++ b/src/taoensso/telemere.cljc @@ -18,15 +18,13 @@ #?(:cljs (:require-macros [taoensso.telemere :refer - [set-ctx! with-ctx with-ctx+ - set-middleware! with-middleware - - with-signal with-signals + [with-signal with-signals signal! event! log! trace! spy! catch->error! ;; Via `sigs/def-api` without-filters with-kind-filter with-ns-filter with-id-filter - with-min-level with-handler with-handler+]]))) + with-min-level with-handler with-handler+ + with-ctx with-ctx+ with-middleware]]))) (comment (remove-ns 'taoensso.telemere) @@ -83,82 +81,6 @@ (impl/defhelp help:signal-content :signal-content) (impl/defhelp help:environmental-config :environmental-config)) -;;;; Context - -(enc/defonce default-ctx - "Default root (base) value of `*ctx*` var. - Defaults to `nil`, controlled by: - (get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>) - - See `get-env` for details." - (enc/get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>)) - -(enc/def* ^:dynamic *ctx* - "Dynamic context: arbitrary user-level state attached as `:ctx` to all signals. - Value may be any type, but is usually nil or a map. - - Re/bind dynamic value using `with-ctx`, `with-ctx+`, or `binding`. - Modify root (base) value using `set-ctx!`. - Default root (base) value is `default-ctx`. - - Note that as with all dynamic Clojure vars, \"binding conveyance\" applies - when using futures, agents, etc. - - Tips: - - Value may be (or may contain) an atom if you want mutable semantics - - Value may be of form { } for custom scoping, etc." - default-ctx) - -#?(:clj - (defmacro set-ctx! - "Set `*ctx*` var's root (base) value. See `*ctx*` for details." - [root-ctx-val] `(enc/set-var-root! *ctx* ~root-ctx-val))) - -#?(:clj - (defmacro with-ctx - "Evaluates given form with given `*ctx*` value. See `*ctx*` for details." - [ctx-val form] `(binding [*ctx* ~ctx-val] ~form))) - -(comment (with-ctx "my-ctx" *ctx*)) - -#?(:clj - (defmacro with-ctx+ - "Evaluates given form with updated `*ctx*` value. - - `update-map-or-fn` may be: - - A map to merge with current `*ctx*` value, or - - A unary fn to apply to current `*ctx*` value - - See `*ctx*` for details." - [update-map-or-fn form] - `(binding [*ctx* (impl/update-ctx *ctx* ~update-map-or-fn)] - ~form))) - -(comment (with-ctx {:a :A1 :b :B1} (with-ctx+ {:a :A2} *ctx*))) - -;;;; Signal middleware - -(enc/defonce ^:dynamic *middleware* - "Optional (fn [signal]) => ?modified-signal to apply (once) when - signal is created. When middleware returns nil, skips all handlers. - - Compose multiple middleware fns together with `comp-middleware`. - - Re/bind dynamic value using `with-middleware`, `binding`. - Modify root (base) value using `set-middleware!`." - nil) - -#?(:clj - (defmacro set-middleware! - "Set `*middleware*` var's root (base) value. See `*middleware*` for details." - [?root-middleware-fn] `(enc/set-var-root! *middleware* ~?root-middleware-fn))) - -#?(:clj - (defmacro with-middleware - "Evaluates given form with given `*middleware*` value. - See `*middleware*` for details." - [?middleware-fn form] `(binding [*middleware* ~?middleware-fn] ~form))) - ;;;; Signal creators ;; - signal! [ opts] ; => allowed? / run result (value or throw) ;; - event! [id ] [id level-or-opts] ; id + ?level => allowed? ; Sole signal with descending main arg! diff --git a/src/taoensso/telemere/impl.cljc b/src/taoensso/telemere/impl.cljc index a9ba062..e7348e0 100644 --- a/src/taoensso/telemere/impl.cljc +++ b/src/taoensso/telemere/impl.cljc @@ -62,22 +62,6 @@ (comment (enc/get-env {:as :edn, :return :explain} :taoensso.telemere/rt-filters<.platform><.edn>)) -;;;; Context (optional arb app-level state) -;; taoensso.telemere/*ctx* - -(defn update-ctx - "Returns `new-ctx` given `old-ctx` and an update map or fn." - [old-ctx update-map-or-fn] - (enc/cond - (nil? update-map-or-fn) old-ctx - (map? update-map-or-fn) (enc/fast-merge old-ctx update-map-or-fn) ; Before ifn - (ifn? update-map-or-fn) (update-map-or-fn old-ctx) - :else - (enc/unexpected-arg! update-map-or-fn - {:context `update-ctx - :param 'update-map-or-fn - :expected '#{nil map fn}}))) - ;;;; Unique IDs (UIDs) (enc/def* nanoid-readable (enc/rand-id-fn {:chars :nanoid-readable, :len 23})) diff --git a/test/taoensso/telemere_tests.cljc b/test/taoensso/telemere_tests.cljc index b5580af..c20fe51 100644 --- a/test/taoensso/telemere_tests.cljc +++ b/test/taoensso/telemere_tests.cljc @@ -228,23 +228,37 @@ (is (= rv6 13)) (is (= (force (get sv6 dk)) [:n 12, :c6 15])) (is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")])))) + (testing "Binding conveyance" + (binding [*dynamic-var* :foo] + (is (sm? (with-sig (sig! {:level :info, :data {:dynamic-var *dynamic-var*}})) {:data {:dynamic-var :foo}})))) + + (testing "Dynamic context (`*ctx*`)" + (let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt"))) + + (testing "Dynamic middleware (`*middleware*`)" + [(is (sm? (tel/with-middleware nil (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity") + (is (sm? (tel/with-middleware identity (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity") + (is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info }))) {:level :info, :foo 1 })) + (is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info, :middleware #(assoc % :foo 2)}))) {:level :info, :foo 2 }) "call > dynamic") + (is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info, :middleware nil}))) {:level :info, :foo :submap/nx}) "call > dynamic") + (is (= (tel/with-middleware #(do nil) (with-sig (sig! {:level :info }))) nil) "return nil => suppress") + (is (sm? (tel/with-middleware #(do nil) (with-sig (sig! {:level :info, :middleware nil}))) {:level :info}) "call > dynamic")]) + (testing "Call middleware" (let [c (enc/counter) [[rv1 _] [sv1]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) [[rv2 _] [sv2]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false})) [[rv3 _] [sv3]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) - [[rv4 _] [sv4]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] "signal-value")}))] + [[rv4 _] [sv4]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] "signal-value")})) + [[rv5 _] [sv5]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] nil)}))] [(is (= rv1 0)) (is (sm? sv1 {:m1 1 :m2 2})) (is (= rv2 3)) (is (nil? sv2)) (is (= rv3 4)) (is (sm? sv3 {:m1 5 :m2 6})) (is (= rv4 true)) (is (= sv4 "signal-value")) + (is (= rv5 true)) (is (nil? sv5)) (is (= @c 7) "3x run + 4x middleware")])) - (testing "Binding conveyance" - (binding [*dynamic-var* :foo] - (is (sm? (with-sig (sig! {:level :info, :data {:dynamic-var *dynamic-var*}})) {:data {:dynamic-var :foo}})))) - #?(:clj (testing "Printing" (let [sv1 (with-sig (sig! {:level :info, :run (+ 1 2), :my-k1 :my-v1})) @@ -398,17 +412,6 @@ (is (= @sv_ :nx)) (is (sm? @error_ {:handler-id :hid1, :error pex1?}))])])]))) -(deftest _ctx - (testing "Context (`*ctx*`)" - [(is (= (binding [tel/*ctx* "my-ctx"] tel/*ctx*) "my-ctx") "Supports manual `binding`") - (is (= (tel/with-ctx "my-ctx" tel/*ctx*) "my-ctx") "Supports any data type") - - (is (= (tel/with-ctx "my-ctx1" (tel/with-ctx+ nil tel/*ctx*)) "my-ctx1") "nil update => keep old-ctx") - (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 [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt"))])) - (deftest _tracing (testing "Tracing" [(let [sv (with-sig (sig! {:level :info }))] (is (sm? sv {:parent nil})))