From 7cccf672f511a47427b442363f02432185c7975e Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Mon, 10 Mar 2025 08:53:06 +0100 Subject: [PATCH] [mod] Rename "middleware" -> "transform" (xfn) Users caught by this change should receive a clear compile-time error. Apologies for the nuissance!! This change is part of a final review of names before the release of v1 final. Motivations: - "xfn" is a lot shorter than "middleware", making it more convenient to use at signal calls, compare: (log! {:middleware my-fn} "msg") (log! {:xfn my-fn} "msg"} - "middleware" was originally chosen to match Timbre's terminology, but actually carries some misleading connotations that in hindsight are probably better avoided while we still have the chance to change this. --- README.md | 13 ++- examples.cljc | 21 +++-- .../signal-docstrings/signal-content.txt | 4 +- .../signal-docstrings/signal-options.txt | 9 ++- main/src/taoensso/telemere.cljc | 6 +- main/src/taoensso/telemere/impl.cljc | 38 ++++----- main/src/taoensso/telemere/utils.cljc | 2 +- main/test/taoensso/telemere_tests.cljc | 80 +++++++++---------- wiki/1-Getting-started.md | 8 +- wiki/2-Architecture.md | 2 +- wiki/3-Config.md | 6 +- wiki/4-Handlers.md | 20 ++--- wiki/7-Tips.md | 14 ++-- wiki/8-Community.md | 4 +- 14 files changed, 113 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index f7fbfba..967bbe2 100644 --- a/README.md +++ b/README.md @@ -113,15 +113,14 @@ It enables you to write code that is **information-verbose by default**. ;; Set minimum level for `event!` signals for particular ns pattern (t/set-min-level! :event "taoensso.sente.*" :warn) -;; Use middleware to: -;; - Transform signals -;; - Filter signals by arb conditions (incl. data/content) +;; Use transforms (xfns) to filter and/or arbitrarily modify signals +;; by signal data/content/etc. -(t/set-middleware! +(t/set-xfn! (fn [signal] (if (-> signal :data :skip-me?) nil ; Filter signal (don't handle) - (assoc signal :passed-through-middleware? true)))) + (assoc signal :transformed? true)))) (t/with-signal (t/event! ::my-id {:data {:skip-me? true}})) ; => nil (t/with-signal (t/event! ::my-id {:data {:skip-me? false}})) ; => {...} @@ -251,7 +250,7 @@ Detailed help is available without leaving your IDE: | :---------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- | | [`help:signal-creators`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-creators) | Creating signals | | [`help:signal-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) | Options when creating signals | -| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal content (map given to middleware/handlers) | +| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal content (map given to transforms/handlers) | | [`help:filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:filters) | Signal filtering and transformation | | [`help:handlers`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handlers) | Signal handler management | | [`help:handler-dispatch-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handler-dispatch-options) | Signal handler dispatch options | @@ -314,7 +313,7 @@ You can also easily [write your own handlers](../../wiki/4-Handlers#writing-hand ## Community -My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, middleware, and utils. +My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, transforms, and utils. See [here](../../wiki/8-Community) for community resources. diff --git a/examples.cljc b/examples.cljc index 96c5eb2..d6639f9 100644 --- a/examples.cljc +++ b/examples.cljc @@ -59,15 +59,14 @@ ;; Set minimum level for `event!` signals for particular ns pattern (t/set-min-level! :event "taoensso.sente.*" :warn) -;; Use middleware to: -;; - Transform signals -;; - Filter signals by arb conditions (incl. data/content) +;; Use transforms (xfns) to filter and/or arbitrarily modify signals +;; by signal data/content/etc. -(t/set-middleware! +(t/set-xfn! (fn [signal] (if (-> signal :data :skip-me?) nil ; Filter signal (don't handle) - (assoc signal :passed-through-middleware? true)))) + (assoc signal :transformed? true)))) (t/with-signal (t/event! ::my-id {:data {:skip-me? true}})) ; => nil (t/with-signal (t/event! ::my-id {:data {:skip-me? false}})) ; => {...} @@ -333,16 +332,16 @@ (t/with-signal (t/event! ::my-id - {:my-middleware-data "foo" - :my-handler-data "bar"})) + {:my-data-for-xfn "foo" + :my-data-for-handler "bar"})) ;; %> ;; {;; App-level kvs included inline (assoc'd to signal root) -;; :my-middleware-data "foo" -;; :my-handler-data "bar" +;; :my-data-for-xfn "foo" +;; :my-data-for-handler "bar" ;; :kvs ; And also collected together under ":kvs" key -;; {:my-middleware-data "foo" -;; :my-handler-data "bar"} +;; {:my-data-for-xfn "foo" +;; :my-data-for-handler "bar"} ;; ... } ;;;; Misc extra examples diff --git a/main/resources/signal-docstrings/signal-content.txt b/main/resources/signal-docstrings/signal-content.txt index 74dd00e..85640a4 100644 --- a/main/resources/signal-docstrings/signal-content.txt +++ b/main/resources/signal-docstrings/signal-content.txt @@ -1,5 +1,5 @@ Signals are maps with {:keys [inst id ns level data msg_ ...]}, though they -can be modified by signal and/or handler middleware. +can be modified by call and/or handler transform (xfns). Default signal keys: @@ -33,7 +33,7 @@ Default signal keys: ---------- Other arb app-level ?kvs given to signal creator. Typically NOT included in handler output, so a great way to provide custom data/opts for use - (only) by custom middleware/handlers. + (only) by custom transforms/handlers. If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs! diff --git a/main/resources/signal-docstrings/signal-options.txt b/main/resources/signal-docstrings/signal-options.txt index c31f627..1d549b6 100644 --- a/main/resources/signal-docstrings/signal-options.txt +++ b/main/resources/signal-docstrings/signal-options.txt @@ -25,17 +25,18 @@ All options are available for all signal creator calls: `:coords` ------ Custom ?[line column] to override auto signal callsite info `:elidable?` --- Should signal be subject to compile-time elision? (Default: true) +`:trace?` ------ Should tracing be enabled for `:run` form? + `:sample-rate` - ?rate ∈ℝ[0,1] for signal sampling (0.75 => allow 75% of signals, nil => allow all) `:when` -------- Arb ?form; when present, form must return truthy to allow signal `:rate-limit` -- ?spec as given to `taoensso.telemere/rate-limiter`, see its docstring for details `:rate-limit-by` When present, rate limits will be enforced independently for each id (any Clojure value!) -`:middleware` -- Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-middleware` -`:middleware+` - Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-middleware+` -`:trace?` ------ Should tracing be enabled for `:run` form? +`:xfn` --------- Optional transform (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-xfn` +`:xfn+` -------- Optional extra transform (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-xfn+` ---------- Other arb app-level ?kvs to incl. in signal. Typically NOT included in handler output, so a great way to provide custom data/opts for use - (only) by custom middleware/handlers. + (only) by custom transforms/handlers. If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs! diff --git a/main/src/taoensso/telemere.cljc b/main/src/taoensso/telemere.cljc index 2b1e0ef..92e07fb 100644 --- a/main/src/taoensso/telemere.cljc +++ b/main/src/taoensso/telemere.cljc @@ -25,7 +25,7 @@ ;; Via `sigs/def-api` without-filters with-kind-filter with-ns-filter with-id-filter with-min-level with-handler with-handler+ - with-ctx with-ctx+ with-middleware with-middleware+]]))) + with-ctx with-ctx+ with-xfn with-xfn+]]))) (comment (remove-ns (symbol (str *ns*))) @@ -50,7 +50,7 @@ add-handler! remove-handler! stop-handlers! ^:dynamic *ctx* set-ctx! #?(:clj with-ctx) #?(:clj with-ctx+) - ^:dynamic *middleware* set-middleware! #?(:clj with-middleware) #?(:clj with-middleware+)) + ^:dynamic *xfn* set-xfn! #?(:clj with-xfn) #?(:clj with-xfn+)) (sigs/def-api {:sf-arity 4 @@ -73,7 +73,7 @@ enc/chance enc/rate-limiter enc/newline - enc/comp-middleware + sigs/comp-xfn sigs/default-handler-dispatch-opts #?(:clj truss/keep-callsite) diff --git a/main/src/taoensso/telemere/impl.cljc b/main/src/taoensso/telemere/impl.cljc index 2ef3d6a..d96af87 100644 --- a/main/src/taoensso/telemere/impl.cljc +++ b/main/src/taoensso/telemere/impl.cljc @@ -18,7 +18,7 @@ #?(:clj (enc/declare-remote ^:dynamic taoensso.telemere/*ctx* - ^:dynamic taoensso.telemere/*middleware* + ^:dynamic taoensso.telemere/*xfn* ^:dynamic taoensso.telemere/*uid-fn* ^:dynamic taoensso.telemere/*otel-tracer*)) @@ -393,7 +393,7 @@ '( [& opts-kvs] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, ; Undocumented - elidable? coords #_inst #_uid #_middleware #_middleware+, + elidable? coords #_inst #_uid #_xfn #_xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, #_ctx #_ctx+ #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}]) @@ -401,7 +401,7 @@ '( [& opts-kvs] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, ; Undocumented - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error run & kvs]}]) @@ -410,7 +410,7 @@ [level msg] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} msg]) @@ -421,7 +421,7 @@ [id {:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]}]) @@ -430,7 +430,7 @@ [id run] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error run & kvs]} run]) @@ -440,7 +440,7 @@ [level run] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error run & kvs]} run]) @@ -450,7 +450,7 @@ [id error] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} error]) @@ -460,7 +460,7 @@ [id run] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, catch-val, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} run]) @@ -470,7 +470,7 @@ [opts-or-id] [{:as opts-map :keys [#_elide? #_allow? #_callsite-id, - elidable? coords inst uid middleware middleware+, + elidable? coords inst uid xfn xfn+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]}]) @@ -618,15 +618,15 @@ `(taoensso.encore.signals/update-ctx taoensso.telemere/*ctx* ~ctx+) (get opts :ctx `taoensso.telemere/*ctx*)) - middleware-form - (if-let [middleware+ (get opts :middleware+)] - `(taoensso.encore/comp-middleware taoensso.telemere/*middleware* ~middleware+) - (get opts :middleware `taoensso.telemere/*middleware*)) + xfn-form + (if-let [xfn+ (get opts :xfn+)] + `(taoensso.encore.signals/comp-xfn taoensso.telemere/*xfn* ~xfn+) + (get opts :xfn `taoensso.telemere/*xfn*)) kvs-form (not-empty (dissoc opts - :elidable? :coords :inst :uid :middleware :middleware+, + :elidable? :coords :inst :uid :xfn :xfn+, :sample-rate :ns :kind :id :level :filter :when #_:rate-limit #_:rate-limit-by, :ctx :ctx+ :parent #_:trace?, :do :let :data :msg :error, :run :run-form :run-val, :elide? :allow? #_:callsite-id :otel/context)) @@ -677,15 +677,15 @@ `(enc/bound-delay ;; Delay (cache) shared by all handlers, incl. `:let` eval, - ;; signal construction, middleware, etc. Throws caught by handler. + ;; signal construction, transform (xfn), etc. Throws caught by handler. ~do-form (let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc. signal# ~signal-form] ;; Final unwrapped signal value visible to users/handler-fns, allow to throw - (if-let [sig-middleware# ~middleware-form] - (sig-middleware# signal#) ; Apply signal middleware, can throw - (do signal#))))) + (if-let [xfn# ~xfn-form] + (xfn# signal#) ; Apply call transform, can throw + (do signal#))))) ;; Trade-off: avoid double `run-form` expansion run-fn-form (when run-form `(fn [] ~run-form)) diff --git a/main/src/taoensso/telemere/utils.cljc b/main/src/taoensso/telemere/utils.cljc index 040ac45..a973c7d 100644 --- a/main/src/taoensso/telemere/utils.cljc +++ b/main/src/taoensso/telemere/utils.cljc @@ -1,5 +1,5 @@ (ns taoensso.telemere.utils - "Misc utils useful for Telemere handlers, middleware, etc." + "Misc utils useful for Telemere handlers, transforms, etc." (:refer-clojure :exclude [newline]) (:require [clojure.string :as str] diff --git a/main/test/taoensso/telemere_tests.cljc b/main/test/taoensso/telemere_tests.cljc index 948c6b9..9873071 100644 --- a/main/test/taoensso/telemere_tests.cljc +++ b/main/test/taoensso/telemere_tests.cljc @@ -250,35 +250,35 @@ (with-sig (sig! {:level :info, :ctx+ {:baz :qux}})))] (is (sm? sv {:ctx {:foo :bar, :baz :qux}}) "`*ctx*` can be updated via call opt"))]) - (testing "Middleware" - [(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 "Transforms" + [(testing "Dynamic transforms (`*xfn*`)" + [(is (sm? (tel/with-xfn nil (with-sig (sig! {:level :info }))) {:level :info }) "nil xfn ~ identity") + (is (sm? (tel/with-xfn identity (with-sig (sig! {:level :info }))) {:level :info }) "nil xfn ~ identity") + (is (sm? (tel/with-xfn #(assoc % :foo 1) (with-sig (sig! {:level :info }))) {:level :info, :foo 1 })) + (is (sm? (tel/with-xfn #(assoc % :foo 1) (with-sig (sig! {:level :info, :xfn #(assoc % :foo 2)}))) {:level :info, :foo 2 }) "call > dynamic") + (is (sm? (tel/with-xfn #(assoc % :foo 1) (with-sig (sig! {:level :info, :xfn nil}))) {:level :info, :foo :submap/nx}) "call > dynamic") + (is (= (tel/with-xfn #(do nil) (with-sig (sig! {:level :info }))) nil) "return nil => suppress") + (is (sm? (tel/with-xfn #(do nil) (with-sig (sig! {:level :info, :xfn nil}))) {:level :info}) "call > dynamic")]) - (testing "Call middleware" + (testing "Call transforms" (let [c (enc/counter) - {rv1 :value, [sv1] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) - {rv2 :value, [sv2] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false})) - {rv3 :value, [sv3] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) - {rv4 :value, [sv4] :signals} (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] "signal-value")})) - {rv5 :value, [sv5] :signals} (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] nil)}))] + {rv1 :value, [sv1] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) + {rv2 :value, [sv2] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false})) + {rv3 :value, [sv3] :signals} (with-sigs :raw nil (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c)))})) + {rv4 :value, [sv4] :signals} (with-sigs :raw nil (sig! {:level :info, :xfn (fn [_] "signal-value")})) + {rv5 :value, [sv5] :signals} (with-sigs :raw nil (sig! {:level :info, :xfn (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")])) + (is (= @c 7) "3x run + 4x xfn")])) - (testing "Mixed middleware" + (testing "Mixed transforms" [(let [sv - (binding [tel/*middleware* #(assoc % :foo true)] - (with-sig (sig! {:level :info, :middleware+ #(assoc % :bar true)})))] + (binding [tel/*xfn* #(assoc % :foo true)] + (with-sig (sig! {:level :info, :xfn+ #(assoc % :bar true)})))] (is (sm? sv {:foo true, :bar true})))])]) #?(:clj @@ -293,35 +293,35 @@ (deftest _handlers ;; Basic handler tests are in Encore - [(testing "Handler middleware" + [(testing "Handler transforms" (let [c (enc/counter) sv-h1_ (atom nil) sv-h2_ (atom nil) - wh1 (sigs/wrap-handler :hid1 (fn [sv] (reset! sv-h1_ sv)) nil {:async nil, :middleware (tel/comp-middleware #(assoc % :hm1 (c)) #(assoc % :hm2 (c)))}) - wh2 (sigs/wrap-handler :hid2 (fn [sv] (reset! sv-h2_ sv)) nil {:async nil, :middleware (tel/comp-middleware #(assoc % :hm1 (c)) #(assoc % :hm2 (c)))})] + wh1 (sigs/wrap-handler :hid1 (fn [sv] (reset! sv-h1_ sv)) nil {:async nil, :xfn (tel/comp-xfn #(assoc % :hm1 (c)) #(assoc % :hm2 (c)))}) + wh2 (sigs/wrap-handler :hid2 (fn [sv] (reset! sv-h2_ sv)) nil {:async nil, :xfn (tel/comp-xfn #(assoc % :hm1 (c)) #(assoc % :hm2 (c)))})] - ;; Note that call middleware output is cached and shared across all handlers + ;; Note that call xfn output is cached and shared across all handlers (binding [impl/*sig-handlers* [wh1 wh2]] - (let [;; 1x run + 4x handler middleware + 2x call middleware = 7x - rv1 (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))}) + (let [;; 1x run + 4x handler xfn + 2x call xfn = 7x + rv1 (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c)))}) sv1-h1 @sv-h1_ sv1-h2 @sv-h2_ c1 @c ;; 1x run - rv2 (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false}) + rv2 (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false}) sv2-h1 @sv-h1_ sv2-h2 @sv-h2_ c2 @c ; 8 - ;; 1x run + 4x handler middleware + 2x call middleware = 7x - rv3 (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))}) + ;; 1x run + 4x handler xfn + 2x call xfn = 7x + rv3 (sig! {:level :info, :run (c), :xfn (tel/comp-xfn #(assoc % :m1 (c)) #(assoc % :m2 (c)))}) sv3-h1 @sv-h1_ sv3-h2 @sv-h2_ c3 @c ; 15 - ;; 4x handler middleware - rv4 (sig! {:level :info, :middleware (fn [_] {:my-sig-val? true})}) + ;; 4x handler xfn + rv4 (sig! {:level :info, :xfn (fn [_] {:my-sig-val? true})}) sv4-h1 @sv-h1_ sv4-h2 @sv-h2_ c4 @c] @@ -330,10 +330,10 @@ (is (= rv2 7)) (is (sm? sv2-h1 {:m1 1, :m2 2, :hm1 3, :hm2 4})) (is (sm? sv2-h2 {:m1 1, :m2 2, :hm1 5, :hm2 6})) (is (= rv3 8)) (is (sm? sv3-h1 {:m1 9, :m2 10, :hm1 11, :hm2 12})) (is (sm? sv3-h2 {:m1 9, :m2 10, :hm1 13, :hm2 14})) (is (= rv4 true)) (is (sm? sv4-h1 {:my-sig-val? true, :hm1 15, :hm2 16})) (is (sm? sv4-h2 {:my-sig-val? true, :hm1 17, :hm2 18})) - (is (= c1 7) "1x run + 4x handler middleware + 2x call middleware") - (is (= c2 8) "2x run + 4x handler middleware + 2x call middleware") - (is (= c3 15) "3x run + 8x handler middleware + 4x call middleware") - (is (= c4 19) "3x run + 12x handler middleware + 4x call middleware")])))) + (is (= c1 7) "1x run + 4x handler xfn + 2x call xfn") + (is (= c2 8) "2x run + 4x handler xfn + 2x call xfn") + (is (= c3 15) "3x run + 8x handler xfn + 4x call xfn") + (is (= c4 19) "3x run + 12x handler xfn + 4x call xfn")])))) (testing "Handler binding conveyance" (let [a (atom nil) @@ -379,7 +379,7 @@ (test1 64 {:async {:mode :dropping, :buffer-size 64}}) (test1 64 {:async {:mode :sliding, :buffer-size 64}})]))))))]) -(def ^:dynamic *throwing-handler-middleware?* false) +(def ^:dynamic *throwing-handler-xfn?* false) (deftest _throwing (let [sv_ (atom :nx) @@ -393,7 +393,7 @@ (tel/with-handler :hid1 (fn [sv] (force (:data sv)) (reset! sv_ sv)) {:async nil, :error-fn (fn [x] (reset! error_ x)), :rl-error nil, - :middleware (fn [sv] (if *throwing-handler-middleware?* (ex1!) sv))} + :xfn (fn [sv] (if *throwing-handler-xfn?* (ex1!) sv))} [(is (->> (sig! {:level :info, :when (ex1!)}) (throws? :ex-info "Ex1")) "`~filterable-expansion/allow` throws at call") (is (->> (sig! {:level :info, :inst (ex1!)}) (throws? :ex-info "Ex1")) "`~inst-form` throws at call") @@ -409,15 +409,15 @@ (is (= @sv_ :nx)) (is (sm? @error_ {:handler-id :hid1, :error ex1}))]) - (testing "Throwing call middleware" + (testing "Throwing call transform" (reset-state!) - [(is (true? (sig! {:level :info, :middleware (fn [_] (ex1!))}))) + [(is (true? (sig! {:level :info, :xfn (fn [_] (ex1!))}))) (is (= @sv_ :nx)) (is (sm? @error_ {:handler-id :hid1, :error ex1}))]) - (testing "Throwing handler middleware" + (testing "Throwing handler transform" (reset-state!) - (binding [*throwing-handler-middleware?* true] + (binding [*throwing-handler-xfn?* true] [(is (true? (sig! {:level :info}))) (is (= @sv_ :nx)) (is (sm? @error_ {:handler-id :hid1, :error ex1}))])) diff --git a/wiki/1-Getting-started.md b/wiki/1-Getting-started.md index e152a4e..cd6bd62 100644 --- a/wiki/1-Getting-started.md +++ b/wiki/1-Getting-started.md @@ -175,10 +175,10 @@ A signal will be provided to a handler iff ALL of the following are true: - a. Compile time: not applicable - b. Runtime: sample rate, kind, ns, id, level, when fn, rate limit -- 3. **Call middleware** `(fn [signal]) => ?modified-signal` returns non-nil -- 4. **Handler middleware** `(fn [signal]) => ?modified-signal` returns non-nil +- 3. **Call transform** `(fn [signal]) => ?modified-signal` returns non-nil +- 4. **Handler transform** `(fn [signal]) => ?modified-signal` returns non-nil -> Middleware provides a flexible way to modify and/or filter signals by arbitrary signal data/content conditions (return nil to skip). +> Transform fns provides a flexible way to modify and/or filter signals by arbitrary signal data/content conditions (return nil to skip handling). Quick examples of some basic filtering: @@ -206,7 +206,7 @@ Telemere includes extensive internal help docstrings: | :---------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- | | [`help:signal-creators`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-creators) | Creating signals | | [`help:signal-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) | Options when creating signals | -| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal content (map given to middleware/handlers) | +| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal content (map given to transforms/handlers) | | [`help:filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:filters) | Signal filtering and transformation | | [`help:handlers`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handlers) | Signal handler management | | [`help:handler-dispatch-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handler-dispatch-options) | Signal handler dispatch options | diff --git a/wiki/2-Architecture.md b/wiki/2-Architecture.md index 7419060..be083a4 100644 --- a/wiki/2-Architecture.md +++ b/wiki/2-Architecture.md @@ -16,4 +16,4 @@ This flow is visualized below: Telemere signal flowchart - `A/sync queue` semantics are specified via [handler dispatch options](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handler-dispatch-options). -- The shared **call middleware cache** is super useful when doing signal transformations that are expensive and/or involve side effects (like syncing with another service/db to get a unique tx id, etc.). \ No newline at end of file +- The shared **call transform** cache is super useful when doing signal transformations that are expensive and/or involve side effects (like syncing with another service/db to get a unique tx id, etc.). \ No newline at end of file diff --git a/wiki/3-Config.md b/wiki/3-Config.md index 4c71843..66eb744 100644 --- a/wiki/3-Config.md +++ b/wiki/3-Config.md @@ -12,10 +12,10 @@ A signal will be provided to a handler iff ALL of the following are true: - a. Compile time: not applicable - b. Runtime: sample rate, kind, ns, id, level, when fn, rate limit -- 3. **Call middleware** `(fn [signal]) => ?modified-signal` returns non-nil -- 4. **Handler middleware** `(fn [signal]) => ?modified-signal` returns non-nil +- 3. **Call transform** `(fn [signal]) => ?modified-signal` returns non-nil +- 4. **Handler transform** `(fn [signal]) => ?modified-signal` returns non-nil -> Middleware provides a flexible way to modify and/or filter signals by arbitrary signal data/content conditions (return nil to skip). +> Transform fns provides a flexible way to modify and/or filter signals by arbitrary signal data/content conditions (return nil to skip handling). See [`help:filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:filters) for more about filtering. diff --git a/wiki/4-Handlers.md b/wiki/4-Handlers.md index d77c6c6..d596ad1 100644 --- a/wiki/4-Handlers.md +++ b/wiki/4-Handlers.md @@ -48,11 +48,11 @@ There's two kinds of config relevant to all signal handlers: ## Dispatch opts -Handler dispatch opts includes dispatch priority (determines order in which handlers are called), handler filtering, handler middleware, a/sync queue semantics, back-pressure opts, etc. +Handler dispatch opts includes dispatch priority (determines order in which handlers are called), handler filtering, handler transform, a/sync queue semantics, back-pressure opts, etc. See [`help:handler-dispatch-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:handler-dispatch-options) for full info, and [`default-handler-dispatch-opts`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#default-handler-dispatch-opts) for defaults. -Note that handler middleware in particular is an easily overlooked but powerful feature, allowing you to arbitrarily transform and/or filter every [signal map](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) before it is given to each handler. +Note that the handler transform is an easily overlooked but powerful feature, allowing you to arbitrarily modify and/or filter every [signal map](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) before it is given to each handler. ## Handler-specific opts @@ -120,27 +120,27 @@ Note that when writing JSON with Clojure, you *must* provide an appropriate `pr- ### Handler-specific per-signal kvs -Telemere includes a handy mechanism for including arbitrary app-level data/opts in individual signals for use by custom middleware and/or handlers. +Telemere includes a handy mechanism for including arbitrary app-level data/opts in individual signals for use by custom transforms and/or handlers. Any *non-standard* (app-level) keys you include in your signal constructor opts will automatically be included in created signals, e.g.: ```clojure (t/with-signal (t/event! ::my-id - {:my-middleware-data "foo" - :my-handler-data "bar"})) + {:my-data-for-xfn "foo" + :my-data-for-handler "bar"})) ;; %> ;; {;; App-level kvs included inline (assoc'd to signal root) -;; :my-middleware-data "foo" -;; :my-handler-data "bar" +;; :my-data-for-xfn "foo" +;; :my-data-for-handler "bar" ;; :kvs ; And also collected together under ":kvs" key -;; {:my-middleware-data "foo" -;; :my-handler-data "bar"} +;; {:my-data-for-xfn "foo" +;; :my-data-for-handler "bar"} ;; ... } ``` -These app-level data/opts are typically NOT included by default in handler output, making them a great way to convey data/opts to custom middleware/handlers. +These app-level data/opts are typically NOT included by default in handler output, making them a great way to convey data/opts to custom transforms/handlers. # Managing handlers diff --git a/wiki/7-Tips.md b/wiki/7-Tips.md index aaa568e..ab5d0e7 100644 --- a/wiki/7-Tips.md +++ b/wiki/7-Tips.md @@ -80,9 +80,9 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between This way you can see all your ids in one place, and precise info on when ids were added/removed/changed. -- Use **signal call middleware** to your advantage. +- Use **signal call transforms** to your advantage. - The result of call middleware is cached and *shared between all handlers* making it an efficient place to transform signals. For this reason - prefer signal middleware to handler middleware when possible/convenient. + The result of call-side signal transforms is cached and *shared between all handlers* making it an efficient place to modify signals going to >1 handler. - Signal and handler **sampling is multiplicative**. @@ -94,12 +94,12 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between So for `n` randomly sampled signals matching some criteria, you'd have seen an estimated `Σ(1.0/sample-rate_i)` such signals _without_ sampling, etc. -- Middleware can return any type, but it's best to return only `nil` or a map. This ensures maximum compatibility with community middleware, handlers, and tools. +- Transforms can technically return any type, but it's best to return only `nil` or a map. This ensures maximum compatibility with community transforms, handlers, and tools. -- Middleware can be used to **filter signals** by returning `nil`. -- Middleware can be used to **split signals**: +- Transforms can be used to **filter signals** by returning `nil`. +- Transforms can be used to **split signals**: - Your middleware can *call signal creators* like any other code. Return `nil` after to filter the source signal. Just be aware that new signals will re-enter your handler queue/s as would any other signal - and so may be subject to handling delay and normal handler queue back-pressure. + Your transforms can *call signal creators* like any other code. Return `nil` after to filter the source signal. Just be aware that new signals will re-enter your handler queue/s as would any other signal - and so may be subject to handling delay and normal handler queue back-pressure. See also the [`dispatch-signal!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#dispatch-signal!) util. @@ -122,7 +122,7 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between Note that all app-level kvs will *also* be available *together* under the signal's `:kvs` key. - App-level kvs are typically *not* included in handler output, so are a great way of providing custom data/opts for use (only) by custom middleware or handlers. + App-level kvs are typically *not* included in handler output, so are a great way of providing custom data/opts for use (only) by custom transforms or handlers. - Signal `kind` can be useful in advanced cases. diff --git a/wiki/8-Community.md b/wiki/8-Community.md index c835ce2..9ed5bf0 100644 --- a/wiki/8-Community.md +++ b/wiki/8-Community.md @@ -1,4 +1,4 @@ -My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, middleware, and utils. +My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, transforms, and utils. **PRs very welcome** to add links to this page! @@ -20,7 +20,7 @@ Includes videos, tutorials, demo projects, etc. # Handlers and tools -Includes libraries or examples for handlers (see [Writing handlers](./4-Handlers#writing-handlers)), middleware, handler utils (e.g. formatters), tools for analyzing signals, etc. [PRs](../wiki#contributions-welcome) welcome for additions! +Includes libraries or examples for handlers (see [Writing handlers](./4-Handlers#writing-handlers)), transforms, handler utils (e.g. formatters), tools for analyzing signals, etc. [PRs](../wiki#contributions-welcome) welcome for additions! | Type | Description | | ---- | :------------------------------------------------------------ |