mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-16 17:41:12 +00:00
[new] Refactor impln of common signal creators
Objectives:
- Support single map opts arg in all cases.
- Make it easier for folks to inspect the source to understand how
the common creators use/wrap underlying `signal!`.
Also updated relevant docstrings, etc.
This commit is contained in:
parent
ace6e2dd2c
commit
d2386d62f1
12 changed files with 265 additions and 376 deletions
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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!`, ...)
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <id-or-opts> 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 <id-or-opts> 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!
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)))))
|
||||
|
|
|
|||
|
|
@ -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}))])])
|
||||
|
|
|
|||
Loading…
Reference in a new issue