taoensso.telemere

Structured telemetry for Clojure/Script applications.

See the GitHub page (esp. Wiki) for info on motivation and design:
  <https://www.taoensso.com/telemere>

*ctx*

dynamic

clj

cljs

Dynamic context: arbitrary app-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

clj

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!

clj

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.

  `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

  `ns-filter`   - Namespace filter as in `set-ns-filter!`
  `kind-filter` - Kind      filter as in `set-kind-filter!` (when relevant)
  `id-filter`   - Id        filter as in `set-id-filter!`   (when relevant)
  `min-level`   - Minimum   level  as in `set-min-level!`

  `filter-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 (namespace, kind, id, level, filter-fn)
    c. Rate limiting
    d. Middleware

  2. Per handler (n>=0):
    a. Sampling
    b. Filtering (namespace, kind, id, level, filter-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

clj

(catch->error! form)(catch->error! level form)(catch->error! {:as opts, :keys [rethrow? catch-val elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error & user-opts]} form)
TODO Docstring [form] [id-or-opts form] => run value or ?catch-val

chance

clj

cljs

(chance prob)
Returns true with given probability ∈ ℝ[0,1].

check-interop

clj

cljs

(check-interop)
Experimental, subject to change.
Runs Telemere's registered interop checks and returns
{<interop-id> {:keys [sending->telemere? telemere-receiving? ...]}}.

Useful for tests/debugging.

default-ctx

clj

cljs

Advanced feature. Default root (base) value of `*ctx*` var, controlled by:
  (get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>)

See `get-env` for details.

error!

macro

clj

(error! error)(error! id error)(error! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error & user-opts]} error)
TODO Docstring [error] [id-or-opts error] => error
(throw (error! <error>)) example.

event!

macro

clj

(event! id)(event! level id)(event! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error & user-opts]} id)
TODO Docstring [id] [level-or-opts id] => allowed?

filtering-help

clj

cljs

Your filter config determines which signal calls will be enabled.

Filtering can occur at compile-time (=> elision), or runtime.
Both compile-time and runtime config can be specified via:

  1. System values (JVM properties, environment variables, or
     classpath resources). See library docs for details.

  2. The filter API consting of the following:
    `set-ns-filter!`,     `with-ns-filter`      - for filtering calls by namespace
    `set-minimum-level!`, `with-minimum-level!` - for filtering calls by signal level
    `set-id-filter!`,     `with-id-filter`      - for filtering calls by signal id   (when relevant)
    `set-kind-filter!`,   `with-kind-filter`    - for filtering calls by signal kind (when relevant)

    See the relevant docstrings for details.

Additional filtering can also be applied on a per-handler basis, 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!

format-error

clj

cljs

(format-error error)(format-error {:keys [use-fonts? sort-stacktrace-by fonts], :or {use-fonts? :auto, sort-stacktrace-by :chronological, fonts clj-commons.format.exceptions/default-fonts}} error)
TODO Docstring

format-instant

clj

cljs

(format-instant instant)(format-instant {:keys [formatter], :or {formatter java.time.format.DateTimeFormatter/ISO_INSTANT}} instant)
TODO Docstring

get-env

macro

clj

added in Encore v3.75.0 (2024-01-29)

(get-env {:keys [as default return]} spec)(get-env {:keys [as default return spec], :or {as :str, return :value}})
Cross-platform util for embedding flexible environmental config 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 ("prop")
  - Environment variable value   for id ("env")
  - Classpath   resource content for id ("res")

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)].

(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 (content type)
    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 (content type)
    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 (content type)
    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 (content type)
    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 if no value found during search (default nil).
  `:return`  - Return type ∈ #{:value :map :debug} (default :value).
               TIP: Use `:debug` to inspect/verify search behaviour!

Result must be something that can be safely embedded in code during
macro-expansion. Symbols in edn will be evaluated during expansion.

get-filters

clj

cljs

(get-filters)
Returns current ?{:keys [compile-time runtime]} filter config.

get-handlers

clj

cljs

(get-handlers)
Returns ?{<handler-id> {:keys [dispatch-opts handler-fn]}} for all
registered signal handlers.

get-min-level

clj

cljs

(get-min-level)(get-min-level kind)(get-min-level kind ns)
Returns current ?{:keys [compile-time runtime]} minimum levels.

handlers-help

clj

cljs

The handler API consists of the following:
  `get-handlers`    - Returns info on currently registered handlers
  `add-handler!`    - Used to   register handlers
  `remove-handler!` - Used to unregister handlers

See the relevant docstrings for details.

If anything is unclear, please ping me (@ptaoussanis) so that I can
improve these docs!

hostname

clj

(hostname)(hostname timeout-msecs timeout-val)
Returns local cached hostname string, or `timeout-val` (default "UnknownHost").

level-aliases

clj

cljs

Map of {<level-keyword> <level-integer>} aliases.

log!

macro

clj

(log! msg)(log! level msg)(log! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error & user-opts]} msg)
TODO Docstring [msg] [level-or-opts msg] => allowed?

msg-skip

clj

cljs

(msg-skip)
TODO Docstring

msg-splice

clj

cljs

(msg-splice args)
TODO Docstring

newline

clj

cljs

added in Encore v3.68.0 (2023-09-25)

Single system newline

rate-limiter

clj

cljs

(rate-limiter spec)(rate-limiter opts spec)
Takes a map spec of form {<limit-id> [<n-max-reqs> <msecs-window>]},
and returns a basic stateful (fn rate-limiter [req-id] [command req-id]).

Call fn with a single request id (e.g. username) by which to count/limit.
Will return:
  - nil when all limits pass for that id, or
  - [<worst-limit-id> <worst-backoff-msecs> {<limit-id> <backoff-msecs>}]
    when any limits fail for that id.

Or call 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!

clj

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

clj

(set-ctx! root-val)
Set `*ctx*` var's root (base) value. See `*ctx*` for details.

set-id-filter!

clj

cljs

(set-id-filter! id-filter)
Sets signal call id filter based on given `id-filter` spec.

`id-filter` may be:
  - A regex pattern of id/s to allow.
  - A str/kw/sym, in which "*"s act as wildcards.
  - A vector or set of regex patterns or strs/kws/syms.
  - {:allow <spec> :deny <spec>} with specs as above.

set-kind-filter!

clj

cljs

(set-kind-filter! kind-filter)
Sets signal call kind filter based on given `kind-filter` spec.

`kind-filter` may be:
  - A regex pattern of kind/s to allow.
  - A str/kw/sym, in which "*"s act as wildcards.
  - A vector or set of regex patterns or strs/kws/syms.
  - {:allow <spec> :deny <spec>} with specs as above.

set-middleware!

macro

clj

(set-middleware! root-val)
Set `*middleware*` var's root (base) value. See `*middleware*` for details.

set-min-level!

clj

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:
  - An integer.
  - A level keyword (see `level-aliases` var for details).

If `ns-filter` is provided, then the given minimum level
will apply only for namespaces 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.

set-ns-filter!

clj

cljs

(set-ns-filter! ns-filter)
Sets signal call namespace filter based on given `ns-filter` spec.

`ns-filter` may be:
  - A regex pattern of namespace/s to allow.
  - A str/kw/sym, in which "*"s act as wildcards.
  - A vector or set of regex patterns or strs/kws/syms.
  - {:allow <spec> :deny <spec>} with specs as above.

set-var-root!

macro

clj

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!`.

signal!

macro

clj

(signal! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error run & user-opts]})
Expands to a low-level signal call.

TODO Docstring
 - How low-level is this? Should location, ctx, etc. be in public arglists?
 - Describe
 - Reference diagram link [1]
 - Mention ability to delay-wrap :data
 - Mention combo `:sample-rate` stuff (call * handler)

- If :run => returns body run-result (re-throwing)
  Otherwise returns true iff call allowed

[1] Ref. <https://github.com/taoensso/telemere/blob/master/signal-flow.svg>

spy!

macro

clj

(spy! form)(spy! id form)(spy! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error run & user-opts]} form)
TODO Docstring [form] [level-or-opts form] => run result (value or throw)

streams->reset!

clj

(streams->reset!)
Experimental, subject to change without notice!
Resets `System/out` and `System/err` to their original value (prior to any
`streams->telemere!` call).

streams->telemere!

clj

(streams->telemere!)(streams->telemere! {:keys [out err], :or {out default-out-opts, err default-err-opts}})
Experimental, subject to change without notice!

When given `out`, sets JVM's `System/out` to flush to Telemere signals with those opts.
When given `err`, sets JVM's `System/err` to flush to Telemere signals with those opts.

Note that setting `System/out` won't necessarily affect Clojure's `*out*`,
and       setting `System/err` won't necessarily affect Clojure's `*err*`.

See also:
  `with-out->telemere`,
  `with-err->telemere`,
  `with-streams->telemere`.

thread-id

clj

(thread-id)

thread-name

clj

(thread-name)

tools-logging->telemere!

clj

(tools-logging->telemere!)
Configures `clojure.tools.logging` to use Telemere as its logging implementation.

trace!

macro

clj

(trace! form)(trace! id form)(trace! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error run & user-opts]} form)
TODO Docstring [form] [id-or-opts form] => run result (value or throw)

uncaught->error!

macro

clj

(uncaught->error!)(uncaught->error! id)(uncaught->error! {:as opts, :keys [elidable? location instant uid middleware sample-rate ns kind id level filter when rate-limit ctx parent trace? let data msg error & user-opts]})
TODO Docstring
See also `uncaught->handler!`.

uncaught->handler!

clj

(uncaught->handler! handler)
Sets JVM's global `DefaultUncaughtExceptionHandler` to given
  (fn handler [`<java.lang.Thread>` `<java.lang.Throwable>`]).
See also `uncaught->error!`.

update-var-root!

macro

clj

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

clj

(with-ctx init-val form)
Evaluates given form with given `*ctx*` value. See `*ctx*` for details.

with-ctx+

macro

clj

(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

clj

(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

clj

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

clj

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

clj

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

clj

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

clj

(with-middleware init-val form)
Evaluates given form with given `*middleware*` value.
See `*middleware*` for details.

with-min-level

macro

clj

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

clj

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

clj

(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

clj

(with-signal form)(with-signal {:keys [return trap-errors? stop-propagation? force-msg?]} form)
Util for tests/debugging.
Executes given form and returns [<form-result> <last-signal-dispatched-by-form>].
If `trap-errors?` is true, form result will be wrapped by {:keys [okay error]}.

with-streams->telemere

macro

clj

(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

clj

cljs

(without-filters form)
Executes form without any runtime filters.