[nop] Misc improvements

This commit is contained in:
Peter Taoussanis 2025-03-10 22:31:54 +01:00
parent 32e8909e42
commit 248e91f982
9 changed files with 145 additions and 163 deletions

View file

@ -1,33 +1,33 @@
(ns examples (ns examples
"Basic Telemere usage examples that appear in the Wiki or docstrings." "Basic Telemere usage examples that appear in the Wiki or docstrings."
(:require [taoensso.telemere :as t])) (:require [taoensso.telemere :as tel]))
(comment (comment
;;;; README "Quick examples" ;;;; README "Quick examples"
(require '[taoensso.telemere :as t]) (require '[taoensso.telemere :as tel])
;; (Just works / no config necessary for typical use cases) ;; (Just works / no config necessary for typical use cases)
;; Without structured data ;; Without structured data
(t/log! :info "Hello world!") ; %> Basic log signal (has message) (tel/log! :info "Hello world!") ; %> Basic log signal (has message)
(t/event! ::my-id :debug) ; %> Basic event signal (just id) (tel/event! ::my-id :debug) ; %> Basic event signal (just id)
;; With structured data ;; With structured data
(t/log! {:level :info, :data {}} "Hello again!") (tel/log! {:level :info, :data {}} "Hello again!")
(t/event! ::my-id {:level :debug, :data {}}) (tel/event! ::my-id {:level :debug, :data {}})
;; Trace (auto interops with OpenTelemetry) ;; Trace (auto interops with OpenTelemetry)
;; Tracks form runtime, return value, and (nested) parent tree ;; Tracks form runtime, return value, and (nested) parent tree
(t/trace! {:id ::my-id :data {}} (tel/trace! {:id ::my-id :data {}}
(do-some-work)) (do-some-work))
;; Check resulting signal content for debug/tests ;; Check resulting signal content for debug/tests
(t/with-signal (t/event! ::my-id)) ; => {:keys [ns level id data msg_ ...]} (tel/with-signal (tel/event! ::my-id)) ; => {:keys [ns level id data msg_ ...]}
;; Getting fancy (all costs are conditional!) ;; Getting fancy (all costs are conditional!)
(t/log! (tel/log!
{:level :debug {:level :debug
:sample 0.75 ; 75% sampling (noop 25% of the time) :sample 0.75 ; 75% sampling (noop 25% of the time)
:when (my-conditional) :when (my-conditional)
@ -49,40 +49,40 @@
["Something interesting happened!" formatted]) ["Something interesting happened!" formatted])
;; Set minimum level ;; Set minimum level
(t/set-min-level! :warn) ; For all signals (tel/set-min-level! :warn) ; For all signals
(t/set-min-level! :log :debug) ; For `log!` signals only (tel/set-min-level! :log :debug) ; For `log!` signals only
;; Set namespace and id filters ;; Set namespace and id filters
(t/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"}) (tel/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"})
(t/set-id-filter! {:allow #{::my-particular-id "my-app/*"}}) (tel/set-id-filter! {:allow #{::my-particular-id "my-app/*"}})
;; Set minimum level for `event!` signals for particular ns pattern ;; Set minimum level for `event!` signals for particular ns pattern
(t/set-min-level! :event "taoensso.sente.*" :warn) (tel/set-min-level! :event "taoensso.sente.*" :warn)
;; Use transforms (xfns) to filter and/or arbitrarily modify signals ;; Use transforms (xfns) to filter and/or arbitrarily modify signals
;; by signal data/content/etc. ;; by signal data/contentel/etc.
(t/set-xfn! (tel/set-xfn!
(fn [signal] (fn [signal]
(if (-> signal :data :skip-me?) (if (-> signal :data :skip-me?)
nil ; Filter signal (don't handle) nil ; Filter signal (don't handle)
(assoc signal :transformed? true)))) (assoc signal :transformed? true))))
(t/with-signal (t/event! ::my-id {:data {:skip-me? true}})) ; => nil (tel/with-signal (tel/event! ::my-id {:data {:skip-me? true}})) ; => nil
(t/with-signal (t/event! ::my-id {:data {:skip-me? false}})) ; => {...} (tel/with-signal (tel/event! ::my-id {:data {:skip-me? false}})) ; => {...}
;; See `t/help:filters` docstring for more filtering options ;; See `tel/help:filters` docstring for more filtering options
;;;; README "More examples" ;;;; README "More examples"
;; Add your own signal handler ;; Add your own signal handler
(t/add-handler! :my-handler (tel/add-handler! :my-handler
(fn (fn
([signal] (println signal)) ([signal] (println signal))
([] (println "Handler has shut down")))) ([] (println "Handler has shut down"))))
;; Use `add-handler!` to set handler-level filtering and back-pressure ;; Use `add-handler!` to set handler-level filtering and back-pressure
(t/add-handler! :my-handler (tel/add-handler! :my-handler
(fn (fn
([signal] (println signal)) ([signal] (println signal))
([] (println "Handler has shut down"))) ([] (println "Handler has shut down")))
@ -93,79 +93,79 @@
:min-level :info :min-level :info
:ns-filter {:disallow "taoensso.*"} :ns-filter {:disallow "taoensso.*"}
:limit {"1 per sec" [1 1000]} :limit {"1 per sec" [1 1000]}
;; See `t/help:handler-dispatch-options` for more ;; See `tel/help:handler-dispatch-options` for more
}) })
;; See current handlers ;; See current handlers
(t/get-handlers) ; => {<handler-id> {:keys [handler-fn handler-stats_ dispatch-opts]}} (tel/get-handlers) ; => {<handler-id> {:keys [handler-fn handler-stats_ dispatch-opts]}}
;; Add console handler to print signals as human-readable text ;; Add console handler to print signals as human-readable text
(t/add-handler! :my-handler (tel/add-handler! :my-handler
(t/handler:console (tel/handler:console
{:output-fn (t/format-signal-fn {})})) {:output-fn (tel/format-signal-fn {})}))
;; Add console handler to print signals as edn ;; Add console handler to print signals as edn
(t/add-handler! :my-handler (tel/add-handler! :my-handler
(t/handler:console (tel/handler:console
{:output-fn (t/pr-signal-fn {:pr-fn :edn})})) {:output-fn (tel/pr-signal-fn {:pr-fn :edn})}))
;; Add console handler to print signals as JSON ;; Add console handler to print signals as JSON
;; Ref. <https://github.com/metosin/jsonista> (or any alt JSON lib) ;; Ref. <https://github.com/metosin/jsonista> (or any alt JSON lib)
#?(:clj (require '[jsonista.core :as jsonista])) #?(:clj (require '[jsonista.core :as jsonista]))
(t/add-handler! :my-handler (tel/add-handler! :my-handler
(t/handler:console (tel/handler:console
{:output-fn {:output-fn
#?(:cljs :json ; Use js/JSON.stringify #?(:cljs :json ; Use js/JSON.stringify
:clj jsonista/write-value-as-string)})) :clj jsonista/write-value-as-string)}))
;;;; Docstring examples ;;;; Docstring examples
(t/with-signal (t/event! ::my-id)) (tel/with-signal (tel/event! ::my-id))
(t/with-signal (t/event! ::my-id :warn)) (tel/with-signal (tel/event! ::my-id :warn))
(t/with-signal (tel/with-signal
(t/event! ::my-id (tel/event! ::my-id
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x} :data {:x x}
:msg ["My msg:" x]})) :msg ["My msg:" x]}))
(t/with-signal (t/log! "My msg")) (tel/with-signal (tel/log! "My msg"))
(t/with-signal (t/log! :warn "My msg")) (tel/with-signal (tel/log! :warn "My msg"))
(t/with-signal (tel/with-signal
(t/log! (tel/log!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}} :data {:x x}}
["My msg:" x])) ["My msg:" x]))
(t/with-signal (throw (t/error! (ex-info "MyEx" {})))) (tel/with-signal (throw (tel/error! (ex-info "MyEx" {}))))
(t/with-signal (throw (t/error! ::my-id (ex-info "MyEx" {})))) (tel/with-signal (throw (tel/error! ::my-id (ex-info "MyEx" {}))))
(t/with-signal (tel/with-signal
(throw (throw
(t/error! (tel/error!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x} :data {:x x}
:msg ["My msg:" x]} :msg ["My msg:" x]}
(ex-info "MyEx" {})))) (ex-info "MyEx" {}))))
(t/with-signal (t/trace! (+ 1 2))) (tel/with-signal (tel/trace! (+ 1 2)))
(t/with-signal (t/trace! ::my-id (+ 1 2))) (tel/with-signal (tel/trace! ::my-id (+ 1 2)))
(t/with-signal (tel/with-signal
(t/trace! (tel/trace!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}} :data {:x x}}
(+ 1 2))) (+ 1 2)))
(t/with-signal (t/spy! (+ 1 2))) (tel/with-signal (tel/spy! (+ 1 2)))
(t/with-signal (t/spy! :debug (+ 1 2))) (tel/with-signal (tel/spy! :debug (+ 1 2)))
(t/with-signal (tel/with-signal
(t/spy! (tel/spy!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}} :data {:x x}}
(+ 1 2))) (+ 1 2)))
(t/with-signal (t/catch->error! (/ 1 0))) (tel/with-signal (tel/catch->error! (/ 1 0)))
(t/with-signal (t/catch->error! ::my-id (/ 1 0))) (tel/with-signal (tel/catch->error! ::my-id (/ 1 0)))
(t/with-signal (tel/with-signal
(t/catch->error! (tel/catch->error!
{:let [x "x"] ; Available to `:data` and `:msg` {:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x} :data {:x x}
:msg ["My msg:" x] :msg ["My msg:" x]
@ -176,25 +176,25 @@
;;; Filter signals ;;; Filter signals
(t/set-min-level! :info) ; Set global minimum level (tel/set-min-level! :info) ; Set global minimum level
(t/with-signal (t/event! ::my-id1 :info)) ; => {:keys [inst id ...]} (tel/with-signal (tel/event! ::my-id1 :info)) ; => {:keys [inst id ...]}
(t/with-signal (t/event! ::my-id1 :debug)) ; => nil (signal not allowed) (tel/with-signal (tel/event! ::my-id1 :debug)) ; => nil (signal not allowed)
(t/with-min-level :trace ; Override global minimum level (tel/with-min-level :trace ; Override global minimum level
(t/with-signal (t/event! ::my-id1 :debug))) ; => {:keys [inst id ...]} (tel/with-signal (tel/event! ::my-id1 :debug))) ; => {:keys [inst id ...]}
;; Disallow all signals in matching namespaces ;; Disallow all signals in matching namespaces
(t/set-ns-filter! {:disallow "some.nosy.namespace.*"}) (tel/set-ns-filter! {:disallow "some.nosy.namespace.*"})
;;; Configuring handlers ;;; Configuring handlers
;; Create a test signal ;; Create a test signal
(def my-signal (def my-signal
(t/with-signal (tel/with-signal
(t/log! {:id ::my-id, :data {:x1 :x2}} "My message"))) (tel/log! {:id ::my-id, :data {:x1 :x2}} "My message")))
;; Create console handler with default opts (writes formatted string) ;; Create console handler with default opts (writes formatted string)
(def my-handler (t/handler:console {})) (def my-handler (tel/handler:console {}))
;; Test handler, remember it's just a (fn [signal]) ;; Test handler, remember it's just a (fn [signal])
(my-handler my-signal) ; %> (my-handler my-signal) ; %>
@ -203,8 +203,8 @@
;; Create console handler which writes signals as edn ;; Create console handler which writes signals as edn
(def my-handler (def my-handler
(t/handler:console (tel/handler:console
{:output-fn (t/pr-signal-fn {:pr-fn :edn})})) {:output-fn (tel/pr-signal-fn {:pr-fn :edn})}))
(my-handler my-signal) ; %> (my-handler my-signal) ; %>
;; {:inst #inst "2024-04-11T10:54:57.202869Z", :msg_ "My message", :ns "examples", ...} ;; {:inst #inst "2024-04-11T10:54:57.202869Z", :msg_ "My message", :ns "examples", ...}
@ -213,9 +213,9 @@
;; Ref. <https://github.com/metosin/jsonista> (or any alt JSON lib) ;; Ref. <https://github.com/metosin/jsonista> (or any alt JSON lib)
#?(:clj (require '[jsonista.core :as jsonista])) #?(:clj (require '[jsonista.core :as jsonista]))
(def my-handler (def my-handler
(t/handler:console (tel/handler:console
{:output-fn {:output-fn
(t/pr-signal-fn (tel/pr-signal-fn
{:pr-fn {:pr-fn
#?(:cljs :json ; Use js/JSON.stringify #?(:cljs :json ; Use js/JSON.stringify
:clj jsonista/write-value-as-string)})})) :clj jsonista/write-value-as-string)})}))
@ -224,19 +224,20 @@
;; {"inst":"2024-04-11T10:54:57.202869Z","msg_":"My message","ns":"examples", ...} ;; {"inst":"2024-04-11T10:54:57.202869Z","msg_":"My message","ns":"examples", ...}
;; Deregister the default console handler ;; Deregister the default console handler
(t/remove-handler! :default/console) (tel/remove-handler! :defaultel/console)
;; Register our custom console handler ;; Register our custom console handler
(t/add-handler! :my-handler my-handler (tel/add-handler! :my-handler my-handler
;; Lots of options here for filtering, etc. ;; Lots of options here for filtering, etc.
;; See `help:handler-dispatch-options` docstring! ;; See `help:handler-dispatch-options` docstring!
{}) {})
;; NB make sure to always stop handlers at the end of your ;; NB make sure to always stop handlers at the end of your
;; `-main` or shutdown procedure ;; `-main` or shutdown procedure
(t/call-on-shutdown! t/stop-handlers!) (tel/call-on-shutdown!
(fn [] (tel/stop-handlers!)))
;; See `t/help:handlers` docstring for more ;; See `tel/help:handlers` docstring for more
;;; Writing handlers ;;; Writing handlers
@ -298,18 +299,18 @@
;;; Message building ;;; Message building
;; A fixed message (string arg) ;; A fixed message (string arg)
(t/log! "A fixed message") ; %> {:msg "A fixed message"} (tel/log! "A fixed message") ; %> {:msg "A fixed message"}
;; A joined message (vector arg) ;; A joined message (vector arg)
(let [user-arg "Bob"] (let [user-arg "Bob"]
(t/log! ["User" (str "`" user-arg "`") "just logged in!"])) (tel/log! ["User" (str "`" user-arg "`") "just logged in!"]))
;; %> {:msg_ "User `Bob` just logged in!` ...} ;; %> {:msg_ "User `Bob` just logged in!` ...}
;; With arg prep ;; With arg prep
(let [user-arg "Bob" (let [user-arg "Bob"
usd-balance-str "22.4821"] usd-balance-str "22.4821"]
(t/log! (tel/log!
{:let {:let
[username (clojure.string/upper-case user-arg) [username (clojure.string/upper-case user-arg)
usd-balance (parse-double usd-balance-str)] usd-balance (parse-double usd-balance-str)]
@ -322,16 +323,16 @@
;; %> {:msg "User BOB has balance: $22" ...} ;; %> {:msg "User BOB has balance: $22" ...}
(t/log! (str "This message " "was built " "by `str`")) (tel/log! (str "This message " "was built " "by `str`"))
;; %> {:msg "This message was built by `str`"} ;; %> {:msg "This message was built by `str`"}
(t/log! (enc/format "This message was built by `%s`" "format")) (tel/log! (enc/format "This message was built by `%s`" "format"))
;; %> {:msg "This message was built by `format`"} ;; %> {:msg "This message was built by `format`"}
;;; App-level kvs ;;; App-level kvs
(t/with-signal (tel/with-signal
(t/event! ::my-id (tel/event! ::my-id
{:my-data-for-xfn "foo" {:my-data-for-xfn "foo"
:my-data-for-handler "bar"})) :my-data-for-handler "bar"}))
@ -346,20 +347,20 @@
;;;; Misc extra examples ;;;; Misc extra examples
(t/log! {:id ::my-id, :data {:x1 :x2}} ["My 2-part" "message"]) ; %> (tel/log! {:id ::my-id, :data {:x1 :x2}} ["My 2-part" "message"]) ; %>
;; 2024-04-11T10:54:57.202869Z INFO LOG MyHost examples(56,1) ::my-id - My 2-part message ;; 2024-04-11T10:54:57.202869Z INFO LOG MyHost examples(56,1) ::my-id - My 2-part message
;; data: {:x1 :x2} ;; data: {:x1 :x2}
;; `:let` bindings are available to `:data` and message, but only paid ;; `:let` bindings are available to `:data` and message, but only paid
;; for when allowed by minimum level and other filtering criteria ;; for when allowed by minimum level and other filtering criteria
(t/log! (tel/log!
{:level :info {:level :info
:let [expensive (reduce * (range 1 12))] ; 12 factorial :let [expensive (reduce * (range 1 12))] ; 12 factorial
:data {:my-metric expensive}} :data {:my-metric expensive}}
["Message with metric:" expensive]) ["Message with metric:" expensive])
;; With sampling 50% and 1/sec rate limiting ;; With sampling 50% and 1/sec rate limiting
(t/log! (tel/log!
{:sample 0.5 {:sample 0.5
:limit {"1 per sec" [1 1000]}} :limit {"1 per sec" [1 1000]}}
"This signal will be sampled and rate limited") "This signal will be sampled and rate limited")
@ -368,8 +369,8 @@
;; All offer the same options, but each has an API optimized ;; All offer the same options, but each has an API optimized
;; for a particular use case: ;; for a particular use case:
(t/log! {:level :info, :id ::my-id} "Hi!") ; [msg] or [level-or-opts msg] (tel/log! {:level :info, :id ::my-id} "Hi!") ; [msg] or [level-or-opts msg]
(t/event! ::my-id {:level :info, :msg "Hi!"}) ; [id] or [id level-or-opts] (tel/event! ::my-id {:level :info, :msg "Hi!"}) ; [id] or [id level-or-opts]
(t/signal! {:level :info, :id ::my-id, :msg "Hi!"}) ; [opts] (tel/signal! {:level :info, :id ::my-id, :msg "Hi!"}) ; [opts]
) )

View file

@ -1,14 +1,17 @@
Signals are maps with {:keys [inst id ns level data msg_ ...]}, though they Telemere signals are maps with {:keys [inst id ns level data msg_ ...]},
can be modified by call and/or handler transform (xfns). though they can be modified by call and/or handler transform (xfns).
Default signal keys: Default signal keys:
`:schema` ------ Int version of signal schema (current: 1) `:schema` ------ Int version of signal schema (current: 1)
`:inst` -------- Platform instant [1] when signal was created, monotonicity depends on system clock `:inst` -------- Platform instant [1] when signal was created, monotonicity depends on system clock
`:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...} `:ns` ---------- ?str namespace of signal callsite
`:coords` ------ ?[line column] of signal callsite
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy :slf4j :tools-logging <app-val> ...} `:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy :slf4j :tools-logging <app-val> ...}
`:id` ---------- ?id of signal (common to all signals created at callsite, contrast with `:uid`) `:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
`:uid` --------- ?id of signal instance (unique to each signal created at callsite when tracing, contrast with `:id`) `:id` ---------- Signal callsite ?id (usu. keyword) (common to all signals created at callsite, contrast with `:uid`)
`:uid` --------- Signal instance ?id (usu. string) (unique to each signal created at callsite when tracing, contrast with `:id`)
`:msg_` -------- Arb app-level message ?str given to signal creator - may be a delay, always use `force` to unwrap! `:msg_` -------- Arb app-level message ?str given to signal creator - may be a delay, always use `force` to unwrap!
`:data` -------- Arb app-level data ?val (usu. a map) given to signal creator `:data` -------- Arb app-level data ?val (usu. a map) given to signal creator
@ -23,9 +26,6 @@ Default signal keys:
`: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
`:ctx` --------- ?val of `*ctx*` (arb app-level state) when signal was created `:ctx` --------- ?val of `*ctx*` (arb app-level state) when signal was created
`:ns` ---------- ?str namespace of signal callsite
`:coords` ------ ?[line column] of signal callsite
`: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

@ -24,10 +24,10 @@ All options are available for all signal creator calls:
`:ns` ---------- Custom ?str namespace to override auto signal callsite info `:ns` ---------- Custom ?str namespace to override auto signal callsite info
`:coords` ------ Custom ?[line column] to override auto signal callsite info `:coords` ------ Custom ?[line column] to override auto signal callsite info
`:elidable?` --- Should signal be subject to compile-time elision? (Default: true) `:elidable?` --- Should signal be subject to compile-time elision? (default true)
`:trace?` ------ Should tracing be enabled for `:run` form? `:trace?` ------ Should tracing be enabled for `:run` form?
`:sample` ------ Sample ?rate ∈ℝ[0,1] for signal sampling (0.75 => allow 75% of signals, nil => allow all) `:sample` ------ Sample ?rate ∈ℝ[0,1] for random signal sampling (0.75 => allow 75% of signals, nil => allow all)
`:when` -------- Arb ?form; when present, form must return truthy to allow signal `:when` -------- Arb ?form; when present, form must return truthy to allow signal
`:limit` ------- Rate limit ?spec given to `taoensso.telemere/rate-limiter`, see its docstring for details `:limit` ------- Rate limit ?spec given to `taoensso.telemere/rate-limiter`, see its docstring for details
`:limit-by` ---- When present, rate limits will be enforced independently for each value (any Clojure value!) `:limit-by` ---- When present, rate limits will be enforced independently for each value (any Clojure value!)

View file

@ -37,7 +37,7 @@
(declare ; Needed to avoid `clj-kondo` "Unresolved var" warnings (declare ; Needed to avoid `clj-kondo` "Unresolved var" warnings
level-aliases level-aliases
help:filters help:handler help:handler-dispatch-options help:filters help:handlers help:handler-dispatch-options
get-filters get-min-levels get-handlers get-handlers-stats get-filters get-min-levels get-handlers get-handlers-stats
#?(:clj without-filters) #?(:clj without-filters)
@ -52,15 +52,18 @@
^:dynamic *ctx* set-ctx! #?(:clj with-ctx) #?(:clj with-ctx+) ^:dynamic *ctx* set-ctx! #?(:clj with-ctx) #?(:clj with-ctx+)
^:dynamic *xfn* set-xfn! #?(:clj with-xfn) #?(:clj with-xfn+)) ^:dynamic *xfn* set-xfn! #?(:clj with-xfn) #?(:clj with-xfn+))
(def default-handler-dispatch-opts
"See `help:handler-dispatch-opts` for details."
(dissoc sigs/default-handler-dispatch-opts
:convey-bindings? ; We use `enc/bound-delay`
))
(sigs/def-api (sigs/def-api
{:sf-arity 4 {:sf-arity 4
:ct-call-filter impl/ct-call-filter :ct-call-filter impl/ct-call-filter
:*rt-call-filter* impl/*rt-call-filter* :*rt-call-filter* impl/*rt-call-filter*
:*sig-handlers* impl/*sig-handlers* :*sig-handlers* impl/*sig-handlers*
:lib-dispatch-opts :lib-dispatch-opts default-handler-dispatch-opts})
(assoc sigs/default-handler-dispatch-opts
:convey-bindings? false ; Handled manually
)})
;;;; Aliases ;;;; Aliases
@ -74,7 +77,6 @@
enc/rate-limiter enc/rate-limiter
enc/newline enc/newline
sigs/comp-xfn sigs/comp-xfn
sigs/default-handler-dispatch-opts
#?(:clj truss/keep-callsite) #?(:clj truss/keep-callsite)
;; Impl ;; Impl

View file

@ -14,7 +14,6 @@
#?(:clj #?(:clj
(defn ^:public handler:console (defn ^:public handler:console
"Alpha, subject to change. "Alpha, subject to change.
Returns a signal handler that: Returns a signal handler that:
- Takes a Telemere signal (map). - Takes a Telemere signal (map).
- Writes the signal as a string to specified stream. - Writes the signal as a string to specified stream.
@ -28,7 +27,7 @@
Defaults to `*err*` if `utils/error-signal?` is true, and `*out*` otherwise." Defaults to `*err*` if `utils/error-signal?` is true, and `*out*` otherwise."
([] (handler:console nil)) ([] (handler:console nil))
([{:keys [stream output-fn ] ([{:keys [stream output-fn]
:or :or
{stream :auto {stream :auto
output-fn (utils/format-signal-fn)}}] output-fn (utils/format-signal-fn)}}]
@ -52,7 +51,6 @@
:cljs :cljs
(defn ^:public handler:console (defn ^:public handler:console
"Alpha, subject to change. "Alpha, subject to change.
If `js/console` exists, returns a signal handler that: If `js/console` exists, returns a signal handler that:
- Takes a Telemere signal (map). - Takes a Telemere signal (map).
- Writes the signal as a string to JavaScript console. - Writes the signal as a string to JavaScript console.
@ -89,7 +87,6 @@
#?(:cljs #?(:cljs
(defn ^:public handler:console-raw (defn ^:public handler:console-raw
"Alpha, subject to change. "Alpha, subject to change.
If `js/console` exists, returns a signal handler that: If `js/console` exists, returns a signal handler that:
- Takes a Telemere signal (map). - Takes a Telemere signal (map).
- Writes the raw signal to JavaScript console. - Writes the raw signal to JavaScript console.

View file

@ -564,20 +564,16 @@
(if elide? (if elide?
run-form run-form
(let [coords (let [coords (get opts :coords (when (= ns-form* :auto) (truss/callsite-coords &form)))
(get opts :coords
(when (= ns-form* :auto)
;; Auto coords iff auto ns
(truss/callsite-coords &form)))
{inst-form :inst {inst-form :inst
level-form :level
kind-form :kind kind-form :kind
id-form :id} opts id-form :id
level-form :level} opts
trace? (get opts :trace? (boolean run-form)) trace? (get opts :trace? (boolean run-form))
_ _
(when-not (contains? #{true false nil} trace?) (when-not (contains? #{true false nil} trace?)
(truss/unexpected-arg! trace? (truss/unexpected-arg! trace?
{:param 'trace? {:param 'trace?
:context `signal! :context `signal!
@ -675,7 +671,7 @@
;; Final unwrapped signal value visible to users/handler-fns, allow to throw ;; Final unwrapped signal value visible to users/handler-fns, allow to throw
(if-let [xfn# ~xfn-form] (if-let [xfn# ~xfn-form]
(xfn# signal#) ; Apply call transform, can throw (xfn# signal#)
(do signal#))))) (do signal#)))))
;; Trade-off: avoid double `run-form` expansion ;; Trade-off: avoid double `run-form` expansion
@ -729,39 +725,34 @@
(truss/try* (truss/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#)))
(finally (.close otel-scope#))))))]) (finally (.close otel-scope#))))))])]
final-form `((fn [] ; iife for better IoC compatibility
;; Unless otherwise specified, allow errors to throw on call ;; Unless otherwise specified, allow errors to throw on call
`(let [~'__run-fn-form ~run-fn-form (let [~'__run-fn-form ~run-fn-form
~'__kind ~kind-form ~'__kind ~kind-form
~'__ns ~ns-form ~'__ns ~ns-form
~'__id ~id-form ~'__id ~id-form
~'__level ~level-form] ~'__level ~level-form]
(enc/if-not ~allow? (enc/if-not ~allow?
~run-form* ~run-form*
(let [~'__inst ~inst-form (let [~'__inst ~inst-form
~'__thread ~thread-form ~'__thread ~thread-form
~'__root0 ~root-form0 ; ?{:keys [id uid]} ~'__root0 ~root-form0 ; ?{:keys [id uid]}
~@into-let-form ; Inject conditional bindings ~@into-let-form ; Inject conditional bindings
signal# ~signal-delay-form] signal# ~signal-delay-form]
(dispatch-signal! (dispatch-signal!
;; Unconditionally send same wrapped signal to all handlers. ;; Unconditionally send same wrapped signal to all handlers.
;; Each handler will use wrapper for handler filtering, ;; Each handler will use wrapper for handler filtering,
;; unwrapping (realizing) only allowed signals. ;; unwrapping (realizing) only allowed signals.
(WrappedSignal. ~'__kind ~'__ns ~'__id ~'__level signal#)) (WrappedSignal. ~'__kind ~'__ns ~'__id ~'__level signal#))
(if ~'__run-result (if ~'__run-result
( ~'__run-result signal#) ( ~'__run-result signal#)
true))))] true))))))))))))
(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

@ -382,9 +382,9 @@
(comment (comment
(do (do
(require '[taoensso.telemere :as t]) (require '[taoensso.telemere :as tel])
(def h1 (handler:open-telemetry)) (def h1 (handler:open-telemetry))
(let [{[s1 s2] :signals} (t/with-signals (t/trace! ::id1 (t/trace! ::id2 "form2")))] (let [{[s1 s2] :signals} (tel/with-signals (tel/trace! ::id1 (tel/trace! ::id2 "form2")))]
(def s1 s1) (def s1 s1)
(def s2 s2))) (def s2 s2)))

View file

@ -540,17 +540,10 @@
(when kind (s+spc (sigs/upper-qn kind))) (when kind (s+spc (sigs/upper-qn kind)))
#?(:clj #?(:clj
(when-let [host (get signal :host)] (when-let [hostname (enc/get-in* signal [:host :name])]
(when-let [hostname (get host :name)] (s+spc hostname)))
(s+spc hostname))))
(when ns
(enc/sb-append sb " " ns)
(when-let [[line column] (get signal :coords)]
(if column
(enc/sb-append sb "[" line "," column "]")
(enc/sb-append sb "[" line "]"))))
(when ns (s+spc (sigs/format-callsite ns (get signal :coords))))
(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
msg (force msg_)] msg (force msg_)]

View file

@ -1,13 +1,12 @@
My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, transforms, and utils. My plan for Telemere is to offer a **stable core of limited scope**, then to focus on making it as easy for the **community** to write additional stuff like handlers, transforms, and utils.
**PRs very welcome** to add links to this page! [PRs](../wiki#contributions-welcome) **very welcome** to add links to this page!
If you spot issues with any linked resources, please **contact the relevant authors** to let them know! Thank you! 🙏 - [Peter](https://www.taoensso.com) If you spot issues with any linked resources, please **contact the relevant authors** to let them know! Thank you! 🙏 - [Peter](https://www.taoensso.com)
# Learning # Learning
Includes videos, tutorials, demo projects, etc. Includes videos, tutorials, demo projects, etc.
[PRs](../wiki#contributions-welcome) welcome for additions!
| Type | Description | | Type | Description |
| ------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@ -20,9 +19,8 @@ Includes videos, tutorials, demo projects, etc.
# Handlers and tools # Handlers and tools
Includes libraries or examples for handlers (see [Writing handlers](./4-Handlers#writing-handlers)), transforms, handler utils (e.g. formatters), tools for analyzing signals, etc. [PRs](../wiki#contributions-welcome) welcome for additions! Includes libraries or examples for handlers (see [Writing handlers](./4-Handlers#writing-handlers)), transforms, handler utils (e.g. formatters), tools for analyzing signals, etc.
| Type | Description | | Type | Description |
| ---- | :------------------------------------------------------------ | | ---- | :------------------------------------------------------------ |
| - | Your link here? [PRs](../wiki#contributions-welcome) welcome! | | - | Your link here? [PRs](../wiki#contributions-welcome) welcome! |