diff --git a/projects/main/resources/signal-docstrings/catch-to-error!.txt b/projects/main/resources/signal-docstrings/catch-to-error!.txt index c3ac340..c94de1a 100644 --- a/projects/main/resources/signal-docstrings/catch-to-error!.txt +++ b/projects/main/resources/signal-docstrings/catch-to-error!.txt @@ -1,10 +1,9 @@ -Unconditionally executes given form and- - If form succeeds: return the form's result. - If form throws: +ALWAYS (unconditionally) executes given `run` form and: + If `run` form succeeds: return the form's result. + If `run` form throws: Call `error!` with the thrown error and the given signal options [2], then return (:catch-val opts) if it exists, or rethrow the error. -API: [form] [id-or-opts form] => form's result (value/throw) (unconditional), or (:catch-val opts) Default kind: `:error` Default level: `:error` diff --git a/projects/main/resources/signal-docstrings/error!.txt b/projects/main/resources/signal-docstrings/error!.txt index 0de6c93..f0eb958 100644 --- a/projects/main/resources/signal-docstrings/error!.txt +++ b/projects/main/resources/signal-docstrings/error!.txt @@ -1,6 +1,7 @@ -"Error" signal creator, emphasizing error + id. +"Error" signal creator, emphasizing (optional id) + error (Exception, etc.). +ALWAYS (unconditionally) returns the given error, so can conveniently be wrapped +by `throw`: (throw (error! (ex-info ...)), etc. -API: [error] [id-or-opts error] => given error (unconditional) Default kind: `:error` Default level: `:error` @@ -22,7 +23,6 @@ Tips: - Supports the same options [2] as other signals [1]. - `error` arg is a platform error (`java.lang.Throwable` or `js/Error`). - - Can conveniently be wrapped by `throw`: (throw (error! ...)). ---------------------------------------------------------------------- [1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...) diff --git a/projects/main/resources/signal-docstrings/event!.txt b/projects/main/resources/signal-docstrings/event!.txt index 8ae4bbc..36069d6 100644 --- a/projects/main/resources/signal-docstrings/event!.txt +++ b/projects/main/resources/signal-docstrings/event!.txt @@ -1,6 +1,6 @@ -"Event" signal creator, emphasizing id + level. +"Event" signal creator, emphasizing id + (optional level). +Returns true iff signal was created (allowed by filtering). -API: [id] [id level-or-opts] => true iff signal was allowed Default kind: `:event` Default level: `:info` diff --git a/projects/main/resources/signal-docstrings/log!.txt b/projects/main/resources/signal-docstrings/log!.txt index 830a889..10bb15c 100644 --- a/projects/main/resources/signal-docstrings/log!.txt +++ b/projects/main/resources/signal-docstrings/log!.txt @@ -1,6 +1,6 @@ -"Log" signal creator, emphasizing message + level. +"Log" signal creator, emphasizing (optional level) + message. +Returns true iff signal was created (allowed by filtering). -API: [msg] [level-or-opts msg] => true iff signal was allowed. Default kind: `:log` Default level: `:info` diff --git a/projects/main/resources/signal-docstrings/signal!.txt b/projects/main/resources/signal-docstrings/signal!.txt index 132c756..1075706 100644 --- a/projects/main/resources/signal-docstrings/signal!.txt +++ b/projects/main/resources/signal-docstrings/signal!.txt @@ -1,16 +1,17 @@ -Low-level generic signal creator. +Low-level "generic" signal creator for creating signals of any "kind". +Takes a single map of options [2] with compile-time keys. -API: [opts] => depends on options [2] -Default kind: `:generic` +Return value depends on options: + - If given `:run` form: unconditionally returns run value, or rethrows run error. + - Otherwise: returns true iff signal was created (allowed by filtering). + +Default kind: `:generic` (feel free to change!) Default level: `:info` When filtering conditions are met [4], creates a Telemere signal [3] and dispatches it to registered handlers for processing (e.g. writing to console/file/queue/db, etc.). -If `:run` option is provided: returns value of given run form, or throws. - Otherwise: returns true iff signal was created (allowed). - Generic signals are fairly low-level and useful mostly for library authors or advanced users writing their own wrapper macros. Regular users will typically prefer one of the higher-level signal creators optimized for ease-of-use in diff --git a/projects/main/resources/signal-docstrings/signal-creators.txt b/projects/main/resources/signal-docstrings/signal-creators.txt index 488ca2a..b9b3367 100644 --- a/projects/main/resources/signal-docstrings/signal-creators.txt +++ b/projects/main/resources/signal-docstrings/signal-creators.txt @@ -14,13 +14,13 @@ various keys: Creators vary only in in their default options and call APIs (expected args and return values), making them more/less convenient for certain use cases: - `event!` -------- [id ] or [id opts/level] => true iff signal was created (allowed) - `log!` ---------- [msg ] or [opts/level msg] => true iff signal was created (allowed) - `error!` -------- [error] or [opts/id error] => given error (unconditional) - `trace!` -------- [form ] or [opts/id form] => form result (value/throw) (unconditional) - `spy!` ---------- [form ] or [opts/level form] => form result (value/throw) (unconditional) - `catch->error!` - [form ] or [opts/id form] => form value, or given fallback - `signal!` ------- [opts ] => depends on options + `signal!` ------- opts => allowed? / unconditional run result (value or throw) + `event!` -------- id + ?level => allowed? + `log!` ---------- ?level + msg => allowed? + `trace!` -------- ?id + run => unconditional run result (value or throw) + `spy!` ---------- ?level + run => unconditional run result (value or throw) + `error!` -------- ?id + error => unconditional given error + `catch->error!` - ?id + run => unconditional run value or ?catch-val - `log!` and `event!` are both good default/general-purpose signal creators. - `log!` emphasizes messages, while `event!` emphasizes ids. diff --git a/projects/main/resources/signal-docstrings/spy!.txt b/projects/main/resources/signal-docstrings/spy!.txt index b20d01f..6359859 100644 --- a/projects/main/resources/signal-docstrings/spy!.txt +++ b/projects/main/resources/signal-docstrings/spy!.txt @@ -1,6 +1,6 @@ -"Spy" signal creator, emphasizing form + level. +"Spy" signal creator, emphasizing (optional level) + form to run. +ALWAYS (unconditionally) returns run value, or rethrows run error. -API: [form] [level-or-opts form] => form's result (value/throw) (unconditional) Default kind: `:spy` Default level: `:info` @@ -8,14 +8,14 @@ When filtering conditions are met [4], creates a Telemere signal [3] and dispatches it to registered handlers for processing (e.g. writing to console/file/queue/db, etc.). -Enables tracing of given `form` arg: +Enables tracing of given `run` form: - Resulting signal will include {:keys [run-form run-val run-nsecs]}. - Nested signals will include this signal's id and uid under `:parent`. Limitations: - 1. Traced code (`form` arg) is usually expected to be synchronous and eager. + 1. Traced `run` form is usually expected to be synchronous and eager. So no lazy seqs, async calls, or inversion of flow control (IoC) macros like core.async `go` blocks, etc. @@ -47,18 +47,18 @@ Tips: - Test using `with-signal`: (with-signal (spy! ...)). - Supports the same options [2] as other signals [1]. - - Identical to `trace!`, but emphasizes form + level rather than form + id. + - Like `trace!`, but takes optional level rather than optional id. - Useful for debugging/monitoring forms, and tracing (nested) execution flow. - - Execution of `form` arg may create additional (nested) signals. + - Execution of `run` form may create additional (nested) signals. Each signal's `:parent` key will indicate its immediate parent. - Can be useful to wrap with `catch->error!`: (catch->error! ::error-id (spy! ...)). - - Runtime of async or lazy code in `form` will intentionally NOT be included - in resulting signal's `:run-nsecs` value. If you want to measure such - runtimes, make sure that your form wraps where the relevant costs are + - Runtime of async or lazy code in `run` form will intentionally NOT be + included in resulting signal's `:run-nsecs` value. If you want to measure + such runtimes, make sure that your form wraps where the relevant costs are actually realized. Compare: (spy! (delay (my-slow-code))) ; Doesn't measure slow code (spy! @(delay (my-slow-code))) ; Does measure slow code diff --git a/projects/main/resources/signal-docstrings/trace!.txt b/projects/main/resources/signal-docstrings/trace!.txt index 2cc3d80..d6c10c9 100644 --- a/projects/main/resources/signal-docstrings/trace!.txt +++ b/projects/main/resources/signal-docstrings/trace!.txt @@ -1,6 +1,6 @@ -"Trace" signal creator, emphasizing form + id. +"Trace" signal creator, emphasizing (optional id) + form to run. +ALWAYS (unconditionally) returns run value, or rethrows run error. -API: [form] [id-or-opts form] => form's result (value/throw) (unconditional) Default kind: `:trace` Default level: `:info` (intentionally NOT `:trace`!) @@ -8,14 +8,14 @@ When filtering conditions are met [4], creates a Telemere signal [3] and dispatches it to registered handlers for processing (e.g. writing to console/file/queue/db, etc.). -Enables tracing of given `form` arg: +Enables tracing of given `run` form: - Resulting signal will include {:keys [run-form run-val run-nsecs]}. - Nested signals will include this signal's id and uid under `:parent`. Limitations: - 1. Traced code (`form` arg) is usually expected to be synchronous and eager. + 1. Traced `run` form is usually expected to be synchronous and eager. So no lazy seqs, async calls, or inversion of flow control (IoC) macros like core.async `go` blocks, etc. @@ -47,10 +47,10 @@ Tips: - Test using `with-signal`: (with-signal (trace! ...)). - Supports the same options [2] as other signals [1]. - - Identical to `spy!`, but emphasizes form + id rather than form + level. + - Like `spy!`, but takes optional id rather than optional level. - Useful for debugging/monitoring forms, and tracing (nested) execution flow. - - Execution of `form` arg may create additional (nested) signals. + - Execution of `run` form may create additional (nested) signals. Each signal's `:parent` key will indicate its immediate parent. - Can be useful to wrap with `catch->error!`: @@ -60,9 +60,9 @@ Tips: refers to the general action of tracing program flow rather than to the common logging level of the same name. - - Runtime of async or lazy code in `form` will intentionally NOT be included - in resulting signal's `:run-nsecs` value. If you want to measure such - runtimes, make sure that your form wraps where the relevant costs are + - Runtime of async or lazy code in `run` form will intentionally NOT be + included in resulting signal's `:run-nsecs` value. If you want to measure + such runtimes, make sure that your form wraps where the relevant costs are actually realized. Compare: (trace! (delay (my-slow-code))) ; Doesn't measure slow code (trace! @(delay (my-slow-code))) ; Does measure slow code diff --git a/projects/main/src/taoensso/telemere.cljc b/projects/main/src/taoensso/telemere.cljc index 6f955eb..4443753 100644 --- a/projects/main/src/taoensso/telemere.cljc +++ b/projects/main/src/taoensso/telemere.cljc @@ -198,154 +198,102 @@ (comment (enc/qb 1e6 (force *otel-tracer*))) ; 51.23 ;;;; Signal creators -;; - event! [id ] [id opts/level] ; id + ?level => allowed? ; Sole signal with descending main arg! -;; - log! [msg ] [opts/level msg] ; msg + ?level => allowed? -;; - error! [error] [opts/id error] ; error + ?id => given error -;; - trace! [form ] [opts/id form] ; run + ?id => run result (value or throw) -;; - spy! [form ] [opts/level form] ; run + ?level => run result (value or throw) -;; - catch->error! [form ] [opts/id form] ; run + ?id => run value or ?return -;; - signal! [opts ] ; => allowed? / run result (value or throw) -;; - uncaught->error! [opts/id] ; ?id => nil +;; - signal! ---------- opts => allowed? / unconditional run result (value or throw) +;; - event! ----------- id + ?level => allowed? +;; - log! ------------- ?level + msg => allowed? +;; - trace! ----------- ?id + run => unconditional run result (value or throw) +;; - spy! ------------- ?level + run => unconditional run result (value or throw) +;; - error! ----------- ?id + error => unconditional given error +;; - catch->error! ---- ?id + run => unconditional run value or ?catch-val +;; - uncaught->error! - ?id => nil #?(:clj - (defmacro event! - "[id] [id level-or-opts] => allowed?" - {:doc (impl/signal-docstring :event!) - :arglists (impl/signal-arglists :event!)} - [& args] - (let [opts - (impl/signal-opts `event! (enc/get-source &form &env) - {:kind :event, :level :info} :id :level :dsc args)] - `(impl/signal! ~opts)))) + (defn- merge-or-assoc-opts [m &form &env k v] + (let [m (assoc m :location* (enc/get-source &form &env))] + (if (map? v) + (merge m v) + (assoc m k v))))) + +#?(:clj + (let [base-opts {:kind :event, :level :info}] + (defmacro event! + "id + ?level => allowed? Note unique arg order: [x opts] rather than [opts x]!" + {:doc (impl/signal-docstring :event!) + :arglists (impl/signal-arglists :event!)} + ([ opts-or-id] `(impl/signal! ~(merge-or-assoc-opts base-opts &form &env :id opts-or-id))) + ([id opts-or-level] `(impl/signal! ~(assoc (merge-or-assoc-opts base-opts &form &env :level opts-or-level) :id id)))))) (comment (with-signal (event! ::my-id :info))) #?(:clj - (defmacro log! - "[msg] [level-or-opts msg] => allowed?" - {:doc (impl/signal-docstring :log!) - :arglists (impl/signal-arglists :log!)} - [& args] - (let [opts - (impl/signal-opts `log! (enc/get-source &form &env) - {:kind :log, :level :info} :msg :level :asc args)] - `(impl/signal! ~opts)))) + (let [base-opts {:kind :log, :level :info}] + (defmacro log! + "?level + msg => allowed?" + {:doc (impl/signal-docstring :log!) + :arglists (impl/signal-arglists :log!)} + ([opts-or-msg ] `(impl/signal! ~(merge-or-assoc-opts base-opts &form &env :msg opts-or-msg))) + ([opts-or-level msg] `(impl/signal! ~(assoc (merge-or-assoc-opts base-opts &form &env :level opts-or-level) :msg msg)))))) (comment (with-signal (log! :info "My msg"))) #?(:clj - (defmacro error! - "[error] [error id-or-opts] => error" - {:doc (impl/signal-docstring :error!) - :arglists (impl/signal-arglists :error!)} - [& args] - (let [opts - (impl/signal-opts `error! (enc/get-source &form &env) - {:kind :error, :level :error} :error :id :asc args) - error-form (get opts :error)] + (let [base-opts {:kind :trace, :level :info, :msg `impl/default-trace-msg}] + (defmacro trace! + "?id + run => unconditional run result (value or throw)." + {:doc (impl/signal-docstring :trace!) + :arglists (impl/signal-arglists :trace!)} + ([opts-or-run] `(impl/signal! ~(merge-or-assoc-opts base-opts &form &env :run opts-or-run))) + ([opts-or-id run] `(impl/signal! ~(assoc (merge-or-assoc-opts base-opts &form &env :id opts-or-id) :run run)))))) - `(let [~'__error ~error-form] - (impl/signal! ~(assoc opts :error '__error)) - ~'__error ; Unconditional! - )))) +(comment (with-signal (trace! ::my-id (+ 1 2)))) + +#?(:clj + (let [base-opts {:kind :spy, :level :info, :msg `impl/default-trace-msg}] + (defmacro spy! + "?level + run => unconditional run result (value or throw)." + {:doc (impl/signal-docstring :spy!) + :arglists (impl/signal-arglists :spy!)} + ([opts-or-run] `(impl/signal! ~(merge-or-assoc-opts base-opts &form &env :run opts-or-run))) + ([opts-or-level run] `(impl/signal! ~(assoc (merge-or-assoc-opts base-opts &form &env :level opts-or-level) :run run)))))) + +(comment (with-signals (spy! :info (+ 1 2)))) + +#?(:clj + (let [base-opts {:kind :error, :level :error}] + (defmacro error! + "?id + error => unconditional given error." + {:doc (impl/signal-docstring :error!) + :arglists (impl/signal-arglists :error!)} + ([opts-or-id error] `(error! ~(assoc (merge-or-assoc-opts base-opts &form &env :id opts-or-id) :error error))) + ([opts-or-error] + (let [opts (merge-or-assoc-opts base-opts &form &env :error opts-or-error)] + `(let [~'__error ~(get opts :error)] + (impl/signal! ~(assoc opts :error '__error)) + (do ~'__error))))))) (comment (with-signal (throw (error! ::my-id (ex-info "MyEx" {}))))) #?(:clj - (defmacro catch->error! - "[form] [id-or-opts form] => run value or ?catch-val" - {:doc (impl/signal-docstring :catch-to-error!) - :arglists (impl/signal-arglists :catch->error!)} - [& args] - (let [opts - (impl/signal-opts `catch->error! (enc/get-source &form &env) - {:kind :error, :level :error} ::__form :id :asc args) + (let [base-opts {:kind :error, :level :error}] + (defmacro catch->error! + "?id + run => unconditional run value or ?catch-val." + {:doc (impl/signal-docstring :catch->error!) + :arglists (impl/signal-arglists :catch->error!)} + ([opts-or-id run] `(catch->error! ~(assoc (merge-or-assoc-opts base-opts &form &env :id opts-or-id) :run run))) + ([opts-or-run] + (let [opts (merge-or-assoc-opts base-opts &form &env :run opts-or-run) + rethrow? (if (contains? opts :catch-val) false (get opts :rethrow? true)) + catch-val (get opts :catch-val) + catch-sym (get opts :catch-sym '__caught-error) ; Undocumented + run-form (get opts :run) + opts (dissoc opts :run :catch-val :catch-sym :rethrow?)] - rethrow? (if (contains? opts :catch-val) false (get opts :rethrow? true)) - catch-val (get opts :catch-val) - catch-sym (get opts :catch-sym '__caught-error) ; Undocumented - form (get opts ::__form) - opts (dissoc opts ::__form :catch-val :catch-sym :rethrow?)] + `(enc/try* ~run-form + (catch :all ~catch-sym + (impl/signal! ~(assoc opts :error catch-sym)) + (if ~rethrow? (throw ~catch-sym) ~catch-val)))))))) - `(enc/try* ~form - (catch :all ~catch-sym - (impl/signal! ~(assoc opts :error catch-sym)) - (if ~rethrow? (throw ~catch-sym) ~catch-val)))))) - -(comment - (with-signal (catch->error! ::my-id (/ 1 0))) - (with-signal (catch->error! { :msg ["Error:" __caught-error]} (/ 1 0))) - (with-signal (catch->error! {:catch-sym my-err :msg ["Error:" my-err]} (/ 1 0)))) - -#?(:clj - (defmacro trace! - "[form] [id-or-opts form] => run result (value or throw)" - {:doc (impl/signal-docstring :trace!) - :arglists (impl/signal-arglists :trace!)} - [& args] - (let [opts - (impl/signal-opts `trace! (enc/get-source &form &env) - {:kind :trace, :level :info, :msg `impl/default-trace-msg} - :run :id :asc args) - - ;; :catch->error currently undocumented - [opts catch-opts] (impl/signal-catch-opts opts)] - - (if catch-opts - `(catch->error! ~catch-opts (impl/signal! ~opts)) - (do `(impl/signal! ~opts)))))) - -(comment - (with-signal (trace! ::my-id (+ 1 2))) - (let [[_ [s1 s2]] - (with-signals - (trace! {:id :id1, :catch->error :id2} - (throw (ex-info "Ex1" {}))))] - [s2])) - -#?(:clj - (defmacro spy! - "[form] [level-or-opts form] => run result (value or throw)" - {:doc (impl/signal-docstring :spy!) - :arglists (impl/signal-arglists :spy!)} - [& args] - (let [opts - (impl/signal-opts `spy! (enc/get-source &form &env) - {:kind :spy, :level :info, :msg `impl/default-trace-msg} - :run :level :asc args) - - ;; :catch->error currently undocumented - [opts catch-opts] (impl/signal-catch-opts opts)] - - (if catch-opts - `(catch->error! ~catch-opts (impl/signal! ~opts)) - (do `(impl/signal! ~opts)))))) - -(comment (with-signal :force (spy! :info (+ 1 2)))) - -#?(:clj - (defmacro uncaught->error! - "Uses `uncaught->handler!` so that `error!` will be called for - uncaught JVM errors. - - See `uncaught->handler!` and `error!` for details." - {:arglists (impl/signal-arglists :uncaught->error!)} - [& args] - (let [msg-form ["Uncaught Throwable on thread:" `(.getName ~(with-meta '__thread-arg {:tag 'java.lang.Thread}))] - opts - (impl/signal-opts `uncaught->error! (enc/get-source &form &env) - {:kind :error, :level :error, :msg msg-form} - :error :id :dsc (into ['__throwable-arg] args))] - - `(uncaught->handler! - (fn [~'__thread-arg ~'__throwable-arg] - (impl/signal! ~opts)))))) - -(comment - (macroexpand '(uncaught->error! ::uncaught)) - (do - (uncaught->error! ::uncaught) - (enc/threaded :user (/ 1 0)))) +(comment (with-signal (catch->error! ::my-id (/ 1 0)))) #?(:clj (defn uncaught->handler! @@ -361,6 +309,31 @@ (handler thread throwable))))) nil)) +#?(:clj + (let [base-opts + {:kind :error, :level :error, + :msg `["Uncaught Throwable on thread:" (.getName ~(with-meta '__thread-arg {:tag 'java.lang.Thread}))] + :error '__throwable-arg}] + + (defmacro uncaught->error! + "Uses `uncaught->handler!` so that `error!` will be called for + uncaught JVM errors. + + See `uncaught->handler!` and `error!` for details." + {:arglists (impl/signal-arglists :uncaught->error!)} + ([ ] (enc/keep-callsite `(uncaught->error! {}))) + ([opts-or-id] + (let [opts (merge-or-assoc-opts base-opts &form &env :id opts-or-id)] + `(uncaught->handler! + (fn [~'__thread-arg ~'__throwable-arg] + (impl/signal! ~opts)))))))) + +(comment + (macroexpand '(uncaught->error! ::uncaught)) + (do + (uncaught->error! ::uncaught) + (enc/threaded :user (/ 1 0)))) + ;;;; (defn dispatch-signal! diff --git a/projects/main/src/taoensso/telemere/impl.cljc b/projects/main/src/taoensso/telemere/impl.cljc index 48f22e1..ece5de8 100644 --- a/projects/main/src/taoensso/telemere/impl.cljc +++ b/projects/main/src/taoensso/telemere/impl.cljc @@ -376,84 +376,84 @@ (defn signal-arglists [macro-id] (case macro-id - :signal! ; [opts] => allowed? / run result (value or throw) - '([{:as opts :keys + :signal! ; opts => allowed? / unconditional run result (value or throw) + '([{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error run & kvs]}]) - :signal-allowed? - '([{:as opts :keys + :signal-allowed? ; opts => allowed? + '([{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented elidable? location #_location* #_inst #_uid #_middleware #_middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, #_ctx #_ctx+ #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}]) - :event! ; [id] [id level-or-opts] => allowed? - '([id ] - [id level] + :event! ; id + ?level => allowed? + '([opts-or-id] + [id level] [id - {:as opts :keys + {:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, 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 + :log! ; ?level + msg => allowed? + '([opts-or-msg] + [level msg] + [{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, elidable? location #_location* inst uid middleware middleware+, 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]) - :error! ; [error] [id-or-opts error] => given error - '([ error] - [id error] - [{:as opts :keys + :trace! ; ?id + run => unconditional run result (value or throw) + '([opts-or-run] + [id run] + [{:as opts-map :keys + [#_defaults #_elide? #_allow? #_expansion-id, + elidable? location #_location* inst uid middleware middleware+, + 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]) + + :spy! ; ?level + run => unconditional run result (value or throw) + '([opts-or-run] + [level run] + [{:as opts-map :keys + [#_defaults #_elide? #_allow? #_expansion-id, + elidable? location #_location* inst uid middleware middleware+, + 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]) + + :error! ; ?id + error => unconditional given error + '([opts-or-error] + [id error] + [{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, elidable? location #_location* inst uid middleware middleware+, 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]) - :trace! ; [form] [id-or-opts form] => run result (value or throw) - '([ form] - [id form] - [{:as opts :keys - [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware middleware+, - sample-rate kind ns id level when rate-limit rate-limit-by, - ctx ctx+ parent root trace?, do let data msg error run & kvs]} - form]) - - :spy! ; [form] [level-or-opts form] => run result (value or throw) - '([ form] - [level form] - [{:as opts :keys - [#_defaults #_elide? #_allow? #_expansion-id, - elidable? location #_location* inst uid middleware middleware+, - sample-rate kind ns id level when rate-limit rate-limit-by, - 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) - '([ form] - [id form] - [{:as opts :keys + :catch->error! ; ?id + run => unconditional run value or ?catch-val + '([opts-or-run] + [id run] + [{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, rethrow? catch-val, elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, ctx ctx+ parent root trace?, do let data msg error #_run & kvs]} - form]) + run]) - :uncaught->error! ; [] [id-or-opts] => nil - '([ ] - [id] - [{:as opts :keys + :uncaught->error! ; ?id => nil + '([] + [opts-or-id] + [{:as opts-map :keys [#_defaults #_elide? #_allow? #_expansion-id, elidable? location #_location* inst uid middleware middleware+, sample-rate kind ns id level when rate-limit rate-limit-by, @@ -461,75 +461,6 @@ (enc/unexpected-arg! macro-id)))) -#?(:clj - (defn signal-opts - "Util to help write common signal wrapper macros." - [context location* defaults main-key extra-key arg-order args] - (enc/cond - :let [context-name (str "`" (name context) "`") - num-args (count args) - bad-args! - (fn [msg data] - (throw - (ex-info (str "Invalid " context-name " args: " msg) - (conj - {:context context - :args args} - data))))] - - (not (#{1 2} num-args)) - (bad-args! (str "wrong number of args (" num-args ")") - {:actual num-args, :expected #{1 2}}) - - :let [[main-arg extra-arg] - (case arg-order - :dsc args ; [main ...] - :asc (reverse args) ; [... main] - (enc/unexpected-arg! - arg-order)) - - extra-arg? (= num-args 2) - extra-opts? (and extra-arg? (map? extra-arg))] - - :do - (enc/cond - (and (map? main-arg) (not extra-arg?)) - (bad-args! "single map arg is USUALLY a mistake, so isn't allowed. Please use 2 arg arity instead, or `signal!`." {}) - - (and extra-opts? (contains? extra-arg main-key)) - (bad-args! (str "given opts should not contain `" main-key "`.") {})) - - :let [base (merge defaults {:location* location*, main-key main-arg})] - extra-opts? (merge base extra-arg) - extra-arg? (merge base {extra-key extra-arg}) - :else base))) - -(comment (signal-opts `foo! :loc* {:level :info} :id :level :dsc [::my-id {:level :warn}])) - -#?(:clj - (defn signal-catch-opts - "For use within `trace!` and `spy!`, etc." - [main-opts] - (let [catch-id-or-opts (get main-opts :catch->error) - main-opts (dissoc main-opts :catch->error) - catch-opts - (when catch-id-or-opts - (let [base ; Inherit some opts from main - (enc/assoc-some {} - :location* (get main-opts :location*) - :id (get main-opts :id))] - (cond - (true? catch-id-or-opts) (do base) - (map? catch-id-or-opts) (conj base catch-id-or-opts) - :else (conj base {:id catch-id-or-opts}))))] - - [main-opts catch-opts]))) - -(comment - (signal-catch-opts {:id :main-id, :catch->error true}) - (signal-catch-opts {:id :main-id, :catch->error :error-id}) - (signal-catch-opts {:id :main-id, :catch->error {:id :error-id}})) - ;;;; Signal macro (deftype RunResult [value error ^long run-nsecs] diff --git a/projects/main/src/taoensso/telemere/timbre.cljc b/projects/main/src/taoensso/telemere/timbre.cljc index a53130d..ec4573c 100644 --- a/projects/main/src/taoensso/telemere/timbre.cljc +++ b/projects/main/src/taoensso/telemere/timbre.cljc @@ -73,9 +73,9 @@ nil))))) (comment - (macroexpand '(trace "foo")) - (tel/with-signal :force-msg (trace "foo")) - (tel/with-signal :force-msg (infof "Hello %s" "world"))) + (macroexpand '(trace "foo")) + (tel/with-signal (trace "foo")) + (tel/with-signal (infof "Hello %s" "world"))) #?(:clj (do @@ -103,24 +103,27 @@ ([ form] (enc/keep-callsite `(spy! :debug nil ~form))) ([level form] (enc/keep-callsite `(spy! ~level nil ~form))) ([level form-name form] - (let [msg - (if-not form-name - `impl/default-trace-msg - `(fn [_form# value# error# nsecs#] - (impl/default-trace-msg ~form-name value# error# nsecs#)))] + (let [location* (enc/get-source &form &env) + msg + (if form-name + `(fn [_form# value# error# nsecs#] (impl/default-trace-msg ~form-name value# error# nsecs#)) + `(fn [_form# value# error# nsecs#] (impl/default-trace-msg '~form value# error# nsecs#)))] - (enc/keep-callsite - `(tel/spy! - {:kind :spy - :level ~level - :id shim-id - :msg ~msg - :catch->error true} + `(tel/spy! + {:location* ~location* + :id shim-id + :level ~level + :msg ~msg} + + (tel/catch->error! + {:location* ~location* + :id shim-id} ~form)))))) (comment - (select-keys (tel/with-signal :force-msg (spy! :info "my-form-name" (+ 1 2))) [:level :msg_]) - (select-keys (tel/with-signal :force-msg (spy! :info "my-form-name" (throw (Exception. "Ex")))) [:level #_:msg_])) + (:level (tel/with-signal (spy! (/ 1 0)))) + (select-keys (tel/with-signal (spy! :info #_"my-form-name" (+ 1 2))) [:level :msg_]) + (select-keys (tel/with-signal (spy! :info #_"my-form-name" (throw (Exception. "Ex")))) [:level :msg_])) #?(:clj (defmacro log-errors "Prefer `telemere/catch->error!`." [& body] (enc/keep-callsite `(tel/catch->error! {:id shim-id, :catch-val nil} (do ~@body))))) #?(:clj (defmacro log-and-rethrow-errors "Prefer `telemere/catch->error!`." [& body] (enc/keep-callsite `(tel/catch->error! {:id shim-id} (do ~@body))))) diff --git a/projects/main/test/taoensso/telemere_tests.cljc b/projects/main/test/taoensso/telemere_tests.cljc index 7c846f8..2badf70 100644 --- a/projects/main/test/taoensso/telemere_tests.cljc +++ b/projects/main/test/taoensso/telemere_tests.cljc @@ -568,42 +568,61 @@ ;;;; (deftest _common-signals - [#?(:clj - (testing "signal-opts" - [(is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :dsc [::my-id ]) {:level :info, :id ::my-id, :location* :loc*})) - (is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :dsc [::my-id :warn ]) {:level :warn, :id ::my-id, :location* :loc*})) - (is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :dsc [::my-id {:level :warn}]) {:level :warn, :id ::my-id, :location* :loc*})) + [(testing "event!" ; id + ?level => allowed? + [(let [[[rv] [sv]] (with-sigs (tel/event! :id1 )) ] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :info, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/event! :id1 :warn)) ] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/event! :id1 {:level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/event! {:id :id1, :level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/event! :id1 {:allow? false})) ] [(is (= rv nil)) (is (nil? sv))])]) - (is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :asc [ ::my-id]) {:level :info, :id ::my-id, :location* :loc*})) - (is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :asc [:warn ::my-id]) {:level :warn, :id ::my-id, :location* :loc*})) - (is (= (impl/signal-opts `foo! :loc* {:level :info} :id :level :asc [{:level :warn} ::my-id]) {:level :warn, :id ::my-id, :location* :loc*})) + (testing "log!" ; ?level + msg => allowed? + [(let [[[rv] [sv]] (with-sigs (tel/log! "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :info}))]) + (let [[[rv] [sv]] (with-sigs (tel/log! :warn "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) + (let [[[rv] [sv]] (with-sigs (tel/log! {:level :warn} "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) + (let [[[rv] [sv]] (with-sigs (tel/log! {:level :warn, :msg "msg"}))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) + (let [[[rv] [sv]] (with-sigs (tel/log! {:allow? false} "msg")) ] [(is (= rv nil)) (is (nil? sv))])]) - (is (= (impl/signal-catch-opts {:id :main-id, :location* {:ns "ns"}, :catch->error true}) [{:id :main-id, :location* {:ns "ns"}} {:location* {:ns "ns"}, :id :main-id}])) - (is (= (impl/signal-catch-opts {:id :main-id, :location* {:ns "ns"}, :catch->error :error-id}) [{:id :main-id, :location* {:ns "ns"}} {:location* {:ns "ns"}, :id :error-id}])) - (is (= (impl/signal-catch-opts {:id :main-id, :location* {:ns "ns"}, :catch->error {:id :error-id}}) [{:id :main-id, :location* {:ns "ns"}} {:location* {:ns "ns"}, :id :error-id}])) + (testing "trace!" ; ?id + run => unconditional run result (value or throw) + [(let [[[rv] [sv]] (with-sigs (tel/trace! (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id nil, :msg_ "(+ 1 2) => 3"}))]) + (let [[[rv] [sv]] (with-sigs (tel/trace! {:msg nil} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id nil, :msg_ nil}))]) + (let [[[rv] [sv]] (with-sigs (tel/trace! :id1 (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/trace! {:id :id1} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/trace! {:id :id1, :run (+ 1 2)}))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) + (let [[[_ re] [sv]] (with-sigs (tel/trace! :id1 (ex1!))) ] [(is (ex1? re)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1, :error pex1?, + :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" + :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) + (let [[[rv] [sv]] (with-sigs (tel/trace! {:allow? false} (+ 1 2))) ] [(is (= rv 3)) (is (nil? sv))]) - (is (throws? :ex-info "Invalid `foo!` args: single map arg is USUALLY a mistake" (impl/signal-opts `foo! :loc* {:level :info} :id :level :dsc [{:msg "msg"}]))) - (is (throws? :ex-info "Invalid `foo!` args: given opts should not contain `:id`" (impl/signal-opts `foo! :loc* {:level :info} :id :level :dsc [:my-id1 {:id ::my-id2}])))])) + (testing ":run-form" ; Undocumented, experimental + [(is (sm? (with-sig (tel/trace! :non-list)) {:run-form :non-list})) + (is (sm? (with-sig (tel/trace! (+ 1 2 3 4))) {:run-form '(+ 1 2 3 4)})) + (is (sm? (with-sig (tel/trace! (+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))) {:run-form '(+ ...)})) + (is (sm? (with-sig (tel/trace! {:run-form my-run-form} (+ 1 2 3 4))) {:run-form 'my-run-form :kvs nil}))]) - (testing "event!" ; id + ?level => allowed? - [(let [[[rv] [sv]] (with-sigs (tel/event! :id1 ))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :info, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/event! :id1 :warn ))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/event! :id1 {:level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/event! :id1 {:allow? false}))] [(is (= rv nil)) (is (nil? sv))])]) + (testing ":run-val" ; Undocumented, experimental + [(is (sm? (with-sig (tel/trace! (+ 2 2))) {:run-val 4, :msg_ "(+ 2 2) => 4"})) + (is (sm? (with-sig (tel/trace! {:run-val "custom"} (+ 2 2))) {:run-val "custom", :msg_ "(+ 2 2) => custom", :kvs nil}))])]) - (testing "error!" ; error + ?id => error - [(let [[[rv] [sv]] (with-sigs (tel/error! ex1))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id nil}))]) - (let [[[rv] [sv]] (with-sigs (tel/error! :id1 ex1))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/error! {:id :id1} ex1))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/error! {:allow? false} ex1))] [(is (ex1? rv)) (is (nil? sv))])]) + (testing "spy" ; ?level + run => unconditional run result (value or throw) + [(let [[[rv] [sv]] (with-sigs (tel/spy! (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :info, :msg_ "(+ 1 2) => 3"}))]) + (let [[[rv] [sv]] (with-sigs (tel/spy! {:msg nil} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :info, :msg_ nil}))]) + (let [[[rv] [sv]] (with-sigs (tel/spy! :warn (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) + (let [[[rv] [sv]] (with-sigs (tel/spy! {:level :warn} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) + (let [[[rv] [sv]] (with-sigs (tel/spy! {:level :warn, :run (+ 1 2)}))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) + (let [[[_ re] [sv]] (with-sigs (tel/spy! :warn (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn, :error pex1?, + :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" + :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) + (let [[[rv] [sv]] (with-sigs (tel/spy! {:allow? false} (+ 1 2))) ] [(is (= rv 3)) (is (nil? sv))])]) - (testing "log!" ; msg + ?level => allowed? - [(let [[[rv] [sv]] (with-sigs (tel/log! "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :info}))]) - (let [[[rv] [sv]] (with-sigs (tel/log! :warn "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) - (let [[[rv] [sv]] (with-sigs (tel/log! {:level :warn} "msg"))] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) - (let [[[rv] [sv]] (with-sigs (tel/log! {:allow? false} "msg"))] [(is (= rv nil)) (is (nil? sv))])]) + (testing "error!" ; ?id + error => unconditional given error + [(let [[[rv] [sv]] (with-sigs (tel/error! ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id nil}))]) + (let [[[rv] [sv]] (with-sigs (tel/error! :id1 ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/error! {:id :id1} ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/error! {:id :id1, :error ex1}))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) + (let [[[rv] [sv]] (with-sigs (tel/error! {:allow? false} ex1)) ] [(is (ex1? rv)) (is (nil? sv))]) + (let [c (enc/counter)] (tel/error! (do (c) ex1)) (is (= @c 1) "Error form evaluated exactly once"))]) - (testing "catch->error!" ; form + ?id => run value or ?return + (testing "catch->error!" ; ?id + run => unconditional run value or ?return [(let [[[rv re] [sv]] (with-sigs (tel/catch->error! (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) (let [[[rv re] [sv]] (with-sigs (tel/catch->error! (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id nil}))]) (let [[[rv re] [sv]] (with-sigs (tel/catch->error! :id1 (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error pex1?, :id :id1}))]) @@ -619,46 +638,6 @@ :data {:my-err my-err}} (ex1!)))] [(is (= rv nil)) (is (sm? sv {:kind :error, :data {:my-err pex1?}}))])]) - (testing "trace!" ; run + ?id => run result (value or throw) - [(let [[[rv] [sv]] (with-sigs (tel/trace! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id nil, :msg_ "(+ 1 2) => 3"}))]) - (let [[[rv] [sv]] (with-sigs (tel/trace! {:msg nil} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id nil, :msg_ nil}))]) - (let [[[rv] [sv]] (with-sigs (tel/trace! :id1 (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) - (let [[[rv] [sv]] (with-sigs (tel/trace! {:id :id1} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) - (let [[[_ re] [sv]] (with-sigs (tel/trace! :id1 (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1, :error pex1?, - :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" - :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) - (let [[[rv] [sv]] (with-sigs (tel/trace! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) - (let [[_ [sv1 sv2]] - (with-sigs (tel/trace! {:id :id1, :catch->error :id2} (ex1!)))] - [(is (sm? sv1 {:kind :trace, :line :submap/some, :level :info, :id :id1})) - (is (sm? sv2 {:kind :error, :line :submap/some, :level :error, :id :id2})) - (is (= (:location sv1) (:location sv2)) "Error inherits exact same location")]) - - (testing ":run-form" ; Undocumented, experimental - [(is (sm? (with-sig (tel/trace! :non-list)) {:run-form :non-list})) - (is (sm? (with-sig (tel/trace! (+ 1 2 3 4))) {:run-form '(+ 1 2 3 4)})) - (is (sm? (with-sig (tel/trace! (+ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))) {:run-form '(+ ...)})) - (is (sm? (with-sig (tel/trace! {:run-form my-run-form} (+ 1 2 3 4))) {:run-form 'my-run-form :kvs nil}))]) - - (testing ":run-val" ; Undocumented, experimental - [(is (sm? (with-sig (tel/trace! (+ 2 2))) {:run-val 4, :msg_ "(+ 2 2) => 4"})) - (is (sm? (with-sig (tel/trace! {:run-val "custom"} (+ 2 2))) {:run-val "custom", :msg_ "(+ 2 2) => custom", :kvs nil}))])]) - - (testing "spy" ; run + ?level => run result (value or throw) - [(let [[[rv] [sv]] (with-sigs (tel/spy! (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :info, :msg_ "(+ 1 2) => 3"}))]) - (let [[[rv] [sv]] (with-sigs (tel/spy! {:msg nil} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :info, :msg_ nil}))]) - (let [[[rv] [sv]] (with-sigs (tel/spy! :warn (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) - (let [[[rv] [sv]] (with-sigs (tel/spy! {:level :warn} (+ 1 2)))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) - (let [[[_ re] [sv]] (with-sigs (tel/spy! :warn (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn, :error pex1?, - :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" - :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) - (let [[[rv] [sv]] (with-sigs (tel/spy! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) - (let [[_ [sv1 sv2]] - (with-sigs (tel/spy! {:id :id1, :catch->error :id2} (ex1!)))] - [(is (sm? sv1 {:kind :spy, :line :submap/some, :level :info, :id :id1})) - (is (sm? sv2 {:kind :error, :line :submap/some, :level :error, :id :id2})) - (is (= (:location sv1) (:location sv2)) "Error inherits exact same location")])]) - #?(:clj (testing "uncaught->error!" (let [sv_ (atom ::nx)] @@ -769,9 +748,12 @@ (is (sm? (with-sig (timbre/info ex1 "x1" "x2")) {:kind :log, :level :info, :error pex1?, :msg_ "x1 x2", :data {:vargs ["x1" "x2"]}}) "First-arg error") - (is (sm? (with-sig (timbre/spy! :info "my-name" (+ 1 2))) {:kind :spy, :level :info, :id timbre/shim-id, :msg_ "my-name => 3", :ns pstr?})) - (is (sm? (with-sig (timbre/spy! (+ 1 2))) {:kind :spy, :level :debug, :id timbre/shim-id, :msg_ "(+ 1 2) => 3", :ns pstr?})) - (is (sm? (with-sig (timbre/spy! (ex1!))) {:kind :error, :level :error, :id timbre/shim-id, :msg_ nil, :error pex1?, :ns pstr?})) + (is (sm? (with-sig (timbre/spy! :info "my-name" (+ 1 2))) {:kind :spy, :level :info, :id timbre/shim-id, :msg_ "my-name => 3", :ns pstr?})) + (is (sm? (tel/with-min-level :debug (with-sig (timbre/spy! (+ 1 2)))) {:kind :spy, :level :debug, :id timbre/shim-id, :msg_ "(+ 1 2) => 3", :ns pstr?})) + + (let [[_ [sv1 sv2]] (tel/with-min-level :debug (with-sigs (timbre/spy! (ex1!))))] + [(is (sm? sv1 {:kind :error, :level :error, :id timbre/shim-id, :msg_ nil, :error pex1?, :ns pstr?})) + (is (sm? sv2 {:kind :spy, :level :debug, :id timbre/shim-id, :msg_ pstr? :error pex1?, :ns pstr?}))]) (let [[[rv re] [sv]] (with-sigs (timbre/log-errors (ex1!)))] [(is (nil? re)) (is (sm? sv {:kind :error, :level :error, :error pex1?, :id timbre/shim-id}))]) (let [[[rv re] [sv]] (with-sigs (timbre/log-and-rethrow-errors (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :level :error, :error pex1?, :id timbre/shim-id}))])])