diff --git a/resources/signal-docstrings/signal-content.txt b/resources/signal-docstrings/signal-content.txt index 639f7f5..3237085 100644 --- a/resources/signal-docstrings/signal-content.txt +++ b/resources/signal-docstrings/signal-content.txt @@ -7,8 +7,8 @@ Default signal keys: `:inst` -------- Platform instant [1] when signal was created `:level` ------- Signal level ∈ #{ :trace :debug :info :warn :error :fatal :report ...} `:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy :slf4j :tools-logging ...} -`:id` ---------- ?id of signal (common to all signals created at callsite, contrast with `:uid`) -`:uid` --------- ?id of signal instance (unique to each signal created at callsite, contrast with `:id`) +`:id` ---------- ?id of signal (common to all signals created at callsite, contrast with `:uid`) +`:uid` --------- ?id of signal instance (unique to each signal created at callsite when tracing, contrast with `:id`) `:msg` --------- Arb app-level message ?str given to signal creator `:data` -------- Arb app-level data ?val (usu. a map) given to signal creator diff --git a/src/taoensso/telemere.cljc b/src/taoensso/telemere.cljc index 4553d05..c49351b 100644 --- a/src/taoensso/telemere.cljc +++ b/src/taoensso/telemere.cljc @@ -81,6 +81,35 @@ (impl/defhelp help:signal-content :signal-content) (impl/defhelp help:environmental-config :environmental-config)) +;;;; + +(def ^:dynamic *uid-fn* + "Experimental, subject to change. + (fn [root?]) used to generate signal `:uid` values when tracing. + These are basically unique signal instance identifiers. + + `root?` argument is true iff signal is a top-level trace (i.e. form + being traced is unnested = has no parent form). + + Root uids typically have ~128 bits of entropy to ensure uniqueness. + Child uids are typically used only with respect to a parent/root, + and so can often make do with ~64 bits of entropy or less. + + Smaller uids are generally cheaper to generate, and use less space + when serializing/transmitting/storing/etc. + + By default generates nano-style uids like + \"r76-B8LoIPs5lBG1_Uhdy\" (root) and \"tMEYoZH0K-\" (non-root). + + For plain fixed-length UUIDs use: (fn [_root?] (utils/uuid)) + For plain fixed-length UUID strings use: (fn [_root?] (utils/uuid-str)) + + See also `utils/nano-uid-fn`, `utils/hex-id-fn`, etc." + + (utils/nano-uid-fn {:secure? false})) + +(comment (enc/qb 1e6 (enc/uuid) (*uid-fn* true) (*uid-fn* false))) ; [168.83 79.02 62.95] + ;;;; Signal creators ;; - event! [id ] [id opts/level] ; id + ?level => allowed? ; Sole signal with descending main arg! ;; - log! [msg ] [opts/level msg] ; msg + ?level => allowed? diff --git a/src/taoensso/telemere/impl.cljc b/src/taoensso/telemere/impl.cljc index ced745d..892232a 100644 --- a/src/taoensso/telemere/impl.cljc +++ b/src/taoensso/telemere/impl.cljc @@ -17,7 +17,8 @@ #?(:clj (enc/declare-remote ; For macro expansions ^:dynamic taoensso.telemere/*ctx* - ^:dynamic taoensso.telemere/*middleware*)) + ^:dynamic taoensso.telemere/*middleware* + ^:dynamic taoensso.telemere/*uid-fn*)) ;;;; Utils @@ -62,27 +63,6 @@ (comment (enc/get-env {:as :edn, :return :explain} :taoensso.telemere/rt-filters<.platform><.edn>)) -;;;; Unique IDs (UIDs) - -(enc/def* nanoid-readable (enc/rand-id-fn {:chars :nanoid-readable, :len 23})) - -#?(:clj - (defn- parse-uid-form [uid-form] - (when uid-form - (case uid-form - :auto/uuid `(enc/uuid) - :auto/uuid-str `(enc/uuid-str) - :auto/nanoid `(enc/nanoid) - :auto/nanoid-readable `(nanoid-readable) - uid-form)))) - -(comment - (enc/qb 1e6 ; [161.36 184.69 274.53 468.67] - (enc/uuid) - (enc/uuid-str) - (enc/nanoid) - (nanoid-readable))) - ;;;; Messages (deftype MsgSkip []) @@ -519,15 +499,14 @@ {:msg "Expected constant (compile-time) `:trace?` boolean" :context `signal!})) - parent-form (get opts :parent (when trace? `taoensso.telemere.impl/*trace-parent*)) - root-form (get opts :root (when trace? `(or taoensso.telemere.impl/*trace-root* - {:id ~'__id, :uid ~'__uid, :inst ~'__inst}))) + parent-form (get opts :parent (when trace? `taoensso.telemere.impl/*trace-parent*)) + root-form (get opts :root (when trace? `taoensso.telemere.impl/*trace-root*)) - inst-form (get opts :inst :auto) - inst-form (if (= inst-form :auto) `(enc/now-inst*) inst-form) + inst-form (get opts :inst :auto) + uid-form (get opts :uid (when trace? :auto)) - uid-form (get opts :uid (when trace? :auto/uuid)) - uid-form (parse-uid-form uid-form) + inst-form (if (not= inst-form :auto) inst-form `(enc/now-inst*)) + uid-form (if (not= uid-form :auto) uid-form `(taoensso.telemere/*uid-fn* (if ~'__root0 false true))) thread-form (if clj? `(enc/thread-info) nil) @@ -621,13 +600,14 @@ ~run-form (let [;;; Allow to throw at call ~'__inst ~inst-form + ~'__root0 ~root-form ~'__level ~level-form ~'__kind ~kind-form ~'__id ~id-form ~'__uid ~uid-form ~'__ns ~ns-form ~'__thread ~thread-form - ~'__root ~root-form + ~'__root (or ~'__root0 (when ~trace? {:id ~'__id, :uid ~'__uid, :inst ~'__inst})) ~'__run-result ; Non-throwing (traps) ~(when run-form diff --git a/src/taoensso/telemere/utils.cljc b/src/taoensso/telemere/utils.cljc index eb2eca8..72b5dd6 100644 --- a/src/taoensso/telemere/utils.cljc +++ b/src/taoensso/telemere/utils.cljc @@ -51,12 +51,91 @@ (format-id (str *ns*) ::id1) (format-id nil ::id1)) -;;;; Public misc +;;;; Unique IDs (UIDs) + +(defn nano-uid-fn + "Experimental, subject to change. + Returns a (fn nano-uid [root?]) that returns a random nano-style uid string like: + \"r76-B8LoIPs5lBG1_Uhdy\" - 126 bit (21 char) root uid + \"tMEYoZH0K-\" - 60 bit (10 char) non-root (child) uid" + {:tag #?(:clj 'String :cljs 'string)} + ([] (nano-uid-fn nil)) + ([{:keys [secure? root-len child-len] + :or + {root-len 21 + child-len 10}}] + + (let [root-len (long root-len) + child-len (long child-len)] + + #?(:cljs (fn nano-uid [root?] (if root? (enc/nanoid secure? root-len) (enc/nanoid secure? child-len))) + :clj + (if secure? + (fn nano-uid-secure [root?] + (let [srng (.get com.taoensso.encore.Ids/SRNG_STRONG)] + (if root? + (com.taoensso.encore.Ids/genNanoId srng root-len) + (com.taoensso.encore.Ids/genNanoId srng child-len)))) + + (fn nano-uid-insecure [root?] + (if root? + (com.taoensso.encore.Ids/genNanoId root-len) + (com.taoensso.encore.Ids/genNanoId child-len)))))))) + +(comment ((nano-uid-fn) true)) + +(defn hex-uid-fn + "Experimental, subject to change. + Returns a (fn hex-uid [root?]) that returns a random hex-style uid string like: + \"05039666eb9dc3206475f44ab9f3d843\" - 128 bit (32 char) root uid + \"721fcef639a51513\" - 64 bit (16 char) non-root (child) uid" + {:tag #?(:clj 'String :cljs 'string)} + ([] (hex-uid-fn nil)) + ([{:keys [secure? root-len child-len] + :or + {root-len 32 + child-len 16}}] + + (let [root-len (long root-len) + child-len (long child-len)] + + #?(:cljs + (let [rand-bytes-fn + (if secure? + (partial enc/rand-bytes true) + (partial enc/rand-bytes false)) + + hex-uid-root (enc/rand-id-fn {:chars :hex-lowercase, :len root-len, :rand-bytes-fn rand-bytes-fn}) + hex-uid-child (enc/rand-id-fn {:chars :hex-lowercase, :len child-len, :rand-bytes-fn rand-bytes-fn})] + + (fn hex-uid [root?] (if root? (hex-uid-root) (hex-uid-child)))) + + :clj + (if secure? + (fn hex-uid-secure [root?] + (let [srng (.get com.taoensso.encore.Ids/SRNG_STRONG)] + (if root? + (com.taoensso.encore.Ids/genHexId srng root-len) + (com.taoensso.encore.Ids/genHexId srng child-len)))) + + (fn hex-uid-insecure [root?] + (if root? + (com.taoensso.encore.Ids/genHexId root-len) + (com.taoensso.encore.Ids/genHexId child-len)))))))) + +(comment ((hex-uid-fn) true)) +(comment + ;; [170.47 180.18 53.87 60.68] + (let [nano-uid-fn (nano-uid-fn), hex-uid-fn (hex-uid-fn)] + (enc/qb 1e6 (enc/uuid) (enc/uuid-str) (nano-uid true) (hex-uid true)))) + +;;;; Misc (enc/defaliases - enc/newline enc/pr-edn #?(:cljs enc/pr-json) - #?@(:clj [enc/thread-info enc/thread-id enc/thread-name - enc/host-info enc/host-ip enc/hostname])) + enc/newline enc/pr-edn #?(:clj enc/uuid) enc/uuid-str + #?@(:cljs [enc/pr-json]) + #?@(:clj [enc/thread-info enc/thread-id enc/thread-name + enc/host-info enc/host-ip enc/hostname])) #?(:cljs (defn js-console-logger