[nop] Misc housekeeping

This commit is contained in:
Peter Taoussanis 2024-12-20 14:44:24 +01:00
parent cca8bb33ff
commit 7eb46ff555
8 changed files with 232 additions and 301 deletions

View file

@ -37,7 +37,8 @@ Examples:
(spy! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...} (spy! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...}
(spy! (spy!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}} :data {:x x}
:msg ["My message:" x]}
(+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...} (+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}

View file

@ -37,7 +37,8 @@ Examples:
(trace! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...} (trace! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...}
(trace! (trace!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}} :data {:x x}
:msg ["My message:" x]}
(+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...} (+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}

View file

@ -32,10 +32,6 @@
(enc/assert-min-encore-version [3 132 0]) (enc/assert-min-encore-version [3 132 0])
;;;; TODO
;; - Update Tufte (signal API, config API, signal keys, etc.)
;; - Update Timbre (signal API, config API, signal keys, backport improvements)
;;;; Shared signal API ;;;; Shared signal API
(sigs/def-api (sigs/def-api
@ -383,7 +379,6 @@
(comment (dispatch-signal! (assoc (with-signal :trap (log! "hello")) :level :warn))) (comment (dispatch-signal! (assoc (with-signal :trap (log! "hello")) :level :warn)))
;;;; Interop ;;;; Interop
#?(:clj #?(:clj

View file

@ -39,8 +39,8 @@
([signal] ([signal]
(let [^java.io.Writer stream (let [^java.io.Writer stream
(case stream (case stream
:*out* *out* (:out :*out*) *out*
:*err* *err* (:err :*err*) *err*
:auto (if (error-signal? signal) *err* *out*) :auto (if (error-signal? signal) *err* *out*)
stream)] stream)]

View file

@ -268,28 +268,20 @@
(deftype #_defrecord WrappedSignal (deftype #_defrecord WrappedSignal
;; Internal type to implement `sigs/IFilterableSignal`, ;; Internal type to implement `sigs/IFilterableSignal`,
;; incl. lazy + cached `signal-value_` field. ;; incl. lazy + cached `signal-value_` field.
[ns kind id level signal-value_] [kind ns id level signal-value_]
sigs/IFilterableSignal sigs/IFilterableSignal
(allow-signal? [_ sig-filter] (sig-filter kind ns id level)) (allow-signal? [_ sig-filter] (sig-filter kind ns id level))
(signal-debug [_] {:kind kind, :ns ns, :id id, :level level}) (signal-debug [_] {:kind kind, :ns ns, :id id, :level level})
(signal-value [_ handler-sample-rate] (signal-value [_ handler-sample-rate]
(let [sig-val (force signal-value_)] (sigs/signal-with-combined-sample-rate handler-sample-rate
(or (force signal-value_))))
(when handler-sample-rate
(when (map? sig-val)
;; Replace call sample rate with combined (call * handler) sample rate
(assoc sig-val :sample-rate
(*
(double handler-sample-rate)
(double (or (get sig-val :sample-rate) 1.0))))))
sig-val))))
(defn wrap-signal (defn wrap-signal
"Used by `taoensso.telemere/dispatch-signal!`." "Used by `taoensso.telemere/dispatch-signal!`."
[signal] [signal]
(when (map? signal) (when (map? signal)
(let [{:keys [ns kind id level]} signal] (let [{:keys [kind ns id level]} signal]
(WrappedSignal. ns kind id level signal)))) (WrappedSignal. kind ns id level signal))))
;;;; Handlers ;;;; Handlers
@ -320,7 +312,7 @@
Should delayed `:msg_` in returned signal be retained as-is? Should delayed `:msg_` in returned signal be retained as-is?
Delay is otherwise replaced by realized string. Delay is otherwise replaced by realized string.
See also `with-signals`." See also `with-signals` for more advanced options."
([ form] `(with-signal false false ~form)) ([ form] `(with-signal false false ~form))
([ trap-signals? form] `(with-signal false ~trap-signals? ~form)) ([ trap-signals? form] `(with-signal false ~trap-signals? ~form))
([raw-msg? trap-signals? form] ([raw-msg? trap-signals? form]
@ -336,7 +328,7 @@
(defmacro ^:public with-signals (defmacro ^:public with-signals
"Experimental, subject to change. "Experimental, subject to change.
Like `with-signal` but returns [[<form-value> <form-error>] [<signal1> ...]]. Like `with-signal` but returns [[<form-value> <form-error>] [<signal1> ...]].
Useful for tests/debugging." Useful for more advanced tests/debugging."
([ form] `(with-signals false false ~form)) ([ form] `(with-signals false false ~form))
([ trap-signals? form] `(with-signals false ~trap-signals? ~form)) ([ trap-signals? form] `(with-signals false ~trap-signals? ~form))
([raw-msgs? trap-signals? form] ([raw-msgs? trap-signals? form]
@ -567,238 +559,242 @@
"Generic low-level signal call, also aliased in Encore." "Generic low-level signal call, also aliased in Encore."
{:doc (signal-docstring :signal!) {:doc (signal-docstring :signal!)
:arglists (signal-arglists :signal!)} :arglists (signal-arglists :signal!)}
[opts]
(have? map? opts) ; We require const map keys, but vals may require eval
(let [defaults (enc/merge {:kind :generic, :level :info} (get opts :defaults))
opts (enc/merge defaults (dissoc opts :defaults))
cljs? (boolean (:ns &env))
clj? (not cljs?)
{run-form :run} opts
show-run-val (get opts :run-val '_run-val) ;; TODO Maybe later, once we're sure we don't want additional arities?
show-run-form ;; Remember to also update signal-arglists, shell, etc.
(when run-form ;; ([arg1 & more] (enc/keep-callsite `(signal! ~(apply hash-map arg1 more))))
(get opts :run-form ([opts]
(if (and (have? map? opts) ; We require const map keys, but vals may require eval
(enc/list-form? run-form) (let [defaults (enc/merge {:kind :generic, :level :info} (get opts :defaults))
(> (count run-form) 1) opts (enc/merge defaults (dissoc opts :defaults))
(> (count (str run-form)) 32)) cljs? (boolean (:ns &env))
(list (first run-form) '...) clj? (not cljs?)
(do run-form)))) {run-form :run} opts
{:keys [#_expansion-id location elide? allow?]} show-run-val (get opts :run-val '_run-val)
(sigs/filterable-expansion show-run-form
{:sf-arity 4 (when run-form
:ct-sig-filter ct-sig-filter (get opts :run-form
:*rt-sig-filter* `*rt-sig-filter*} (if (and
(enc/list-form? run-form)
(> (count run-form) 1)
(> (count (str run-form)) 32))
(list (first run-form) '...)
(do run-form))))
(assoc opts {:keys [#_expansion-id location elide? allow?]}
:location* (get opts :location* (enc/get-source &form &env)) (sigs/filterable-expansion
:bound-forms {:sf-arity 4
{:kind '__kind :ct-sig-filter ct-sig-filter
:ns '__ns :*rt-sig-filter* `*rt-sig-filter*}
:id '__id
:level '__level}))]
(if elide? (assoc opts
run-form :location* (get opts :location* (enc/get-source &form &env))
(let [{ns-form :ns :bound-forms
line-form :line {:kind '__kind
column-form :column :ns '__ns
file-form :file} location :id '__id
:level '__level}))]
{inst-form :inst (if elide?
level-form :level run-form
kind-form :kind (let [{ns-form :ns
id-form :id} opts line-form :line
column-form :column
file-form :file} location
trace? (get opts :trace? (boolean run-form)) {inst-form :inst
_ level-form :level
(when-not (contains? #{true false nil} trace?) kind-form :kind
(enc/unexpected-arg! trace? id-form :id} opts
{:msg "Expected constant (compile-time) `:trace?` boolean"
:context `signal!}))
thread-form (when clj? `(enc/thread-info)) trace? (get opts :trace? (boolean run-form))
_
(when-not (contains? #{true false nil} trace?)
(enc/unexpected-arg! trace?
{:msg "Expected constant (compile-time) `:trace?` boolean"
:context `signal!}))
inst-form (get opts :inst :auto) thread-form (when clj? `(enc/thread-info))
inst-form (auto-> inst-form `(enc/now-inst*))
parent-form (get opts :parent `*trace-parent*) inst-form (get opts :inst :auto)
root-form0 (get opts :root `*trace-root*) inst-form (auto-> inst-form `(enc/now-inst*))
uid-form (get opts :uid (when trace? :auto)) parent-form (get opts :parent `*trace-parent*)
root-form0 (get opts :root `*trace-root*)
signal-delay-form uid-form (get opts :uid (when trace? :auto))
(let [{do-form :do
let-form :let
msg-form :msg
data-form :data
error-form :error
sample-rate-form :sample-rate} opts
let-form (or let-form '[]) signal-delay-form
msg-form (parse-msg-form msg-form) (let [{do-form :do
let-form :let
msg-form :msg
data-form :data
error-form :error
sample-rate-form :sample-rate} opts
ctx-form let-form (or let-form '[])
(if-let [ctx+ (get opts :ctx+)] msg-form (parse-msg-form msg-form)
`(taoensso.encore.signals/update-ctx taoensso.telemere/*ctx* ~ctx+)
(get opts :ctx `taoensso.telemere/*ctx*))
middleware-form ctx-form
(if-let [middleware+ (get opts :middleware+)] (if-let [ctx+ (get opts :ctx+)]
`(taoensso.telemere/comp-middleware taoensso.telemere/*middleware* ~middleware+) `(taoensso.encore.signals/update-ctx taoensso.telemere/*ctx* ~ctx+)
(get opts :middleware `taoensso.telemere/*middleware*)) (get opts :ctx `taoensso.telemere/*ctx*))
kvs-form middleware-form
(not-empty (if-let [middleware+ (get opts :middleware+)]
(dissoc opts `(taoensso.encore/comp-middleware taoensso.telemere/*middleware* ~middleware+)
:elidable? :location :location* :inst :uid :middleware :middleware+, (get opts :middleware `taoensso.telemere/*middleware*))
:sample-rate :ns :kind :id :level :filter :when #_:rate-limit #_:rate-limit-by,
:ctx :ctx+ :parent #_:trace?, :do :let :data :msg :error,
:run :run-form :run-val, :elide? :allow? #_:expansion-id :otel/context))
_ ; Compile-time validation kvs-form
(do (not-empty
(when (and run-form error-form) ; Ambiguous source of error (dissoc opts
(throw :elidable? :location :location* :inst :uid :middleware :middleware+,
(ex-info "Signals cannot have both `:run` and `:error` opts at the same time" :sample-rate :ns :kind :id :level :filter :when #_:rate-limit #_:rate-limit-by,
{:run-form run-form :ctx :ctx+ :parent #_:trace?, :do :let :data :msg :error,
:error-form error-form :run :run-form :run-val, :elide? :allow? #_:expansion-id :otel/context))
:location location
:other-opts (dissoc opts :run :error)})))
(when-let [e (find opts :msg_)] ; Common typo/confusion _ ; Compile-time validation
(throw (do
(ex-info "Signals cannot have `:msg_` opt (did you mean `:msg`?))" (when (and run-form error-form) ; Ambiguous source of error
{:msg_ (enc/typed-val (val e))})))) (throw
(ex-info "Signals cannot have both `:run` and `:error` opts at the same time"
{:run-form run-form
:error-form error-form
:location location
:other-opts (dissoc opts :run :error)})))
signal-form (when-let [e (find opts :msg_)] ; Common typo/confusion
(let [record-form (throw
(let [clause [(if run-form :run :no-run) (if clj? :clj :cljs)]] (ex-info "Signals cannot have `:msg_` opt (did you mean `:msg`?))"
(case clause {:msg_ (enc/typed-val (val e))}))))
[: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 :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)
[: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 :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)
(enc/unexpected-arg! clause {:context :signal-constructor-args})))
record-form signal-form
(if-not run-form (let [record-form
record-form (let [clause [(if run-form :run :no-run) (if clj? :clj :cljs)]]
`(let [~(with-meta '_run-result {:tag `RunResult}) ~'__run-result (case clause
~'_run-nsecs (.-run-nsecs ~'_run-result) [: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-val (.-value ~'_run-result) [: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-err (.-error ~'_run-result) [: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)
~'_end-inst (inst+nsecs ~'__inst ~'_run-nsecs) [: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)
~'_msg_ (enc/unexpected-arg! clause {:context :signal-constructor-args})))
(let [mf# ~msg-form]
(if (fn? mf#) ; Undocumented, handy for `trace!`/`spy!`, etc.
(delay (mf# '~show-run-form ~show-run-val ~'_run-err ~'_run-nsecs))
mf#))]
~record-form))]
(if-not kvs-form record-form
record-form (if-not run-form
`(let [signal# ~record-form] record-form
(reduce-kv assoc signal# (.-kvs signal#)))))] `(let [~(with-meta '_run-result {:tag `RunResult}) ~'__run-result
~'_run-nsecs (.-run-nsecs ~'_run-result)
~'_run-val (.-value ~'_run-result)
~'_run-err (.-error ~'_run-result)
~'_end-inst (inst+nsecs ~'__inst ~'_run-nsecs)
~'_msg_
(let [mf# ~msg-form]
(if (fn? mf#) ; Undocumented, handy for `trace!`/`spy!`, etc.
(delay (mf# '~show-run-form ~show-run-val ~'_run-err ~'_run-nsecs))
mf#))]
~record-form))]
`(enc/bound-delay (if-not kvs-form
;; Delay (cache) shared by all handlers, incl. `:let` eval, record-form
;; signal construction, middleware, etc. Throws caught by handler. `(let [signal# ~record-form]
~do-form (reduce-kv assoc signal# (.-kvs signal#)))))]
(let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc.
signal# ~signal-form]
;; Final unwrapped signal value visible to users/handler-fns, allow to throw `(enc/bound-delay
(if-let [sig-middleware# ~middleware-form] ;; Delay (cache) shared by all handlers, incl. `:let` eval,
(sig-middleware# signal#) ; Apply signal middleware, can throw ;; signal construction, middleware, etc. Throws caught by handler.
(do signal#))))) ~do-form
(let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc.
signal# ~signal-form]
;; Trade-off: avoid double `run-form` expansion ;; Final unwrapped signal value visible to users/handler-fns, allow to throw
run-fn-form (when run-form `(fn [] ~run-form)) (if-let [sig-middleware# ~middleware-form]
run-form* (when run-form `(~'__run-fn-form)) (sig-middleware# signal#) ; Apply signal middleware, can throw
(do signal#)))))
into-let-form ;; Trade-off: avoid double `run-form` expansion
(enc/cond! run-fn-form (when run-form `(fn [] ~run-form))
(not trace?) ; Don't trace run-form* (when run-form `(~'__run-fn-form))
`[~'__otel-context1 nil
~'__uid ~(auto-> uid-form `(taoensso.telemere/*uid-fn* (if ~'__root0 false true)))
~'__root1 ~'__root0 ; Retain, but don't establish
~'__run-result
~(when run-form
`(let [t0# (enc/now-nano*)]
(enc/try*
(do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#)))
(catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#))))))]
;; Trace without OpenTelemetry into-let-form
(or cljs? (not enabled:otel-tracing?)) (enc/cond!
`[~'__otel-context1 nil (not trace?) ; Don't trace
~'__uid ~(auto-> uid-form `(taoensso.telemere/*uid-fn* (if ~'__root0 false true))) `[~'__otel-context1 nil
~'__root1 (or ~'__root0 ~(when trace? `{:id ~'__id, :uid ~'__uid})) ~'__uid ~(auto-> uid-form `(taoensso.telemere/*uid-fn* (if ~'__root0 false true)))
~'__run-result ~'__root1 ~'__root0 ; Retain, but don't establish
~(when run-form ~'__run-result
`(binding [*trace-root* ~'__root1 ~(when run-form
*trace-parent* {:id ~'__id, :uid ~'__uid}] `(let [t0# (enc/now-nano*)]
(let [t0# (enc/now-nano*)] (enc/try*
(enc/try* (do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#)))
(do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#))) (catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#))))))]
(catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#)))))))]
;; Trace with OpenTelemetry ;; Trace without OpenTelemetry
(and clj? enabled:otel-tracing?) (or cljs? (not enabled:otel-tracing?))
`[~'__otel-context0 ~(get opts :otel/context `(otel-context)) ; Context `[~'__otel-context1 nil
~'__otel-context1 ~(if run-form `(otel-context+span ~'__id ~'__inst ~'__otel-context0) ~'__otel-context0) ~'__uid ~(auto-> uid-form `(taoensso.telemere/*uid-fn* (if ~'__root0 false true)))
~'__uid ~(auto-> uid-form `(or (otel-span-id ~'__otel-context1) (com.taoensso.encore.Ids/genHexId16))) ~'__root1 (or ~'__root0 ~(when trace? `{:id ~'__id, :uid ~'__uid}))
~'__root1 ~'__run-result
(or ~'__root0 ~(when run-form
~(when trace? `(binding [*trace-root* ~'__root1
`{:id ~'__id, :uid (or (otel-trace-id ~'__otel-context1) (com.taoensso.encore.Ids/genHexId32))})) *trace-parent* {:id ~'__id, :uid ~'__uid}]
(let [t0# (enc/now-nano*)]
(enc/try*
(do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#)))
(catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#)))))))]
~'__run-result ;; Trace with OpenTelemetry
~(when run-form (and clj? enabled:otel-tracing?)
`(binding [*otel-context* ~'__otel-context1 `[~'__otel-context0 ~(get opts :otel/context `(otel-context)) ; Context
*trace-root* ~'__root1 ~'__otel-context1 ~(if run-form `(otel-context+span ~'__id ~'__inst ~'__otel-context0) ~'__otel-context0)
*trace-parent* {:id ~'__id, :uid ~'__uid}] ~'__uid ~(auto-> uid-form `(or (otel-span-id ~'__otel-context1) (com.taoensso.encore.Ids/genHexId16)))
(let [otel-scope# (.makeCurrent ~'__otel-context1) ~'__root1
t0# (enc/now-nano*)] (or ~'__root0
(enc/try* ~(when trace?
(do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#))) `{:id ~'__id, :uid (or (otel-trace-id ~'__otel-context1) (com.taoensso.encore.Ids/genHexId32))}))
(catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#)))
(finally (.close otel-scope#))))))])
final-form ~'__run-result
;; Unless otherwise specified, allow errors to throw on call ~(when run-form
`(let [~'__run-fn-form ~run-fn-form `(binding [*otel-context* ~'__otel-context1
~'__kind ~kind-form *trace-root* ~'__root1
~'__ns ~ns-form *trace-parent* {:id ~'__id, :uid ~'__uid}]
~'__id ~id-form (let [otel-scope# (.makeCurrent ~'__otel-context1)
~'__level ~level-form] t0# (enc/now-nano*)]
(enc/try*
(do (RunResult. ~run-form* nil (- (enc/now-nano*) t0#)))
(catch :all t# (RunResult. nil t# (- (enc/now-nano*) t0#)))
(finally (.close otel-scope#))))))])
(enc/if-not ~allow? final-form
~run-form* ;; Unless otherwise specified, allow errors to throw on call
(let [~'__inst ~inst-form `(let [~'__run-fn-form ~run-fn-form
~'__thread ~thread-form ~'__kind ~kind-form
~'__root0 ~root-form0 ; ?{:keys [id uid]} ~'__ns ~ns-form
~'__id ~id-form
~'__level ~level-form]
~@into-let-form ; Inject conditional bindings (enc/if-not ~allow?
signal# ~signal-delay-form] ~run-form*
(let [~'__inst ~inst-form
~'__thread ~thread-form
~'__root0 ~root-form0 ; ?{:keys [id uid]}
(dispatch-signal! ~@into-let-form ; Inject conditional bindings
;; Unconditionally send same wrapped signal to all handlers. signal# ~signal-delay-form]
;; Each handler will use wrapper for handler filtering,
;; unwrapping (realizing) only allowed signals.
(WrappedSignal. ~'__ns ~'__kind ~'__id ~'__level signal#))
(if ~'__run-result (dispatch-signal!
( ~'__run-result signal#) ;; Unconditionally send same wrapped signal to all handlers.
true))))] ;; Each handler will use wrapper for handler filtering,
;; unwrapping (realizing) only allowed signals.
(WrappedSignal. ~'__kind ~'__ns ~'__id ~'__level signal#))
(if-let [iife-wrap? true #_cljs?] (if ~'__run-result
;; Small perf hit to improve compatibility within `go` and other IOC-style bodies ( ~'__run-result signal#)
`((fn [] ~final-form)) true))))]
(do final-form)))))))
(if-let [iife-wrap? true #_cljs?]
;; Small perf hit to improve compatibility within `go` and other IOC-style bodies
`((fn [] ~final-form))
(do final-form))))))))
(comment (comment
(with-signal (signal! {:level :warn :let [x :x] :msg ["Test" "message" x] :data {:a :A :x x} :run (+ 1 2)})) (with-signal (signal! {:level :warn :let [x :x] :msg ["Test" "message" x] :data {:a :A :x x} :run (+ 1 2)}))

View file

@ -2,7 +2,8 @@
"Email handler using `postal`, "Email handler using `postal`,
Ref. <https://github.com/drewr/postal>." Ref. <https://github.com/drewr/postal>."
(:require (:require
[taoensso.encore :as enc :refer [have have?]] [taoensso.encore :as enc]
[taoensso.encore.signals :as sigs]
[taoensso.telemere.utils :as utils] [taoensso.telemere.utils :as utils]
[postal.core :as postal])) [postal.core :as postal]))
@ -32,9 +33,9 @@
sb (enc/str-builder) sb (enc/str-builder)
s+spc (enc/sb-appender sb " ")] s+spc (enc/sb-appender sb " ")]
(when level (s+spc (utils/format-level level))) (when level (s+spc (sigs/format-level level)))
(when kind (s+spc (utils/upper-qn kind))) (when kind (s+spc (sigs/upper-qn kind)))
(when id (s+spc (utils/format-id nil id))) (when id (s+spc (sigs/format-id nil id)))
(when-let [msg (force msg_)] (s+spc "- " msg)) (when-let [msg (force msg_)] (s+spc "- " msg))
(enc/substr (str sb) 0 max-len)))))) (enc/substr (str sb) 0 max-len))))))

View file

@ -4,7 +4,8 @@
(:require (:require
[clojure.string :as str] [clojure.string :as str]
#?(:clj [clojure.java.io :as jio]) #?(:clj [clojure.java.io :as jio])
[taoensso.encore :as enc :refer [have have?]] [taoensso.encore :as enc]
[taoensso.encore.signals :as sigs]
[taoensso.telemere.impl :as impl])) [taoensso.telemere.impl :as impl]))
(comment (comment
@ -12,61 +13,9 @@
(remove-ns (symbol (str *ns*))) (remove-ns (symbol (str *ns*)))
(:api (enc/interns-overview))) (:api (enc/interns-overview)))
;;;; Private ;;;;
(enc/def* ^:no-doc upper-qn ;; (enc/defalias sigs/upper-qn sigs/format-level sigs/format-id sigs/format-location)
"Private, don't use.
`:foo/bar` -> \"FOO/BAR\", etc."
{:tag #?(:clj 'String :cljs 'string)}
(enc/fmemoize (fn [x] (str/upper-case (enc/as-qname x)))))
(comment (upper-qn :foo/bar))
(enc/def* ^:no-doc format-level
"Private, don't use.
`:info` -> \"INFO\",
`5` -> \"LEVEL:5\", etc."
{:tag #?(:clj 'String :cljs 'string)}
(enc/fmemoize
(fn [x]
(if (keyword? x)
(upper-qn x)
(str "LEVEL:" x)))))
(comment (format-level :info))
(enc/def* ^:no-doc format-id
"Private, don't use.
`:foo.bar/baz` -> \"::baz\", etc."
{:tag #?(:clj 'String :cljs 'string)}
(enc/fmemoize
(fn [ns x]
(if (keyword? x)
(if (= (namespace x) ns)
(str "::" (name x))
(str x))
(str x)))))
(comment
(format-id (str *ns*) ::id1)
(format-id nil ::id1))
(enc/def* ^:private format-location
"Private, don't use.
Returns \"<ns/file>(<line>,<column>)\", etc."
{:tag #?(:clj 'String :cljs 'string)}
(enc/fmemoize
(fn [ns line column file]
(when-let [base (or ns file)]
(if line
(if column
(str base "(" line "," column ")")
(str base "(" line ")"))
base)))))
(comment
(format-location "my-ns" 120 8 nil)
(format-location nil 120 8 *file*))
;;;; Unique IDs (UIDs) ;;;; Unique IDs (UIDs)
@ -573,9 +522,9 @@
s+spc (enc/sb-appender sb " ")] s+spc (enc/sb-appender sb " ")]
(when inst (when-let [ff format-inst-fn] (s+spc (ff inst)))) (when inst (when-let [ff format-inst-fn] (s+spc (ff inst))))
(when level (s+spc (format-level level))) (when level (s+spc (sigs/format-level level)))
(if kind (s+spc (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` ;; As `format-location`
@ -587,7 +536,7 @@
(when-let [c (get signal :column)] (s+ "," c)) (when-let [c (get signal :column)] (s+ "," c))
(s+ ")")))) (s+ ")"))))
(when id (s+spc (format-id ns id))) (when id (s+spc (sigs/format-id ns id)))
(when-let [msg (force msg_)] (s+spc "- " msg)) (when-let [msg (force msg_)] (s+spc "- " msg))
(when-not (zero? (enc/sb-length sb)) (when-not (zero? (enc/sb-length sb))
@ -595,13 +544,11 @@
(comment ((signal-preamble-fn) (tel/with-signal (tel/event! ::ev-id)))) (comment ((signal-preamble-fn) (tel/with-signal (tel/event! ::ev-id))))
(defn- not-empty-coll [x] (when x (if (coll? x) (not-empty x) x)))
(defn signal-content-fn (defn signal-content-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn content [signal]) that: Returns a (fn content [signal]) that:
- Takes a Telemere signal (map). - Takes a Telemere signal (map).
- Returns a signal content ?string (incl. data, ctx, etc.). - Returns a human-readable signal content ?string (incl. data, ctx, etc.).
Options: Options:
`:raw-error?` - Retain unformatted error? (default false) `:raw-error?` - Retain unformatted error? (default false)
@ -644,9 +591,9 @@
(when (and parent root) (af " root: " (vf (dissoc root :inst)))) ; {:keys [id uid]} (when (and parent root) (af " root: " (vf (dissoc root :inst)))) ; {:keys [id uid]}
#?(:clj (when (and host incl-host?) (af " host: " (vf host)))) ; {:keys [ name ip]} #?(:clj (when (and host incl-host?) (af " host: " (vf host)))) ; {:keys [ name ip]}
#?(:clj (when (and thread incl-thread?) (af " thread: " (vf thread)))) ; {:keys [group name id]} #?(:clj (when (and thread incl-thread?) (af " thread: " (vf thread)))) ; {:keys [group name id]}
(when (not-empty-coll data) (af " data: " (vf data))) (when (enc/not-empty-coll data) (af " data: " (vf data)))
(when (and kvs incl-kvs?) (af " kvs: " (vf kvs))) (when (and kvs incl-kvs?) (af " kvs: " (vf kvs)))
(when (not-empty-coll ctx) (af " ctx: " (vf ctx)))) (when (enc/not-empty-coll ctx) (af " ctx: " (vf ctx))))
(let [{:keys [run-form error]} signal] (let [{:keys [run-form error]} signal]
(when run-form (when run-form

View file

@ -785,17 +785,7 @@
;;;; Utils ;;;; Utils
(deftest _utils (deftest _utils
[(testing "Basic utils" [(testing "error-signal?"
[(is (= (utils/upper-qn :foo/bar) "FOO/BAR"))
(is (= (utils/format-level :info) "INFO"))
(is (= (utils/format-level 8) "LEVEL:8"))
(is (= (utils/format-id "foo.bar" :foo.bar/qux) "::qux"))
(is (= (utils/format-id "foo.baz" :foo.bar/qux) ":foo.bar/qux"))
(is (= (utils/format-id nil :foo.bar/qux) ":foo.bar/qux"))])
(testing "error-signal?"
[(is (= (utils/error-signal? {:error nil}) false)) [(is (= (utils/error-signal? {:error nil}) false))
(is (= (utils/error-signal? {:error ex1}) true)) (is (= (utils/error-signal? {:error ex1}) true))
(is (= (utils/error-signal? {:kind :error}) true)) (is (= (utils/error-signal? {:kind :error}) true))