taoensso.telemere
*ctx*
dynamic
cljs
Dynamic context: arbitrary user-level state attached as `:ctx` to all signals.
Value may be any type, but is usually nil or a map.
Re/bind dynamic value using `with-ctx`, `with-ctx+`, or `binding`.
Modify root (base) value using `set-ctx!`.
Default root (base) value is `default-ctx`.
Note that as with all dynamic Clojure vars, "binding conveyance" applies
when using futures, agents, etc.
Tips:
- Value may be (or may contain) an atom if you want mutable semantics
- Value may be of form {<scope-id> <data>} for custom scoping, etc.*middleware*
dynamic
cljs
Optional vector of unary middleware fns to apply (sequentially/left-to-right)
to each signal before passing it to handlers. If any middleware fn returns nil,
aborts immediately without calling handlers.
Useful for transforming each signal before handling.
Re/bind dynamic value using `with-middleware`, `binding`.
Modify root (base) value using `set-middleware!`.
add-handler!
cljs
(add-handler! handler-id handler-fn)(add-handler! handler-id handler-fn dispatch-opts)
Registers given signal handler and returns
{<handler-id> {:keys [dispatch-opts handler-fn]}} for all signal handlers
now registered.
`handler-fn` should be a fn of 1-2 arities:
([handler-arg]) => Handle the given argument (e.g. write to disk/db, etc.)
([]) => Optional arity, called exactly once on system shutdown.
Provides an opportunity for handler to close/release
any resources that it may have opened/acquired.
See the relevant docstring/s for `handler-arg` details.
Handler ideas:
Save to a db, `tap>`, log, `put!` to an appropriate `core.async`
channel, filter, aggregate, use for a realtime analytics dashboard,
examine for outliers or unexpected data, etc.
Dispatch options include:
`async` (Clj only)
Options for running handler asynchronously via `taoensso.encore/runner`,
{:keys [mode buffer-size n-threads daemon-threads? ...]}
Supports `:blocking`, `:dropping`, and `:sliding` back-pressure modes.
NB handling order may be non-sequential when `n-threads` > 1.
Default:
{:mode :dropping, :buffer-size 1024, :n-threads 1, :daemon-threads? true}
I.e. async by default, with a buffer of size 1024 that drops new entries
when full.
Options:
`mode` - Mode of operation, ∈ #{:sync :blocking :dropping :sliding}.
`buffer-size` - Size of buffer before back-pressure mechanism is engaged.
`n-threads` - Number of threads for asynchronously executing fns.
NB execution order may be non-sequential when n > 1.
`priority`
Optional handler priority ∈ℤ (default 100). Handlers will be called in
descending priority order.
`sample-rate`
Optional sample rate ∈ℝ[0,1], or (fn dyamic-sample-rate []) => ℝ[0,1].
When present, handle only this (random) proportion of args:
1.0 => handle every arg (same as `nil` rate, default)
0.0 => noop every arg
0.5 => handle random 50% of args
`kind-filter` - Kind filter as in `set-kind-filter!` (when relevant)
`ns-filter` - Namespace filter as in `set-ns-filter!`
`id-filter` - Id filter as in `set-id-filter!` (when relevant)
`min-level` - Minimum level as in `set-min-level!`
`when-fn`
Optional nullary (fn allow? []) that must return truthy for handler to be
called. When present, called *after* sampling and other filters, but before
rate limiting.
`rate-limit`
Optional rate limit spec as provided to `taoensso.encore/rate-limiter`,
{<limit-id> [<n-max-calls> <msecs-window>]}.
Examples:
{"1/sec" [1 1000]} => Max 1 call per 1000 msecs
{"1/sec" [1 1000]
"10/min" [10 60000]} => Max 1 call per 1000 msecs,
and 10 calls per 60 secs
`middleware`
Optional vector of unary middleware fns to apply (left-to-right/sequentially)
to `handler-arg` before passing to `handler-fn`. If any middleware fn returns
nil, aborts immediately without calling `handler-fn`.
Useful for transforming `handler-arg` before handling.
`error-fn` - (fn [{:keys [handler-id handler-arg error]}]) to call on handler error.
`backp-fn` - (fn [{:keys [handler-id ]}]) to call on handler back-pressure.
Flow sequence:
1. Per call (n=1)
a. Sampling
b. Filtering (kind, namespace, id, level, when-form)
c. Rate limiting
d. Middleware
2. Per handler (n>=0)
a. Sampling
b. Filtering (kind, namespace, id, level, when-fn)
c. Rate limiting
d. Middleware
e. Hander fn
Note: call filters should generally be at least as permissive as handler filters,
otherwise calls will be suppressed before reaching handlers.catch->error!
macro
cljs
(catch->error! form)(catch->error! id form)(catch->error! {:as opts, :keys [rethrow? catch-val elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error & kvs]} form)
Unconditionally executes given form and-
If form succeeds: return the form's result.
If form throws:
Call `error!` with the thrown error and the given signal options [2],
then return (:catch-val opts) if it exists, or rethrow the error.
API: [form] [id-or-opts form] => form's result (value/throw) (unconditional), or (:catch-val opts)
Default kind: `:error`
Default level: `:error`
Examples:
(catch->error! (/ 1 0)) ; %> {:kind :error, :level :error, :error <caught> ...}
(catch->error! ::my-id (/ 1 0)) ; %> {... :id ::my-id ...}
(catch->error!
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}
:msg ["My msg:" x my-error]
:catch-val "Return value when form throws"
:catch-sym my-error ; Sym of caught error, available to `:data` and `:msg`
}
(/ 1 0)) ; %> {... :data {x "x"}, :msg_ "My msg: x <caught>" ...}
Tips:
- Test using `with-signal`: (with-signal (catch->error! ...)).
- Supports the same options [2] as other signals [1].
- Useful for recording errors in forms, futures, callbacks, etc.
See also `error!`.
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)chance
cljs
(chance prob)
Returns true with given probability ∈ ℝ[0,1].
default-ctx
cljs
Default root (base) value of `*ctx*` var.
Defaults to `nil`, controlled by:
(get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>)
See `get-env` for details.error!
macro
cljs
(error! error)(error! id error)(error! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error & kvs]} error)
"Error" signal creator, emphasizing error + id.
API: [error] [id-or-opts error] => given error (unconditional)
Default kind: `:error`
Default level: `:error`
Examples:
(throw (error! (ex-info "MyEx" {}))) ; %> {:kind :error, :level :error, :error <MyEx> ...}
(throw (error! ::my-id (ex-info "MyEx" {}))) ; %> {... :id ::my-id ...}
(throw
(error!
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}
:msg ["My message:" x]}
(ex-info "MyEx" {}))) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}
Tips:
- Test using `with-signal`: (with-signal (error! ...)).
- Supports the same options [2] as other signals [1].
- `error` arg is a platform error (`java.lang.Throwable` or `js/Error`).
- Can conveniently be wrapped by `throw`: (throw (error! ...)).
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)error-signal?
cljs
(error-signal? signal)
Experimental, subject to change.
Returns true iff given signal has an `:error` value, or a `:kind` or `:level`
that indicates that it's an error.
event!
macro
cljs
(event! id)(event! id level)(event! id {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error & kvs]})
"Event" signal creator, emphasizing id + level.
API: [id] [id level-or-opts] => true iff signal was allowed
Default kind: `:event`
Default level: `:info`
When filtering conditions are met [4], creates a Telemere signal [3] and
dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
Examples:
(event! ::my-id) ; %> {:kind :event, :level :info, :id ::my-id ...}
(event! ::my-id :warn) ; %> {... :level :warn ...}
(event! ::my-id
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}
:msg ["My msg:" x]}) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}
Tips:
- Test using `with-signal`: (with-signal (event! ...)).
- Supports the same options [2] as other signals [1].
- `log!` and `event!` are both good default/general-purpose signal creators.
- `log!` emphasizes messages, while `event!` emphasizes ids.
- Has a different 2-arity arg order to all other signals!
Mnemonic: the arg that's typically larger is *always* in the rightmost
position, and for `event!` that's the `level-or-opts` arg.
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)get-env
macro
cljs
added in Encore v3.75.0 (2024-01-29)
(get-env {:keys [as default return], :or {as :str, return :value}} spec)
Flexible cross-platform util for embedding a config value during
macro expansion. Used by other Taoensso libraries.
Given a const kw/string id or vector of desc-priority alternative ids,
parse and return the first of the following that exists:
- JVM property value for id
- Environment variable value for id
- Classpath resource content for id
Ids may include optional segment in `<>` tag (e.g. `<.edn>`).
Ids may include `<.?platform.?>` tag for auto replacement, useful
for supporting platform-specific config.
Search order: desc by combined [alt-index platform(y/n) optional(y/n)].
So (get-env {:as :edn} [:my-app/alt1<.platform><.edn> :my-app/alt2])
will parse and return the first of the following that exists:
1. Alt1 +platform +optional (.edn suffix)
1a. `my-app.alt1.clj.edn` JVM property value
1b. `MY_APP_ALT1_CLJ_EDN` environment variable value
1c. `my-app.alt1.clj.edn` classpath resource content
2. Alt1 +platform -optional (.edn suffix)
2a. `my-app.alt1.clj` JVM property value
2b. `MY_APP_ALT1_CLJ` environment variable value
2c. `my-app.alt1.clj` classpath resource content
3. Alt1 -platform +optional (.edn suffix)
3a. `my-app.alt1.edn` JVM property value
3b. `MY_APP_ALT1_EDN` environment variable value
3c. `my-app.alt1.edn` classpath resource content
4. Alt1 -platform -optional (.edn suffix)
4a. `my-app.alt1` JVM property value
4b. `MY_APP_ALT1` environment variable value
4c. `my-app.alt1` classpath resource content
5. Alt2
5a. `my-app.alt2` JVM property value
5b. `MY_APP_ALT2` environment variable value
5c. `my-app.alt2` classpath resource content
Options:
`:as` - Parse found value as given type ∈ #{:str :bool :edn} (default `:str`).
`:default` - Fallback to return unparsed if no value found during search (default `nil`).
`:return` - Return type ∈ #{:value :map :explain} (default `:value`).
Resulting config value must be something that can be safely embedded in code during
macro-expansion. Symbols in edn will be evaluated during expansion.
TIP!: Use the {:return :explain} option in tests or at the REPL to verify/inspect
resulting config value, config source, and specific search order of prop/env/res ids.get-filters
cljs
(get-filters)
Returns current ?{:keys [compile-time runtime]} filter config.
get-handlers
cljs
(get-handlers)
Returns ?{<handler-id> {:keys [dispatch-opts handler-fn]}} for all
registered signal handlers.get-min-level
cljs
(get-min-level)(get-min-level kind)(get-min-level kind ns)
Returns current ?{:keys [compile-time runtime]} minimum levels.
handler:console
cljs
(handler:console)(handler:console {:keys [format-signal-fn], :or {format-signal-fn (utils/format-signal->str-fn)}})
Experimental, subject to change. Feedback welcome!
If `js/console` exists, returns a (fn handler [signal]) that:
- Takes a Telemere signal.
- Writes a formatted signal string to JavaScript console.
A general-purpose `println`-style handler that's well suited for outputting
signals formatted as edn, JSON, or human-readable strings.
Options:
`:format-signal-fn` - (fn [signal]) => output, see `help:signal-formatters`
handler:console-raw
cljs
(handler:console-raw)(handler:console-raw {:keys [format-signal->prelude-fn format-nsecs-fn], :as opts, :or {format-signal->prelude-fn (utils/format-signal->prelude-fn), format-nsecs-fn (utils/format-nsecs-fn)}})
Experimental, subject to change. Feedback welcome!
If `js/console` exists, returns a (fn handler [signal]) that:
- Takes a Telemere signal.
- Writes raw signal data to JavaScript console.
Intended for use with browser formatting tools like `binaryage/devtools`,
Ref. <https://github.com/binaryage/cljs-devtools>.
help:filters
cljs
Your filter config determines which signal calls will be allowed.
Filtering can occur at compile-time, runtime, or both.
Compile-time filtering elides (permanently removes!) code for
disallowed signals. Most users will want only runtime filtering.
Both compile-time and runtime config can be specified via
environmental config (JVM properties, environment variables, or
classpath resources) [1].
Runtime config can also be specified with:
`set-kind-filter!`, `with-kind-filter` - for filtering calls by signal kind (when relevant)
`set-ns-filter!`, `with-ns-filter` - for filtering calls by namespace
`set-id-filter!`, `with-id-filter` - for filtering calls by signal id (when relevant)
`set-min-level!`, `with-min-level!` - for filtering calls by signal level
See the relevant docstrings for details.
Filtering can also be applied per handler, see `add-handler!` for details.
See also:
`get-filters` - to see current filter config
`get-min-level` - to see current minimum level
`without-filters` - to disable all runtime filtering
If anything is unclear, please ping me (@ptaoussanis) so that I can
improve these docs!
[1] Environmental filter config includes:
Kind filter:
JVM property: `taoensso.telemere.rt-kind-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_KIND_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-kind-filter.edn`
Namespace filter:
JVM property: `taoensso.telemere.rt-ns-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_NS_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-ns-filter.edn`
Id filter:
JVM property: `taoensso.telemere.rt-id-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_ID_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-id-filter.edn`
Minimum level:
JVM property: `taoensso.telemere.rt-min-level.edn`
Env variable: `TAOENSSO_TELEMERE_RT_MIN_LEVEL_EDN`
Classpath resource: `taoensso.telemere.rt-min-level.edn`
Examples:
`taoensso.telemere.rt-min-level.edn` -> ":info"
`TAOENSSO_TELEMERE_RT_NS_FILTER_EDN` -> "{:deny \"taoensso.*\"}"
`taoensso.telemere.rt-id-filter.cljs.edn` -> "#{:my-id1 :my-id2}"
`TAOENSSO_TELEMERE_RT_KIND_FILTER_CLJ_EDN` -> "nil"
Tips:
- The above ids are for runtime filters (the most common).
For compile-time filters, change `rt`->`ct` / `RT`->`CT`.
- The above ids will affect both Clj AND Cljs.
For platform-specific filters, use
".clj.edn" / "_CLJ_EDN" or
".cljs.edn" / "_CLJS_EDN" suffixes instead.
- ".edn" / "_EDN" suffixes are optional.
- Config values should be edn. To get the right syntax, first set
your runtime filters using the standard utils (`set-min-level!`,
etc.). Then call `get-filters` and serialize the relevant parts
to edn with `pr-str`.
- All environmental config uses `get-env` underneath.
See the `get-env` docstring for more/advanced details.
- Classpath resources are files accessible on your project's
classpath. This usually includes files in your project's
`resources/` dir.help:handlers
cljs
Manage handlers with:
`get-handlers` - Returns info on registered handlers
`shut-down-handlers!` - Shuts down registered handlers
`add-handler!` - Registers given handler
`remove-handler!` - Unregisters given handler
See the relevant docstrings for details.
Clj only: `shut-down-handlers!` is called automatically on JVM shutdown.
If anything is unclear, please ping me (@ptaoussanis) so that I can
improve these docs!
help:signal-content
cljs
Signals are maps with {:keys [inst id ns level data msg_ ...]},
though they can be modified by signal and/or handler middleware.
Default signal keys:
`:schema` ------ Int version of signal schema (current: 1)
`:inst` -------- Platform instant [1] when signal was created
`:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy <user-val> ...}
`: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`)
`:msg` --------- Arb user-level message ?str given to signal creator
`:data` -------- Arb user-level data ?val (usu. a map) given to signal creator
`:error` ------- Arb user-level platform ?error [2] given to signal creator
`:run-form` ---- Unevaluated ?form given to signal creator as `:run`
`:run-val` ----- Successful return ?val of `:run` ?form
`:run-nsecs` --- ?int nanosecs runtime of `:run` ?form
`:end-inst` ---- Platform ?instant [1] when `:run` ?form completed
`:ctx` --------- ?val of `*ctx*` (arb user-level state) when signal was created
`:parent` ------ ?{:keys [id uid]} of parent signal, present in nested signals when tracing
`: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)
`: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
in handler output, so a great way to provide custom data/opts for use
(only) by custom middleware/handlers.
If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs!
[1] `java.time.Instant` or `js/Date`
[2] `java.lang.Throwable` or `js/Error`help:signal-creators
cljs
Call a Telemere signal creator to conditionally create a signal at that callsite.
When filtering conditions are met [4], the call creates a Telemere signal [3]
and dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
Telemere doesn't make a hard distinction between different kinds of signals
(log, event, error, etc.) - they're all just plain Clojure/Script maps with
various keys:
- All signal creators offer the same options [2], and
- All signal kinds can contain the same content [3]
Creators vary only in in their default options and call APIs (expected args
and return values), making them more/less convenient for certain use cases:
`log!` ---------- [message + opts/level] => true iff signal was created (allowed)
`event!` -------- [id + opts/level] => true iff signal was created (allowed)
`error!` -------- [error + opts/id ] => given error (unconditional)
`trace!` -------- [form + opts/id ] => form result (value/throw) (unconditional)
`spy!` ---------- [form + opts/level] => form result (value/throw) (unconditional)
`catch->error!` - [error + opts/id ] => form value, or given fallback
`signal!` ------- [ opts ] => depends on options
- `log!` and `event!` are both good default/general-purpose signal creators.
- `log!` emphasizes messages, while `event!` emphasizes ids.
- `signal!` is the generic creator, and is used by all the others.
-------------------------------------------------------------------
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)help:signal-flow
cljs
A signal will be provided to a handler iff ALL of the following are true:
1. Signal (creation) is allowed by compile-time filters
2. Signal (creation) is allowed by runtime filters
3. Signal (handling) is allowed by handler filters
4. Signal middleware does not suppress the signal (return nil)
5. Handler middleware does not suppress the signal (return nil)
For 1-3, filtering may depend on (in order):
Sample rate → namespace → kind → id → level → when form/fn → rate limit
Compile-time vs runtime filtering:
Compile-time filtering is an advanced feature that can be tricky to set
and use correctly. Most folks will want ONLY runtime filtering.
Compile-time filtering works by eliding (completely removing the code for)
disallowed signals. This means zero performance cost for these signals,
but also means that compile-time filtering is PERMANENT once applied.
So if you set `:info` as the compile-time minimum level, that'll REMOVE
CODE for every signal call below `:info` level. To decrease that minimum
level, you'll need to rebuild.
Compile-time filtering can be set ONLY with environmental config
(JVM properties, environment variables, or classpath resources).
Signal and handler sampling is multiplicative:
Both signals and handlers can have independent sample rates, and these
MULTIPLY!
If a signal is created with 20% sampling and a handler handles 50%
of received signals, then 10% of possible signals will be handled
(50% of 20%).
The multiplicative rate is helpfully reflected in each signal's final
`:sample-rate` value.
For more info:
- Signal visual flowchart, Ref. <https://www.taoensso.com/telemere/flow>
- On signal filters, see: `help:signal-filters` docstring
- On handler filters, see: `help:signal-handlers` docstring
If anything is unclear, please ping me (@ptaoussanis) so that I can
improve these docs!
help:signal-options
cljs
Signal options (shared by all signal creators):
`:inst` -------- Platform instant [1] when signal was created, ∈ #{nil :auto <user-val>}
`:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy <user-val> ...}
`: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`)
`:msg` --------- Arb user-level ?message to incl. in signal: str or vec of strs to join (with `\space`)
`:data` -------- Arb user-level ?data to incl. in signal: usu. a map
`:error` ------- Arb user-level ?error to incl. in signal: platform error [2]
`:run` --------- ?form to execute UNCONDITIONALLY; will incl. `:run-value` in signal
`:do` ---------- ?form to execute conditionally (iff signal allowed), before establishing `:let` ?binding
`:let` --------- ?bindings to establish conditionally (iff signal allowed), BEFORE evaluating `:data` and `:msg` (useful!)
`:ctx` --------- Custom ?val to override auto (dynamic `*ctx*`) in signal
`:parent` ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal info in signal
`:location` ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location
`:elidable?` --- Should signal be subject to compile-time elision? (Default: true)
`:sample-rate` - ?rate ∈ℝ[0,1] for signal sampling (0.75 => allow 75% of signals, nil => allow all)
`:when` -------- Arb ?form; when present, form must return truthy to allow signal
`:rate-limit` -- ?spec as given to `taoensso.telemere/rate-limiter`, see its docstring for details
`:middleware` -- ?[(fn [signal])=>modified-signal ...] signal middleware
`:trace?` ------ Should tracing be enabled for `:run` form?
<kvs> ---------- Other arb user-level ?kvs to incl. in signal. Typically NOT included in
handler output, so a great way to provide custom data/opts for use
(only) by custom middleware/handlers.
handler-specific data that can just be ignored by other handlers
If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs!
[1] `java.time.Instant` or `js/Date`
[2] `java.lang.Throwable` or `js/Error`log!
macro
cljs
(log! msg)(log! level msg)(log! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error & kvs]} msg)
"Log" signal creator, emphasizing message + level.
API: [msg] [level-or-opts msg] => true iff signal was allowed.
Default kind: `:log`
Default level: `:info`
When filtering conditions are met [4], creates a Telemere signal [3] and
dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
Examples:
(log! "My msg") ; %> {:kind :log, :level :info, :id ::my-id ...}
(log! :warn "My msg") ; %> {... :level :warn ...}
(log!
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}}
["My msg:" x]) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}
Tips:
- Test using `with-signal`: (with-signal (log! ...)).
- Supports the same options [2] as other signals [1].
- `log!` and `event!` are both good default/general-purpose signal creators.
- `log!` emphasizes messages, while `event!` emphasizes ids.
- `msg` arg may be a string, or vector of strings to join with `\space`.
- See also `msg-splice`, `msg-skip` utils.
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)msg-splice
cljs
(msg-splice args)
For use within signal message vectors.
Wraps given arguments so that they're spliced when creating message.
Useful for conditionally splicing in extra message content, etc.:
(signal! {:msg [(when <cond> (msg-splice ["Username:" "Steve"])) <...>]}) or
(log! [(when <cond> (msg-splice ["Username:" "Steve"]))])
%> {:msg_ "Username: Steve"}newline
cljs
added in Encore v3.68.0 (2023-09-25)
rate-limiter
cljs
(rate-limiter spec)(rate-limiter opts spec)
Takes a spec of form
[ [<n-max-reqs> <msecs-window>] ...] or
{<limit-id> [<n-max-reqs> <msecs-window>]},
and returns a basic stateful (fn a-rate-limiter [req-id] [command req-id]).
Call the limiter fn with a request id (e.g. username) by which to count/limit.
Will return:
- nil when allowed (all limits pass for given req-id), or
- [<worst-limit-id> <worst-backoff-msecs> {<limit-id> <backoff-msecs>}]
when denied (any limits fail for given req-id).
Or call the limiter fn with an additional command argument:
`:rl/peek` <req-id> - Check limits w/o incrementing count.
`:rl/reset` <req-id> - Reset all limits for given req-id.
Example:
(defonce my-rate-limiter
(rate-limiter
{"1 per sec" [1 1000]
"10 per min" [10 60000]}))
(defn send-message! [username msg-content]
(if-let [fail (my-rate-limiter username)]
(throw (ex-info "Sorry, rate limited!" {:fail fail}))
<send message>))remove-handler!
cljs
(remove-handler! handler-id)
Deregisters signal handler with given id, and returns
?{<handler-id> {:keys [dispatch-opts handler-fn]}} for all signal handlers
still registered.set-ctx!
macro
cljs
(set-ctx! root-val)
Set `*ctx*` var's root (base) value. See `*ctx*` for details.
set-id-filter!
cljs
(set-id-filter! id-filter)
Sets signal call id filter based on given `id-filter` spec.
`id-filter` may be:
- A str/kw/sym, in which "*"s act as wildcards.
- A regex pattern of id/s to allow.
- A vector or set of regex patterns or strs/kws/syms.
- {:allow <spec> :deny <spec>} with specs as above.
If present, `:allow` spec MUST match, AND
If present, `:deny` spec MUST NOT match.set-kind-filter!
cljs
(set-kind-filter! kind-filter)
Sets signal call kind filter based on given `kind-filter` spec.
`kind-filter` may be:
- A str/kw/sym, in which "*"s act as wildcards.
- A regex pattern of kind/s to allow.
- A vector or set of regex patterns or strs/kws/syms.
- {:allow <spec> :deny <spec>} with specs as above.
If present, `:allow` spec MUST match, AND
If present, `:deny` spec MUST NOT match.set-middleware!
macro
cljs
(set-middleware! root-val)
Set `*middleware*` var's root (base) value. See `*middleware*` for details.
set-min-level!
cljs
(set-min-level! min-level)(set-min-level! kind min-level)(set-min-level! kind ns-filter min-level)
Sets minimum signal call level based on given `min-level` spec.
`min-level` may be:
- `nil` (=> no minimum level).
- A level keyword (see `level-aliases` var for details).
- An integer.
If `ns-filter` is provided, then the given minimum level
will apply only for the namespace/s that match `ns-filter`.
See `set-ns-filter!` for details.
If non-nil `kind` is provided, then the given minimum level
will apply only for that signal kind.
Examples:
(set-min-level! nil) ; Disable minimum level
(set-min-level! :info) ; Set `:info` as minimum level
(set-min-level! 100) ; Set 100 as minimum level
;; Set `:debug` as minimum level for current namespace
;; (nil `kind` => apply to all kinds)
(set-min-level! nil *ns* :debug)
set-ns-filter!
cljs
(set-ns-filter! ns-filter)
Sets signal call namespace filter based on given `ns-filter` spec.
`ns-filter` may be:
- A namespace.
- A str/kw/sym, in which "*"s act as wildcards.
- A regex pattern of namespace/s to allow.
- A vector or set of regex patterns or strs/kws/syms.
- {:allow <spec> :deny <spec>} with specs as above.
If present, `:allow` spec MUST match, AND
If present, `:deny` spec MUST NOT match.set-var-root!
macro
cljs
added in Encore v3.75.0 (2024-01-29)
(set-var-root! var-sym root-val)
Sets root binding (value) of the var identified by given symbol, and returns
the new value. Cross-platform. See also `update-var-root!`.
shut-down-handlers!
cljs
(shut-down-handlers!)
Shuts down all registered signal handlers in parallel, and returns
?{<handler-id> {:keys [okay error]}}.
Future calls to handlers will no-op.
Clj only: `shut-down-handlers!` is called automatically on JVM shutdown.signal!
macro
cljs
(signal! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error run & kvs]})
Low-level generic signal creator.
API: [opts] => depends on options [2]
Default kind: none (optional)
Default level: none (must be provided)
When filtering conditions are met [4], creates a Telemere signal [3] and
dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
If `:run` option is provided: returns value of given run form, or throws.
Otherwise: returns true iff signal was created (allowed).
Generic signals are fairly low-level and useful mostly for library authors or
advanced users writing their own wrapper macros. Regular users will typically
prefer one of the higher-level signal creators optimized for ease-of-use in
common cases [1].
Tips:
- Test using `with-signal`: (with-signal (signal! ...)).
- Supports the same options [2] as other signals [1].
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)spy!
macro
cljs
(spy! form)(spy! id form)(spy! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error run & kvs]} form)
"Spy" signal creator, emphasizing form + level.
API: [form] [level-or-opts form] => form's result (value/throw) (unconditional)
Default kind: `:spy`
Default level: `:info`
When filtering conditions are met [4], creates a Telemere signal [3] and
dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
Examples:
(spy! (+ 1 2)) ; %> {:kind :trace, :level :info, :run-form '(+ 1 2),
; :run-val 3, :run-nsecs <int>, :parent {:keys [id uid]}
; :msg "(+ 1 2) => 3" ...}
(spy! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...}
(spy!
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}}
(+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}
Tips:
- Test using `with-signal`: (with-signal (spy! ...)).
- Supports the same options [2] as other signals [1].
- Identical to `trace!`, but emphasizes form + level rather than form + id.
- Useful for debugging/monitoring forms, and tracing (nested) execution flow.
- Execution of `form` arg may create additional (nested) signals.
Each signal's `:parent` key will indicate its immediate parent.
- Can be useful to wrap with `catch->error!`:
(catch->error! ::error-id (spy! ...)).
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)trace!
macro
cljs
(trace! form)(trace! id form)(trace! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error run & kvs]} form)
"Trace" signal creator, emphasizing form + id.
API: [form] [id-or-opts form] => form's result (value/throw) (unconditional)
Default kind: `:trace`
Default level: `:info` (intentionally NOT `:trace`!)
When filtering conditions are met [4], creates a Telemere signal [3] and
dispatches it to registered handlers for processing (e.g. writing to
console/file/queue/db, etc.).
Examples:
(trace! (+ 1 2)) ; %> {:kind :trace, :level :info, :run-form '(+ 1 2),
; :run-val 3, :run-nsecs <int>, :parent {:keys [id uid]} ...
; :msg "(+ 1 2) => 3" ...}
(trace! ::my-id (+ 1 2)) ; %> {... :id ::my-id ...}
(trace!
{:let [x "x"] ; Available to `:data` and `:msg`
:data {:x x}}
(+ 1 2)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}
Tips:
- Test using `with-signal`: (with-signal (trace! ...)).
- Supports the same options [2] as other signals [1].
- Identical to `spy!`, but emphasizes form + id rather than form + level.
- Useful for debugging/monitoring forms, and tracing (nested) execution flow.
- Execution of `form` arg may create additional (nested) signals.
Each signal's `:parent` key will indicate its immediate parent.
- Can be useful to wrap with `catch->error!`:
(catch->error! ::error-id (trace! ...)).
- Default level is `:info`, not `:trace`! The name "trace" in "trace signal"
refers to the general action of tracing program flow rather than to the
common logging level of the same name.
-------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options` - {:keys [kind level id data ...]}
[3] See `help:signal-content` - {:keys [kind level id data ...]}
[4] See `help:signal-flow` - (filters, handling, etc.)uncaught->error!
macro
cljs
(uncaught->error!)(uncaught->error! id)(uncaught->error! {:as opts, :keys [elidable? location inst uid middleware sample-rate kind ns id level when rate-limit ctx parent trace? do let data msg error & kvs]})
Uses `uncaught->handler!` so that `error!` will be called for
uncaught JVM errors.
See `uncaught->handler!` and `error!` for details.
update-var-root!
macro
cljs
added in Encore v3.68.0 (2023-09-25)
(update-var-root! var-sym update-fn)
Updates root binding (value) of the var identified by given symbol, and returns
the new value:
(update-var-root! my-var (fn [old-root-val] <new-root-val>)) => <new-root-val>
Similar to `alter-var-root` but cross-platform and takes a symbol rather than a var.
See also `set-var-root!`.
with-ctx
macro
cljs
(with-ctx init-val form)
Evaluates given form with given `*ctx*` value. See `*ctx*` for details.
with-ctx+
macro
cljs
(with-ctx+ update-map-or-fn form)
Evaluates given form with updated `*ctx*` value.
`update-map-or-fn` may be:
- A map to merge with current `*ctx*` value, or
- A unary fn to apply to current `*ctx*` value
See `*ctx*` for details.
with-err->telemere
macro
cljs
(with-err->telemere form)(with-err->telemere opts form)
Executes form with `*err*` bound to flush to Telemere signals with given opts.
with-handler
macro
cljs
(with-handler handler-id handler-fn dispatch-opts form)
Executes form with ONLY the given handler-fn registered.
Useful for tests/debugging. See also `with-handler+`.
with-handler+
macro
cljs
(with-handler+ handler-id handler-fn dispatch-opts form)
Executes form with the given handler-fn registered.
Useful for tests/debugging. See also `with-handler`.
with-id-filter
macro
cljs
(with-id-filter id-filter form)
Executes form with given signal call id filter in effect.
See `set-id-filter!` for details.
with-kind-filter
macro
cljs
(with-kind-filter kind-filter form)
Executes form with given signal call kind filter in effect.
See `set-kind-filter!` for details.
with-middleware
macro
cljs
(with-middleware init-val form)
Evaluates given form with given `*middleware*` value.
See `*middleware*` for details.
with-min-level
macro
cljs
(with-min-level min-level form)(with-min-level kind min-level form)(with-min-level kind ns-filter min-level form)
Executes form with given minimum signal call level in effect.
See `set-min-level!` for details.
with-ns-filter
macro
cljs
(with-ns-filter ns-filter form)
Executes form with given signal call namespace filter in effect.
See `set-ns-filter!` for details.
with-out->telemere
macro
cljs
(with-out->telemere form)(with-out->telemere opts form)
Executes form with `*out*` bound to flush to Telemere signals with given opts.
with-signal
macro
cljs
(with-signal form)(with-signal trap-signals? form)(with-signal raw-msg? trap-signals? form)
Experimental.
Executes given form, trapping errors. Returns the LAST signal created by form.
Useful for tests/debugging.
Options:
`trap-signals?` (default: false)
Should ALL signals created by form be trapped to prevent normal dispatch
to registered handlers?
`raw-msg?` (default: false)
Should delayed `:msg_` in returned signal be retained as-is?
Delay is otherwise replaced by realized string.
See also `with-signals`.with-signals
macro
cljs
(with-signals form)(with-signals trap-signals? form)(with-signals raw-msgs? trap-signals? form)
Experimental.
Like `with-signal` but returns [[<form-value> <form-error>] [<signal1> ...]].
Useful for tests/debugging.
with-streams->telemere
macro
cljs
(with-streams->telemere form)(with-streams->telemere {:keys [out err], :or {out default-out-opts, err default-err-opts}} form)
Executes form with `*out*` and/or `*err*` bound to flush to Telemere signals
with given opts.
without-filters
macro
cljs
(without-filters form)
Executes form without any runtime filters.