[new] Add experimental :thread key to Clj signals

Only downside/hesitation is that this info *must* be collected at the callsite,
which means that it affects the performance of *all* created signals.

Adds ~30-50 nsecs per signal.
This commit is contained in:
Peter Taoussanis 2024-04-29 19:58:28 +02:00
parent 839143167b
commit ebe8a957f5
3 changed files with 39 additions and 20 deletions

View file

@ -26,6 +26,7 @@ Default signal keys:
`:line` -------- ?int line of signal creator callsite, same as (:line location) `:line` -------- ?int line of signal creator callsite, same as (:line location)
`:column` ------ ?int column of signal creator callsite, same as (:column location) `:column` ------ ?int column of signal creator callsite, same as (:column location)
`:file` -------- ?str filename of signal creator callsite, same as (:file location) `:file` -------- ?str filename of signal creator callsite, same as (:file location)
`:thread` ------ (Clj only) {:keys [group name id]} thread info for thread that called signal creator
`:sample-rate` - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all) `:sample-rate` - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all)
<kvs> ---------- Other arb user-level ?kvs given to signal creator. Typically NOT included <kvs> ---------- Other arb user-level ?kvs given to signal creator. Typically NOT included

View file

@ -215,7 +215,7 @@
(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
[^long schema inst uid, [^long schema inst uid,
location ns line column file, location ns line column file #?(:clj thread),
sample-rate, kind id level, ctx parent, sample-rate, kind id level, ctx parent,
data msg_ error run-form run-val, data msg_ error run-form run-val,
end-inst run-nsecs kvs] end-inst run-nsecs kvs]
@ -351,7 +351,7 @@
^Signal ^Signal
;; Note all dynamic vals passed as explicit args for better control ;; Note all dynamic vals passed as explicit args for better control
[inst uid, [inst uid,
location ns line column file, location ns line column file #?(:clj thread :cljs _thread),
sample-rate, kind id level, ctx parent, sample-rate, kind id level, ctx parent,
kvs data msg_, kvs data msg_,
run-form run-result error] run-form run-result error]
@ -371,14 +371,14 @@
msg_)] msg_)]
(Signal. 1 inst uid, (Signal. 1 inst uid,
location ns line column file, location ns line column file #?(:clj thread),
sample-rate, kind id level, ctx parent, sample-rate, kind id level, ctx parent,
data msg_, data msg_,
run-err run-form run-val, run-err run-form run-val,
end-inst run-nsecs kvs)) end-inst run-nsecs kvs))
(Signal. 1 inst uid, (Signal. 1 inst uid,
location ns line column file, location ns line column file #?(:clj thread),
sample-rate, kind id level, ctx parent, sample-rate, kind id level, ctx parent,
data msg_, error nil nil nil nil kvs))] data msg_, error nil nil nil nil kvs))]
@ -387,10 +387,10 @@
(do signal)))) (do signal))))
(comment (comment
(enc/qb 1e6 ; 55.67 (enc/qb 1e6 ; 66.8
(new-signal (new-signal
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil))) nil nil nil nil nil nil nil nil nil nil)))
;;;; Signal API helpers ;;;; Signal API helpers
@ -540,6 +540,17 @@
;;;; Signal macro ;;;; Signal macro
#?(:clj
(defn thread-info
"Returns {:keys [group name id]} for current thread."
[]
(when-let [t (Thread/currentThread)]
{:group (when-let [g (.getThreadGroup t)] (.getName g))
:name (.getName t)
:id (.getId t)})))
(comment (enc/qb 1e6 (thread-info))) ; 44.49
#?(:clj #?(:clj
(defmacro ^:public signal! (defmacro ^:public signal!
"Generic low-level signal call, also aliased in Encore." "Generic low-level signal call, also aliased in Encore."
@ -549,6 +560,7 @@
(have? map? opts) ; We require const map keys, but vals may require eval (have? map? opts) ; We require const map keys, but vals may require eval
(let [defaults (get opts :defaults) (let [defaults (get opts :defaults)
opts (merge defaults (dissoc opts :defaults)) opts (merge defaults (dissoc opts :defaults))
clj? (not (:ns &env))
{run-form :run} opts {run-form :run} opts
{:keys [#_expansion-id location elide? allow?]} {:keys [#_expansion-id location elide? allow?]}
@ -587,6 +599,8 @@
uid-form (get opts :uid (when trace? :auto/uuid)) uid-form (get opts :uid (when trace? :auto/uuid))
uid-form (parse-uid-form uid-form) uid-form (parse-uid-form uid-form)
thread-form (if clj? `(thread-info) nil)
signal-delay-form signal-delay-form
(let [{do-form :do (let [{do-form :do
let-form :let let-form :let
@ -626,7 +640,7 @@
(let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc. (let [~@let-form ; Allow to throw, eval BEFORE data, msg, etc.
~'__signal ~'__signal
(new-signal ~'__inst ~'__uid (new-signal ~'__inst ~'__uid
~location ~'__ns ~line-form ~column-form ~file-form, ~location ~'__ns ~line-form ~column-form ~file-form ~'__thread,
~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form, ~sample-rate-form, ~'__kind ~'__id ~'__level, ~ctx-form ~parent-form,
~kvs-form ~data-form ~msg-form, ~kvs-form ~data-form ~msg-form,
'~run-form ~'__run-result ~error-form)] '~run-form ~'__run-result ~error-form)]
@ -651,6 +665,7 @@
~'__id ~id-form ; '' ~'__id ~id-form ; ''
~'__uid ~uid-form ; '' ~'__uid ~uid-form ; ''
~'__ns ~ns-form ; '' ~'__ns ~ns-form ; ''
~'__thread ~thread-form ; ''
~'__run-result ; Non-throwing (traps) ~'__run-result ; Non-throwing (traps)
~(when run-form ~(when run-form

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 :refer [have have?]]
[taoensso.telemere.impl :as impl]))
(comment (comment
(require '[taoensso.telemere :as tel]) (require '[taoensso.telemere :as tel])
@ -52,7 +53,7 @@
;;;; Public misc ;;;; Public misc
(enc/defaliases enc/newline enc/pr-edn #?(:cljs enc/pr-json)) (enc/defaliases enc/newline enc/pr-edn #?(:cljs enc/pr-json) #?(:clj impl/thread-info))
#?(:clj (defn thread-name "Returns string name of current thread." ^String [] (.getName (Thread/currentThread)))) #?(:clj (defn thread-name "Returns string name of current thread." ^String [] (.getName (Thread/currentThread))))
#?(:clj (defn thread-id "Returns long id of current thread." ^long [] (.getId (Thread/currentThread)))) #?(:clj (defn thread-id "Returns long id of current thread." ^long [] (.getId (Thread/currentThread))))
@ -375,10 +376,12 @@
err-stop (str newline ">>> error >>>")] err-stop (str newline ">>> error >>>")]
(fn a-signal-content-handler [signal hf vf] (fn a-signal-content-handler [signal hf vf]
(let [{:keys [uid parent data #_kvs ctx sample-rate]} signal] (let [{:keys [uid parent data #_kvs ctx #?(:clj thread) sample-rate]} signal]
(when sample-rate (hf "sample: " (vf sample-rate))) (when sample-rate (hf "sample: " (vf sample-rate)))
(when uid (hf " uid: " (vf uid))) (when uid (hf " uid: " (vf uid)))
(when parent (hf "parent: " (vf parent))) (when parent (hf "parent: " (vf parent)))
#?(:clj
(when thread (hf "thread: " (vf thread))))
(when data (hf " data: " (vf data))) (when data (hf " data: " (vf data)))
#_(when kvs (hf " kvs: " (vf kvs))) ; Don't auto include in output #_(when kvs (hf " kvs: " (vf kvs))) ; Don't auto include in output
(when ctx (hf " ctx: " (vf ctx)))) (when ctx (hf " ctx: " (vf ctx))))