diff --git a/projects/main/resources/signal-docstrings/signal-options.txt b/projects/main/resources/signal-docstrings/signal-options.txt index a36ab4f..6255da7 100644 --- a/projects/main/resources/signal-docstrings/signal-options.txt +++ b/projects/main/resources/signal-docstrings/signal-options.txt @@ -15,17 +15,19 @@ Signal options (shared by all signal creators): `:do` ---------- ?form to execute conditionally (iff signal allowed), before establishing `:let` ?binding `:let` --------- ?bindings to establish conditionally (iff signal allowed), BEFORE evaluating `:data` and `:msg` (useful!) -`:ctx` --------- Custom ?val to override auto (dynamic `*ctx*`) in signal `:parent` ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal tracing info `:root` -------- Custom ?{:keys [id uid]} to override auto (dynamic) root signal tracing info `:location` ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location +`:ctx` --------- Custom ?val to override auto (dynamic `*ctx*`) in signal, as per `with-ctx` +`:ctx+` -------- Custom ?val to update auto (dynamic `*ctx*`) in signal, as per `with-ctx+` `:elidable?` --- Should signal be subject to compile-time elision? (Default: true) `: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 +`: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? ---------- Other arb app-level ?kvs to incl. in signal. Typically NOT included in diff --git a/projects/main/src/taoensso/telemere/impl.cljc b/projects/main/src/taoensso/telemere/impl.cljc index 7621b85..6103b01 100644 --- a/projects/main/src/taoensso/telemere/impl.cljc +++ b/projects/main/src/taoensso/telemere/impl.cljc @@ -385,16 +385,16 @@ :signal! ; [opts] => allowed? / run result (value or throw) '([{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error run & kvs]}]) + ctx ctx+ parent root trace?, do let data msg error run & kvs]}]) :signal-allowed? '([{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented - elidable? location #_location* #_inst #_uid #_middleware, + elidable? location #_location* #_inst #_uid #_middleware #_middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - #_ctx #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}]) + #_ctx #_ctx+ #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}]) :event! ; [id] [id level-or-opts] => allowed? '([id ] @@ -402,18 +402,18 @@ [id {:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error #_run & kvs]}]) + ctx ctx+ parent root trace?, do let data msg error #_run & kvs]}]) :log! ; [msg] [level-or-opts msg] => allowed? '([ msg] [level msg] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error #_run & kvs]} + ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} msg]) :error! ; [error] [id-or-opts error] => given error @@ -421,9 +421,9 @@ [id error] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error #_run & kvs]} + ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} error]) :trace! ; [form] [id-or-opts form] => run result (value or throw) @@ -431,9 +431,9 @@ [id form] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error run & kvs]} + ctx ctx+ parent root trace?, do let data msg error run & kvs]} form]) :spy! ; [form] [level-or-opts form] => run result (value or throw) @@ -441,9 +441,9 @@ [level form] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error run & kvs]} + ctx ctx+ parent root trace?, do let data msg error run & kvs]} form]) :catch->error! ; [form] [id-or-opts form] => run result (value or throw) @@ -451,9 +451,9 @@ [id form] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, rethrow? catch-val, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error #_run & kvs]} + ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} form]) :uncaught->error! ; [] [id-or-opts] => nil @@ -461,9 +461,9 @@ [id] [{:as opts :keys [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error #_run & kvs]}]) + ctx ctx+ parent root trace?, do let data msg error #_run & kvs]}]) (enc/unexpected-arg! macro-id)))) @@ -637,15 +637,22 @@ let-form (or let-form '[]) msg-form (parse-msg-form msg-form) - ctx-form (get opts :ctx `taoensso.telemere/*ctx*) - middleware-form (get opts :middleware `taoensso.telemere/*middleware*) + ctx-form + (if-let [ctx+ (get opts :ctx+)] + `(taoensso.encore.signals/update-ctx taoensso.telemere/*ctx* ~ctx+) + (get opts :ctx `taoensso.telemere/*ctx*)) + + middleware-form + (if-let [middleware+ (get opts :middleware+)] + `(taoensso.telemere/comp-middleware taoensso.telemere/*middleware* ~middleware+) + (get opts :middleware `taoensso.telemere/*middleware*)) kvs-form (not-empty (dissoc opts - :elidable? :location :location* :inst :uid :middleware, + :elidable? :location :location* :inst :uid :middleware :middleware+, :sample-rate :ns :kind :id :level :filter :when #_:rate-limit #_:rate-limit-by, - :ctx :parent #_:trace?, :do :let :data :msg :error :run, + :ctx :ctx+ :parent #_:trace?, :do :let :data :msg :error :run, :elide? :allow? #_:expansion-id :otel/context)) _ ; Compile-time validation diff --git a/projects/main/test/taoensso/telemere_tests.cljc b/projects/main/test/taoensso/telemere_tests.cljc index 235d2f9..a368451 100644 --- a/projects/main/test/taoensso/telemere_tests.cljc +++ b/projects/main/test/taoensso/telemere_tests.cljc @@ -232,39 +232,51 @@ (is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")])))) (testing "Dynamic bindings, etc." - [(binding[#?@(:clj [impl/*sig-spy-off-thread?* true]) - *dynamic-var* "foo" - tel/*ctx* "bar"] - (let [sv (with-sig (sig! {:level :info, :data {:*dynamic-var* *dynamic-var*, :*ctx* tel/*ctx*}}))] - (is (sm? sv {:data {:*dynamic-var* "foo", :*ctx* "bar"}}) - "Retain dynamic bindings in place at time of signal call"))) + [(let [sv + (binding[#?@(:clj [impl/*sig-spy-off-thread?* true]) + *dynamic-var* "dynamic-val" + tel/*ctx* "ctx-val"] + (with-sig (sig! {:level :info, :data {:*dynamic-var* *dynamic-var*, :*ctx* tel/*ctx*}})))] + (is (sm? sv {:data {:*dynamic-var* "dynamic-val", :*ctx* "ctx-val"}}) + "Retain dynamic bindings in place at time of signal call")) (let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] - (is (sm? sv {:ctx "my-ctx"}) "`*ctx*` can be overridden via call opt"))]) + (is (sm? sv {:ctx "my-ctx"}) "`*ctx*` can be overridden 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")]) + (let [sv (binding [tel/*ctx* {:foo :bar}] + (with-sig (sig! {:level :info, :ctx+ {:baz :qux}})))] + (is (sm? sv {:ctx {:foo :bar, :baz :qux}}) "`*ctx*` can be updated via call opt"))]) - (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")})) - [[rv5 _] [sv5]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] nil)}))] + (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")]) - [(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 "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")})) + [[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 "Mixed middleware" + [(let [sv + (binding [tel/*middleware* #(assoc % :foo true)] + (with-sig (sig! {:level :info, :middleware+ #(assoc % :bar true)})))] + (is (sm? sv {:foo true, :bar true})))])]) #?(:clj (testing "Printing" diff --git a/projects/shell/src/taoensso/telemere/shell.cljc b/projects/shell/src/taoensso/telemere/shell.cljc index cbd35c2..ea0b7ea 100644 --- a/projects/shell/src/taoensso/telemere/shell.cljc +++ b/projects/shell/src/taoensso/telemere/shell.cljc @@ -132,9 +132,9 @@ :keys [fallback, ; Unique to shell #_defaults #_elide? #_allow? #_expansion-id, ; Undocumented - elidable? location #_location* inst uid middleware, + elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - ctx parent root trace?, do let data msg error run & kvs]}])} + ctx ctx+ parent root trace?, do let data msg error run & kvs]}])} [opts] (if telemere-present? @@ -171,9 +171,9 @@ '([{:as opts :keys [#_fallback, ; Unique to shell #_defaults #_elide? #_allow? #_expansion-id, ; Undocumented - elidable? location #_location* #_inst #_uid #_middleware, + elidable? location #_location* #_inst #_uid #_middleware #_middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, - #_ctx #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}])} + #_ctx #_ctx+ #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}])} [opts] (if telemere-present?