[mod] Signal content: drop :location, add :coords

This is a BREAKING change to get in before v1 final.

Signal keys BEFORE this commit:
  `:location` ---- ?{:keys [ns file line column]} signal creator callsite
  `:ns` ---------- ?str namespace of signal creator callsite, same as (:ns     location)
  `:line` -------- ?int line      of signal creator callsite, same as (:line   location)
  `:column` ------ ?int column    of signal creator callsite, same as (:column location)
  `:file` -------- ?str filename  of signal creator callsite, same as (:file   location)

Signal keys AFTER this commit:
  `:ns` ---------- ?str namespace of signal creator callsite
  `:coords` ------ ?[line column] of signal creator callsite

Motivation for the breaking change:

  The new callsite schema is simpler to use/override, reduces noise, and can reduce
  code expansion size (and so Cljs build size).

  - `:file` was rarely useful, but often added large embedded strings.
  - `:location` was redundant, and often difficult for Closure's
    advanced build to properly de-duplicate.

  This schema will be shared by Truss v2 and Tufte v3.
This commit is contained in:
Peter Taoussanis 2025-02-26 17:47:58 +01:00
parent bb715fb206
commit 1f99f7186b
6 changed files with 78 additions and 88 deletions

View file

@ -23,11 +23,8 @@ Default signal keys:
`:parent` ------ ?{:keys [id uid]} of parent signal, present in nested signals when tracing `:parent` ------ ?{:keys [id uid]} of parent signal, present in nested signals when tracing
`:root` -------- ?{:keys [id uid]} of root signal, present in nested signals when tracing `:root` -------- ?{:keys [id uid]} of root signal, present in nested signals when tracing
`:location` ---- ?{:keys [ns file line column]} signal creator callsite `:ns` ---------- ?str namespace of signal creator callsite
`:ns` ---------- ?str namespace of signal creator callsite, same as (:ns location) `:coords` ------ ?[line column] of signal creator callsite
`:line` -------- ?int line of signal creator callsite, same as (:line location)
`:column` ------ ?int column of signal creator callsite, same as (:column location)
`:file` -------- ?str filename of signal creator callsite, same as (:file location)
`:host` -------- (Clj only) {:keys [name ip]} info for network host `:host` -------- (Clj only) {:keys [name ip]} info for network host
`:thread` ------ (Clj only) {:keys [name id group]} info for thread that created signal `:thread` ------ (Clj only) {:keys [name id group]} info for thread that created signal

View file

@ -248,8 +248,8 @@
(defrecord Signal (defrecord Signal
;; Telemere's main public data type, we avoid nesting and duplication ;; Telemere's main public data type, we avoid nesting and duplication
[schema inst uid, [schema inst uid, ns coords,
location ns line column file, #?@(:clj [host thread _otel-context]), #?@(:clj [host thread _otel-context]),
sample-rate, kind id level, ctx parent root, data kvs msg_, sample-rate, kind id level, ctx parent root, data kvs msg_,
error run-form run-val end-inst run-nsecs] error run-form run-val end-inst run-nsecs]
@ -556,6 +556,8 @@
column-form :column column-form :column
file-form :file} location file-form :file} location
coords (when line-form [line-form column-form])
{inst-form :inst {inst-form :inst
level-form :level level-form :level
kind-form :kind kind-form :kind
@ -625,10 +627,10 @@
(let [record-form (let [record-form
(let [clause [(if run-form :run :no-run) (if clj? :clj :cljs)]] (let [clause [(if run-form :run :no-run) (if clj? :clj :cljs)]]
(case clause (case clause
[:run :clj ] `(Signal. 1 ~'__inst ~'__uid, ~location ~'__ns ~line-form ~column-form ~file-form, (enc/host-info) ~'__thread ~'__otel-context1, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~'_msg_, ~'_run-err '~show-run-form ~show-run-val ~'_end-inst ~'_run-nsecs) [:run :clj ] `(Signal. 1 ~'__inst ~'__uid, ~'__ns ~coords (enc/host-info) ~'__thread ~'__otel-context1, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~'_msg_, ~'_run-err '~show-run-form ~show-run-val ~'_end-inst ~'_run-nsecs)
[:run :cljs] `(Signal. 1 ~'__inst ~'__uid, ~location ~'__ns ~line-form ~column-form ~file-form, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~'_msg_, ~'_run-err '~show-run-form ~show-run-val ~'_end-inst ~'_run-nsecs) [:run :cljs] `(Signal. 1 ~'__inst ~'__uid, ~'__ns ~coords ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~'_msg_, ~'_run-err '~show-run-form ~show-run-val ~'_end-inst ~'_run-nsecs)
[:no-run :clj ] `(Signal. 1 ~'__inst ~'__uid, ~location ~'__ns ~line-form ~column-form ~file-form, (enc/host-info) ~'__thread ~'__otel-context1, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~msg-form, ~error-form nil nil nil nil) [:no-run :clj ] `(Signal. 1 ~'__inst ~'__uid, ~'__ns ~coords (enc/host-info) ~'__thread ~'__otel-context1, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~msg-form, ~error-form nil nil nil nil)
[:no-run :cljs] `(Signal. 1 ~'__inst ~'__uid, ~location ~'__ns ~line-form ~column-form ~file-form, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~msg-form, ~error-form nil nil nil nil) [:no-run :cljs] `(Signal. 1 ~'__inst ~'__uid, ~'__ns ~coords ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form ~'__root1, ~data-form ~kvs-form ~msg-form, ~error-form nil nil nil nil)
(truss/unexpected-arg! clause {:context :signal-constructor-args}))) (truss/unexpected-arg! clause {:context :signal-constructor-args})))
record-form record-form

View file

@ -164,11 +164,12 @@
(when data ; Non-standard (when data ; Non-standard
(merge-attrs! ab "exception.data" data))) (merge-attrs! ab "exception.data" data)))
(let [{:keys [ns line column]} signal] (let [ns (get signal :ns)]
;; All standard ;; All standard
(put-attr! ab "code.namespace" ns) (put-attr! ab "code.namespace" ns)
(put-attr! ab "code.line.number" line) (when-let [[line column] (get signal :coords)]
(put-attr! ab "code.column.number" column)) (when line (put-attr! ab "code.line.number" line))
(when column (put-attr! ab "code.column.number" column))))
(let [{:keys [kind id uid]} signal] (let [{:keys [kind id uid]} signal]
(put-attr! ab "kind" kind) (put-attr! ab "kind" kind)

View file

@ -16,7 +16,7 @@
;;;; ;;;;
(enc/defaliases #_sigs/upper-qn sigs/format-level sigs/format-id sigs/format-location) (enc/defaliases #_sigs/upper-qn sigs/format-level sigs/format-id)
;;;; Unique IDs (UIDs) ;;;; Unique IDs (UIDs)
@ -509,7 +509,7 @@
Returns a (fn preamble [signal]) that: Returns a (fn preamble [signal]) that:
- Takes a Telemere signal (map). - Takes a Telemere signal (map).
- Returns a signal preamble ?string like: - Returns a signal preamble ?string like:
\"2024-03-26T11:14:51.806Z INFO EVENT Hostname taoensso.telemere(2,21) ::ev-id msg\" \"2024-03-26T11:14:51.806Z INFO EVENT Hostname taoensso.telemere[2,21] ::ev-id msg\"
Options: Options:
`:format-inst-fn` - (fn format [instant]) => string. `:format-inst-fn` - (fn format [instant]) => string.
@ -532,14 +532,12 @@
(if kind (s+spc (sigs/upper-qn kind)) (s+spc "DEFAULT")) (if kind (s+spc (sigs/upper-qn kind)) (s+spc "DEFAULT"))
#?(:clj (s+spc (hostname))) #?(:clj (s+spc (hostname)))
;; As `format-location` (when ns
(when-let [base (or ns (get signal :file))] (enc/sb-append sb " " ns)
(let [s+ (partial enc/sb-append sb)] ; Without separator (when-let [[line column] (get signal :coords)]
(s+ " " base) (if column
(when-let [l (get signal :line)] (enc/sb-append sb "[" line "," column "]")
(s+ "(" l) (enc/sb-append sb "[" line "]"))))
(when-let [c (get signal :column)] (s+ "," c))
(s+ ")"))))
(when id (when-let [ff format-id-fn] (s+spc (ff ns id)))) (when id (when-let [ff format-id-fn] (s+spc (ff ns id))))
(enc/when-let [ff format-msg-fn (enc/when-let [ff format-msg-fn
@ -653,7 +651,7 @@
`:incl-nils?` - Include signal's keys with nil values? (default false) `:incl-nils?` - Include signal's keys with nil values? (default false)
`:incl-kvs?` - Include signal's app-level root kvs? (default false) `:incl-kvs?` - Include signal's app-level root kvs? (default false)
`:incl-keys` - Subset of signal keys to retain from those otherwise `:incl-keys` - Subset of signal keys to retain from those otherwise
excluded by default: #{:location :kvs :file :host :thread}" excluded by default: #{:kvs :host :thread}"
([] (clean-signal-fn nil)) ([] (clean-signal-fn nil))
([{:keys [incl-kvs? incl-nils? incl-keys] :as opts}] ([{:keys [incl-kvs? incl-nils? incl-keys] :as opts}]
(let [assoc!* (let [assoc!*
@ -661,11 +659,9 @@
(fn [m k v] (if (nil? v) m (assoc! m k v))) ; As `remove-signal-nils` (fn [m k v] (if (nil? v) m (assoc! m k v))) ; As `remove-signal-nils`
(do assoc!)) (do assoc!))
incl-location? (contains? incl-keys :location) incl-kvs-key? (contains? incl-keys :kvs)
incl-kvs-key? (contains? incl-keys :kvs) incl-host? (contains? incl-keys :host)
incl-file? (contains? incl-keys :file) incl-thread? (contains? incl-keys :thread)]
incl-host? (contains? incl-keys :host)
incl-thread? (contains? incl-keys :thread)]
(fn clean-signal [signal] (fn clean-signal [signal]
(when (map? signal) (when (map? signal)
@ -677,7 +673,7 @@
(clojure.core/into () (clojure.core/into ()
(clojure.core/disj (clojure.core/disj
taoensso.telemere.impl/standard-signal-keys taoensso.telemere.impl/standard-signal-keys
:msg_ :error :location :kvs :file :host :thread)) :msg_ :error :kvs :host :thread))
(assoc!* m k v) (assoc!* m k v)
;; Main keys to include with modified val ;; Main keys to include with modified val
@ -689,11 +685,9 @@
taoensso.telemere.impl/impl-signal-keys) m ; noop taoensso.telemere.impl/impl-signal-keys) m ; noop
;;; Other keys to exclude by default ;;; Other keys to exclude by default
:location (if incl-location? (assoc!* m k v) m) :kvs (if incl-kvs-key? (assoc!* m k v) m)
:kvs (if incl-kvs-key? (assoc!* m k v) m) :thread (if incl-thread? (assoc!* m k v) m)
:file (if incl-file? (assoc!* m k v) m) :host (if incl-host? (assoc!* m k v) m)
:thread (if incl-thread? (assoc!* m k v) m)
:host (if incl-host? (assoc!* m k v) m)
;; Other (app-level) keys ;; Other (app-level) keys
(enc/cond (enc/cond

View file

@ -76,6 +76,8 @@
"x y nil [\"z1\" nil \"z2\" \"z3\"] s1 nil s2 s3 s4 :kw"))]) "x y nil [\"z1\" nil \"z2\" \"z3\"] s1 nil s2 s3 s4 :kw"))])
(defn coords? [x] (and (vector? x) (let [[line column] x] (and (enc/nat-int? line) (enc/nat-int? column)))))
(deftest _signal-macro (deftest _signal-macro
[(is (= (with-sigs (sig! {:level :info, :elide? true })) {:value nil}) "With compile-time elision") [(is (= (with-sigs (sig! {:level :info, :elide? true })) {:value nil}) "With compile-time elision")
(is (= (with-sigs (sig! {:level :info, :elide? true, :run (+ 1 2)})) {:value 3}) "With compile-time elision, run-form") (is (= (with-sigs (sig! {:level :info, :elide? true, :run (+ 1 2)})) {:value 3}) "With compile-time elision, run-form")
@ -567,26 +569,26 @@
(deftest _common-signals (deftest _common-signals
[(testing "event!" ; id + ?level => allowed? [(testing "event!" ; id + ?level => allowed?
[(let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 ))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :info, :id :id1}))]) [(let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 ))] [(is (= rv true)) (is (sm? sv {:kind :event, :coords coords?, :level :info, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 :warn)) ] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 :warn)) ] [(is (= rv true)) (is (sm? sv {:kind :event, :coords coords?, :level :warn, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 {:level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :line :submap/some, :level :warn, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 {:level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :coords coords?, :level :warn, :id :id1}))])
(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/event! {:id :id1, :level :warn}))] [(is (= rv true)) (is (sm? sv {:kind :event, :coords coords?, :level :warn, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 {:allow? false})) ] [(is (= rv nil)) (is (nil? sv))])]) (let [{rv :value, [sv] :signals} (with-sigs (tel/event! :id1 {:allow? false})) ] [(is (= rv nil)) (is (nil? sv))])])
(testing "log!" ; ?level + msg => allowed? (testing "log!" ; ?level + msg => allowed?
[(let [{rv :value, [sv] :signals} (with-sigs (tel/log! "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :info}))]) [(let [{rv :value, [sv] :signals} (with-sigs (tel/log! "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :coords coords?, :msg_ "msg", :level :info}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/log! :warn "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/log! :warn "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :coords coords?, :msg_ "msg", :level :warn}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/log! {:level :warn} "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :line :submap/some, :msg_ "msg", :level :warn}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/log! {:level :warn} "msg")) ] [(is (= rv true)) (is (sm? sv {:kind :log, :coords coords?, :msg_ "msg", :level :warn}))])
(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/log! {:level :warn, :msg "msg"}))] [(is (= rv true)) (is (sm? sv {:kind :log, :coords coords?, :msg_ "msg", :level :warn}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/log! {:allow? false} "msg")) ] [(is (= rv nil)) (is (nil? sv))])]) (let [{rv :value, [sv] :signals} (with-sigs (tel/log! {:allow? false} "msg")) ] [(is (= rv nil)) (is (nil? sv))])])
(testing "trace!" ; ?id + run => unconditional run result (value or throw) (testing "trace!" ; ?id + run => unconditional run result (value or throw)
[(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/trace! (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id nil, :msg_ "(+ 1 2) => 3"}))])
(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/trace! {:msg nil} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id nil, :msg_ nil}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/trace! :id1 (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/trace! :id1 (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id :id1}))])
(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/trace! {:id :id1} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id :id1}))])
(let [{rv :value, [sv] :signals} (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 [{rv :value, [sv] :signals} (with-sigs (tel/trace! {:id :id1, :run (+ 1 2)}))] [(is (= rv 3)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id :id1}))])
(let [{re :error, [sv] :signals} (with-sigs (tel/trace! :id1 (ex1!))) ] [(is (ex1? re)) (is (sm? sv {:kind :trace, :line :submap/some, :level :info, :id :id1, :error ex1, (let [{re :error, [sv] :signals} (with-sigs (tel/trace! :id1 (ex1!))) ] [(is (ex1? re)) (is (sm? sv {:kind :trace, :coords coords?, :level :info, :id :id1, :error ex1,
:msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo"
:cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/trace! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/trace! {:allow? false} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])
@ -594,8 +596,8 @@
(testing "Use with `catch->error!`" (testing "Use with `catch->error!`"
(let [{re :error, [sv1 sv2] :signals} (with-sigs (tel/trace! ::id1 (tel/catch->error! ::id2 (ex1!))))] (let [{re :error, [sv1 sv2] :signals} (with-sigs (tel/trace! ::id1 (tel/catch->error! ::id2 (ex1!))))]
[(is (ex1? re)) [(is (ex1? re))
(is (sm? sv1 {:kind :error, :line :submap/some, :level :error, :id ::id2, :error ex1, :parent {:id ::id1}})) (is (sm? sv1 {:kind :error, :coords coords?, :level :error, :id ::id2, :error ex1, :parent {:id ::id1}}))
(is (sm? sv2 {:kind :trace, :line :submap/some, :level :info, :id ::id1, :error ex1, :root {:id ::id1}}))])) (is (sm? sv2 {:kind :trace, :coords coords?, :level :info, :id ::id1, :error ex1, :root {:id ::id1}}))]))
(testing ":run-form" ; Undocumented, experimental (testing ":run-form" ; Undocumented, experimental
[(is (sm? (with-sig (tel/trace! :non-list)) {:run-form :non-list})) [(is (sm? (with-sig (tel/trace! :non-list)) {:run-form :non-list}))
@ -608,12 +610,12 @@
(is (sm? (with-sig (tel/trace! {:run-val "custom"} (+ 2 2))) {:run-val "custom", :msg_ "(+ 2 2) => custom", :kvs nil}))])]) (is (sm? (with-sig (tel/trace! {:run-val "custom"} (+ 2 2))) {:run-val "custom", :msg_ "(+ 2 2) => custom", :kvs nil}))])])
(testing "spy" ; ?level + run => unconditional run result (value or throw) (testing "spy" ; ?level + run => unconditional run result (value or throw)
[(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/spy! (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :coords coords?, :level :info, :msg_ "(+ 1 2) => 3"}))])
(let [{rv :value, [sv] :signals} (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 :value, [sv] :signals} (with-sigs (tel/spy! {:msg nil} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :coords coords?, :level :info, :msg_ nil}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/spy! :warn (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/spy! :warn (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :coords coords?, :level :warn}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:level :warn} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:level :warn} (+ 1 2))) ] [(is (= rv 3)) (is (sm? sv {:kind :spy, :coords coords?, :level :warn}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:level :warn, :run (+ 1 2)}))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:level :warn, :run (+ 1 2)}))] [(is (= rv 3)) (is (sm? sv {:kind :spy, :coords coords?, :level :warn}))])
(let [{re :error, [sv] :signals} (with-sigs (tel/spy! :warn (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :spy, :line :submap/some, :level :warn, :error ex1, (let [{re :error, [sv] :signals} (with-sigs (tel/spy! :warn (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :spy, :coords coords?, :level :warn, :error ex1,
:msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo" :msg_ #?(:clj "(ex1!) !> clojure.lang.ExceptionInfo"
:cljs "(ex1!) !> cljs.core/ExceptionInfo")}))]) :cljs "(ex1!) !> cljs.core/ExceptionInfo")}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:allow? false} (+ 1 2))) ] [(is (= rv 3)) (is (nil? sv))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/spy! {:allow? false} (+ 1 2))) ] [(is (= rv 3)) (is (nil? sv))])
@ -621,23 +623,23 @@
(testing "Use with `catch->error!`" (testing "Use with `catch->error!`"
(let [{re :error, [sv1 sv2] :signals} (with-sigs (tel/spy! :warn (tel/catch->error! :error (ex1!))))] (let [{re :error, [sv1 sv2] :signals} (with-sigs (tel/spy! :warn (tel/catch->error! :error (ex1!))))]
[(is (ex1? re)) [(is (ex1? re))
(is (sm? sv1 {:kind :error, :line :submap/some, :level :error, :error ex1, :parent {}})) (is (sm? sv1 {:kind :error, :coords coords?, :level :error, :error ex1, :parent {}}))
(is (sm? sv2 {:kind :spy, :line :submap/some, :level :warn, :error ex1, :root {}}))]))]) (is (sm? sv2 {:kind :spy, :coords coords?, :level :warn, :error ex1, :root {}}))]))])
(testing "error!" ; ?id + error => unconditional given error (testing "error!" ; ?id + error => unconditional given error
[(let [{rv :value, [sv] :signals} (with-sigs (tel/error! ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id nil}))]) [(let [{rv :value, [sv] :signals} (with-sigs (tel/error! ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id nil}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/error! :id1 ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/error! :id1 ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/error! {:id :id1} ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/error! {:id :id1} ex1)) ] [(is (ex1? rv)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/error! {:id :id1, :error ex1}))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/error! {:id :id1, :error ex1}))] [(is (ex1? rv)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/error! {:allow? false} ex1)) ] [(is (ex1? rv)) (is (nil? sv))]) (let [{rv :value, [sv] :signals} (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"))]) (let [c (enc/counter)] (tel/error! (do (c) ex1)) (is (= @c 1) "Error form evaluated exactly once"))])
(testing "catch->error!" ; ?id + run => unconditional run value or ?return (testing "catch->error!" ; ?id + run => unconditional run value or ?return
[(let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))]) [(let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])
(let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id nil}))]) (let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id nil}))])
(let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! :id1 (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))]) (let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! :id1 (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1}))])
(let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! {:id :id1} (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))]) (let [{re :error, [sv] :signals} (with-sigs (tel/catch->error! {:id :id1} (ex1!)))] [(is (ex1? re)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! {:catch-val :foo} (ex1!)))] [(is (= rv :foo)) (is (sm? sv {:kind :error, :line :submap/some, :level :error, :error ex1, :id nil}))]) (let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! {:catch-val :foo} (ex1!)))] [(is (= rv :foo)) (is (sm? sv {:kind :error, :coords coords?, :level :error, :error ex1, :id nil}))])
(let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! {:catch-val :foo} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])]) (let [{rv :value, [sv] :signals} (with-sigs (tel/catch->error! {:catch-val :foo} (+ 1 2)))] [(is (= rv 3)) (is (nil? sv))])])
#?(:clj #?(:clj
@ -646,13 +648,13 @@
[(do (enc/set-var-root! impl/*sig-handlers* [(sigs/wrap-handler "h1" (fn h1 [x] (reset! sv_ x)) nil {:async nil})]) :set-handler) [(do (enc/set-var-root! impl/*sig-handlers* [(sigs/wrap-handler "h1" (fn h1 [x] (reset! sv_ x)) nil {:async nil})]) :set-handler)
;; ;;
(is (nil? (tel/uncaught->error!))) (is (nil? (tel/uncaught->error!)))
(is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :line :submap/some, :level :error, :error ex1, :id nil}))) (is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :coords coords?, :level :error, :error ex1, :id nil})))
;; ;;
(is (nil? (tel/uncaught->error! :id1))) (is (nil? (tel/uncaught->error! :id1)))
(is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))) (is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1})))
;; ;;
(is (nil? (tel/uncaught->error! {:id :id1}))) (is (nil? (tel/uncaught->error! {:id :id1})))
(is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :line :submap/some, :level :error, :error ex1, :id :id1}))) (is (do (.join (enc/threaded :user (ex1!))) (sm? @sv_ {:kind :error, :coords coords?, :level :error, :error ex1, :id :id1})))
;; ;;
(do (enc/set-var-root! impl/*sig-handlers* nil) :unset-handler)])))]) (do (enc/set-var-root! impl/*sig-handlers* nil) :unset-handler)])))])
@ -664,7 +666,7 @@
(deftest _dispatch-signal! (deftest _dispatch-signal!
[(sm? (tel/with-signal (tel/dispatch-signal! (assoc (tel/with-signal :trap (tel/log! "hello")) :level :warn))) [(sm? (tel/with-signal (tel/dispatch-signal! (assoc (tel/with-signal :trap (tel/log! "hello")) :level :warn)))
{:kind :log, :level :warn, :line :submap/some})]) {:kind :log, :level :warn, :coords coords?})])
#?(:clj #?(:clj
(deftest _uncaught->handler! (deftest _uncaught->handler!
@ -701,7 +703,7 @@
:system/err {:sending->telemere? false, :telemere-receiving? false}})) :system/err {:sending->telemere? false, :telemere-receiving? false}}))
(is (sm? (with-sig (tel/with-out->telemere (println "Hello" "x" "y"))) (is (sm? (with-sig (tel/with-out->telemere (println "Hello" "x" "y")))
{:level :info, :location nil, :ns nil, :kind :system/out, :msg_ "Hello x y"}))]) {:level :info, :coords nil, :ns nil, :kind :system/out, :msg_ "Hello x y"}))])
(testing "SLF4J -> Telemere" (testing "SLF4J -> Telemere"
[(is (sm? (tel/check-interop) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}})) [(is (sm? (tel/check-interop) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}}))
@ -777,9 +779,7 @@
:id nil :id nil
:msg_ (delay "msg") :msg_ (delay "msg")
:error ex2 :error ex2
:location "loc"
:kvs "kvs" :kvs "kvs"
:file "file"
:thread "thread" :thread "thread"
:a "a" :a "a"
:b "b"}] :b "b"}]
@ -790,8 +790,7 @@
(is (= ((utils/clean-signal-fn {:incl-keys #{:kvs}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, :kvs "kvs"})) (is (= ((utils/clean-signal-fn {:incl-keys #{:kvs}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, :kvs "kvs"}))
(is (= ((utils/clean-signal-fn {:incl-keys #{:a}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, :a "a"})) (is (= ((utils/clean-signal-fn {:incl-keys #{:a}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, :a "a"}))
(is (= ((utils/clean-signal-fn {:incl-keys (is (= ((utils/clean-signal-fn {:incl-keys
#{:location :kvs :file :thread}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, #{:kvs :thread}}) sig) {:level :info, :msg_ "msg", :error ex2-chain, :kvs "kvs", :thread "thread"}))]))
:location "loc", :kvs "kvs", :file "file", :thread "thread"}))]))
(testing "Misc utils" (testing "Misc utils"
[(is (= (utils/remove-signal-kvs {:a :A, :b :B, :kvs {:b :B}}) {:a :A})) [(is (= (utils/remove-signal-kvs {:a :A, :b :B, :kvs {:b :B}}) {:a :A}))
@ -834,10 +833,10 @@
(testing "signal-preamble-fn" (testing "signal-preamble-fn"
(let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t1, :msg ["a" "b"]})) (let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t1, :msg ["a" "b"]}))
preamble ((utils/signal-preamble-fn) sig)] ; "2024-06-09T21:15:20.170Z INFO EVENT taoensso.telemere-tests(592,35) ::ev-id" preamble ((utils/signal-preamble-fn) sig)] ; "2024-06-09T21:15:20.170Z INFO EVENT taoensso.telemere-tests[592,35] ::ev-id"
[(is (enc/str-starts-with? preamble "2024-01-01T01:01:01.110Z INFO EVENT")) [(is (enc/str-starts-with? preamble "2024-01-01T01:01:01.110Z INFO EVENT"))
(is (enc/str-ends-with? preamble "::ev-id a b")) (is (enc/str-ends-with? preamble "::ev-id a b"))
(is (string? (re-find #"taoensso.telemere-tests\(\d+,\d+\)" preamble)))])) (is (string? (re-find #"taoensso.telemere-tests\[\d+,\d+\]" preamble)))]))
(testing "pr-signal-fn" (testing "pr-signal-fn"
(let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t1, :msg ["a" "b"]}))] (let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t1, :msg ["a" "b"]}))]
@ -854,8 +853,7 @@
:ns "taoensso.telemere-tests" :ns "taoensso.telemere-tests"
:msg_ "a b" :msg_ "a b"
:inst udt1 :inst udt1
:line enc/nat-int? :coords vector?}))]))
:column enc/nat-int?}))]))
#?(:cljs #?(:cljs
(testing ":json pr-fn" (testing ":json pr-fn"
@ -866,8 +864,7 @@
"level" "info", "ns" "taoensso.telemere-tests" "level" "info", "ns" "taoensso.telemere-tests"
"msg_" "a b" "msg_" "a b"
"inst" t1s "inst" t1s
"line" enc/nat-int? "coords" vector?})))))
"column" enc/nat-int?})))))
(testing "Custom pr-fn" (testing "Custom pr-fn"
(is (= ((tel/pr-signal-fn {:pr-fn (fn [_] "str")}) sig) (str "str" utils/newline))))])) (is (= ((tel/pr-signal-fn {:pr-fn (fn [_] "str")}) sig) (str "str" utils/newline))))]))
@ -1012,9 +1009,8 @@
{:kind :event {:kind :event
:level :info :level :info
:ns "ns" :ns "ns"
:line 10 :coords [10 20]
:column 20
:id ::id1 :id ::id1
:uid #uuid "7e9c1df6-78e4-40ac-8c5c-e2353df9ab82" :uid #uuid "7e9c1df6-78e4-40ac-8c5c-e2353df9ab82"

View file

@ -21,7 +21,7 @@ And they're represented by plain **Clojure/Script maps** with those attributes (
Fundamentally **all signals**: Fundamentally **all signals**:
- Occur or are observed at a particular **location** in your code (file, namespace, line, column). - Occur or are observed at a particular **location** in your code (namespace, line, column).
- Occur or are observed *within* a particular **program state** / context. - Occur or are observed *within* a particular **program state** / context.
- Convey something of value *about* that **program state** / context. - Convey something of value *about* that **program state** / context.