Liking cljdoc? Tell your friends :D

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

Structured telemetry for Clojure/Script applications.

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

*ctx*clj/s

Optional context (state) attached to all signals. Value may be any type, but is usually nil or a map. Default (root) value is nil.

Useful for dynamically attaching arbitrary app-level state to signals.

Re/bind dynamic value using with-ctx, with-ctx+, or binding. Modify root (default) value using set-ctx!.

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.
  • Use get-env to set default (root) value based on environmental config.
Optional context (state) attached to all signals.
Value may be any type, but is usually nil or a map. Default (root) value is nil.

Useful for dynamically attaching arbitrary app-level state to signals.

Re/bind dynamic        value using `with-ctx`, `with-ctx+`, or `binding`.
Modify  root (default) value using `set-ctx!`.

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.
  - Use `get-env` to set default (root) value based on environmental config.
raw docstring

*middleware*clj/s

Optional (fn [signal]) => ?modified-signal to apply to all signals. When middleware returns nil, skips all handlers. Default (root) value is nil.

Useful for dynamically transforming signals and/or filtering signals by signal data/content/etc.

Re/bind dynamic value using with-middleware, with-middleware+, binding. Modify root (default) value using set-middleware!.

As with all dynamic Clojure vars, "binding conveyance" applies when using futures, agents, etc.

Examples:

;; Filter all signals by returning nil: (t/set-middleware! (fn [signal] (when-not (:skip-me? signal) signal)))

;; Remove key/s from all signals: (t/set-middleware! (fn [signal] (dissoc signal :unwanted-key1 ...)))

;; Remove key/s from signals to specific handler: (t/add-handler! ::my-handler my-handler {:middleware (fn [signal] (dissoc signal :unwanted-key1 ...))})

;; Set middleware for specific signal/s: (binding [middleware (fn [signal] ...)] (...))

Tips:

  • Compose multiple middleware fns together with comp-middleware.
  • Use get-env to set default (root) value based on environmental config.
Optional (fn [signal]) => ?modified-signal to apply to all signals.
When middleware returns nil, skips all handlers. Default (root) value is nil.

Useful for dynamically transforming signals and/or filtering signals
by signal data/content/etc.

Re/bind dynamic        value using `with-middleware`, `with-middleware+`, `binding`.
Modify  root (default) value using `set-middleware!`.

As with all dynamic Clojure vars, "binding conveyance" applies when using
futures, agents, etc.

Examples:

  ;; Filter all signals by returning nil:
  (t/set-middleware! (fn [signal] (when-not (:skip-me? signal) signal)))

  ;; Remove key/s from all signals:
  (t/set-middleware! (fn [signal] (dissoc signal :unwanted-key1 ...)))

  ;; Remove key/s from signals to specific handler:
  (t/add-handler! ::my-handler my-handler
    {:middleware (fn [signal] (dissoc signal :unwanted-key1 ...))})

  ;; Set middleware for specific signal/s:
  (binding [*middleware* (fn [signal] ...)]
    (...))

Tips:
  - Compose multiple middleware fns together with `comp-middleware`.
  - Use `get-env` to set default (root) value based on environmental config.
raw docstring

*otel-tracer*clj


*uid-fn*clj/s

Experimental, subject to change. (fn [root?]) used to generate signal :uid values (unique instance ids) when tracing.

Relevant only when otel-tracing? is false. If otel-tracing? is true, uids are instead generated by *otel-tracer*.

root? argument is true iff signal is a top-level trace (i.e. form being traced is unnested = has no parent form). Root-level uids typically need more entropy and so are usually longer (e.g. 32 vs 16 hex chars).

Override default by setting one of the following: JVM property: taoensso.telemere/uid-fn Env variable: TAOENSSO_TELEMERE_UID_FN Classpath resource: taoensso.telemere/uid-fn

Possible (compile-time) values include: :uuid - UUID string (Cljs) or java.util.UUID (Clj) :uuid-str - UUID string (36/36 chars) :nano/secure - nano-style string (21/10 chars) w/ strong RNG :nano/insecure - nano-style string (21/10 chars) w/ fast RNG (default) :hex/insecure - hex-style string (32/16 chars) w/ strong RNG :hex/secure - hex-style string (32/16 chars) w/ fast RNG

Experimental, subject to change.
(fn [root?]) used to generate signal `:uid` values (unique instance ids)
when tracing.

Relevant only when `otel-tracing?` is false.
If `otel-tracing?` is true, uids are instead generated by `*otel-tracer*`.

`root?` argument is true iff signal is a top-level trace (i.e. form being
traced is unnested = has no parent form). Root-level uids typically need
more entropy and so are usually longer (e.g. 32 vs 16 hex chars).

Override default by setting one of the following:
        JVM property: `taoensso.telemere/uid-fn`
        Env variable: `TAOENSSO_TELEMERE_UID_FN`
  Classpath resource: `taoensso.telemere/uid-fn`

  Possible (compile-time) values include:
    `:uuid`          - UUID string (Cljs) or `java.util.UUID` (Clj)
    `:uuid-str`      - UUID string       (36/36 chars)
    `:nano/secure`   - nano-style string (21/10 chars) w/ strong RNG
    `:nano/insecure` - nano-style string (21/10 chars) w/ fast   RNG (default)
    `:hex/insecure`  - hex-style  string (32/16 chars) w/ strong RNG
    `:hex/secure`    - hex-style  string (32/16 chars) w/ fast   RNG
raw docstring

add-handler!clj/s≠

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 handlers now registered. If an old handler already existed under the same id, stop it.

handler-fn should be a fn of exactly 2 arities:

[signal] ; Single argument Called asynchronously or synchronously (depending on dispatch options) to do something useful with the given signal.

Example actions:
  Save data to disk or 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.

[] ; No arguments Called exactly once when stopping handler to provide an opportunity for handler to flush buffers, close files, etc. May just noop.

NB you should always call stop-handlers! somewhere appropriate - usually near the end of your -main or shutdown procedure, AFTER all other code has completed that could create signals.

See help:handler-dispatch-options for handler filters, etc.

Registers given signal handler and returns
{<handler-id> {:keys [dispatch-opts handler-fn]}} for all handlers
now registered. If an old handler already existed under the same id, stop it.

`handler-fn` should be a fn of exactly 2 arities:

  [signal] ; Single argument
    Called asynchronously or synchronously (depending on dispatch options)
    to do something useful with the given signal.

    Example actions:
      Save data to disk or 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.

  [] ; No arguments
    Called exactly once when stopping handler to provide an opportunity
    for handler to flush buffers, close files, etc. May just noop.

NB you should always call `stop-handlers!` somewhere appropriate - usually
near the end of your `-main` or shutdown procedure, AFTER all other code has
completed that could create signals.

See `help:handler-dispatch-options` for handler filters, etc.
raw docstring

call-on-shutdown!clj

(call-on-shutdown! f)

Registers given nullary fn as a JVM shutdown hook. (f) will be called sometime during shutdown. While running, it will attempt to block shutdown.

Registers given nullary fn as a JVM shutdown hook.
(f) will be called sometime during shutdown. While running, it will
attempt to block shutdown.
raw docstring

catch->error!clj/smacro

(catch->error! form)
(catch->error! id form)
(catch->error! {:as opts
                :keys [rethrow? catch-val elidable? location inst uid middleware
                       middleware+ sample-rate kind ns id level when rate-limit
                       rate-limit-by ctx ctx+ parent root 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 preventing errors from going unnoticed in futures, callbacks, agent actions, etc.!: (future (catch->error ::my-future (do-something)))

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-filters - (by ns/kind/id/level, sampling, etc.)

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 preventing errors from going unnoticed in futures, callbacks,
    agent actions, etc.!: (future (catch->error ::my-future (do-something)))

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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

chanceclj/s

(chance prob)

Returns true with given probability ∈ ℝ[0,1].

Returns true with given probability ∈ ℝ[0,1].
raw docstring

check-interopclj

(check-interop)

Experimental, subject to change. Runs Telemere's registered interop checks and returns info useful for tests/debugging, e.g.:

{:open-telemetry {:present? false} :tools-logging {:present? false} :slf4j {:present? true :sending->telemere? true :telemere-receiving? true} ...}

Experimental, subject to change.
Runs Telemere's registered interop checks and returns info useful
for tests/debugging, e.g.:

  {:open-telemetry {:present? false}
   :tools-logging  {:present? false}
   :slf4j          {:present? true
                    :sending->telemere?  true
                    :telemere-receiving? true}
   ...}
raw docstring

clean-signal-fnclj/s

(clean-signal-fn)
(clean-signal-fn {:keys [incl-kvs? incl-nils? incl-keys] :as opts})

Experimental, subject to change. Returns a (fn clean [signal]) that:

  • Takes a Telemere signal (map).
  • Returns a minimal signal (map) ready for printing, etc.

Signals are optimized for cheap creation and easy handling, so tend to be verbose and may contain things like nil values and duplicated content.

This util efficiently cleans signals of such noise, helping reduce storage/transmission size, and making key info easier to see.

Options: :incl-nils? - Include signal's keys with nil values? (default false) :incl-kvs? - Include signal's app-level root kvs? (default false) :incl-keys - Subset of signal keys to retain from those otherwise excluded by default: #{:location :kvs :file :host :thread}

Experimental, subject to change.
Returns a (fn clean [signal]) that:
  - Takes a Telemere  signal (map).
  - Returns a minimal signal (map) ready for printing, etc.

Signals are optimized for cheap creation and easy handling, so tend to be
verbose and may contain things like nil values and duplicated content.

This util efficiently cleans signals of such noise, helping reduce
storage/transmission size, and making key info easier to see.

Options:
  `:incl-nils?` - Include signal's keys with nil values? (default false)
  `:incl-kvs?`  - Include signal's app-level root kvs?   (default false)
  `:incl-keys`  - Subset of signal keys to retain from those otherwise
                  excluded by default: #{:location :kvs :file :host :thread}
raw docstring

comp-middlewareclj/s

(comp-middleware fs)
(comp-middleware f1 f2)
(comp-middleware f1 f2 f3)
(comp-middleware f1 f2 f3 & fs)

Returns a single (composite) unary fn that applies all given unary fns sequentially (left->right!: f1, f2, ...). If any given fn returns nil, the returned composite fn immediately returns nil:

((comp-middleware inc #(* % 2) inc) 1) => 5 ; (inc (* (inc 1) 2)) ((comp-middleware inc (fn [_] nil) (fn [_] (throw (Exception. "Never thrown!")))) 1) => nil

Useful for composing Ring-style middleware fns.

Returns a single (composite) unary fn that applies all given unary fns
sequentially (left->right!: f1, f2, ...). If any given fn returns nil, the
returned composite fn immediately returns nil:

  ((comp-middleware inc #(* % 2) inc) 1) => 5 ; (inc (* (inc 1) 2))
  ((comp-middleware inc (fn [_] nil) (fn [_] (throw (Exception. "Never thrown!")))) 1) => nil

Useful for composing Ring-style middleware fns.
raw docstring

default-handler-dispatch-optsclj/s≠

clj

Default handler dispatch options, see help:handler-dispatch-options for details.

Default handler dispatch options, see
`help:handler-dispatch-options` for details.
raw docstring

dispatch-signal!clj/s

(dispatch-signal! signal)

Dispatches given signal to registered handlers, supports with-signal/s. Normally called automatically (internally) by signal creators, this util is provided publicly since it's also handy for manually re/dispatching custom/modified signals, etc.:

(let [original-signal (with-signal :trap (event! ::my-id1)) modified-signal (assoc original-signal :id ::my-id2)] (dispatch-signal! modified-signal))

Dispatches given signal to registered handlers, supports `with-signal/s`.
Normally called automatically (internally) by signal creators, this util
is provided publicly since it's also handy for manually re/dispatching
custom/modified signals, etc.:

  (let [original-signal (with-signal :trap (event! ::my-id1))
        modified-signal (assoc original-signal :id ::my-id2)]
    (dispatch-signal! modified-signal))
raw docstring

error!clj/smacro

(error! error)
(error! id error)
(error! {:as opts
         :keys [elidable? location inst uid middleware middleware+ sample-rate
                kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
                root 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-filters - (by ns/kind/id/level, sampling, etc.)

"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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

error-signal?clj/s

(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.

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.
raw docstring

event!clj/smacro

(event! id)
(event! id level)
(event! id
        {:as opts
         :keys [elidable? location inst uid middleware middleware+ sample-rate
                kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
                root 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-filters - (by ns/kind/id/level, sampling, etc.)

"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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

format-signal-fnclj/s

(format-signal-fn)
(format-signal-fn {:keys [incl-newline? preamble-fn content-fn]
                   :or {incl-newline? true
                        preamble-fn (signal-preamble-fn)
                        content-fn (signal-content-fn)}})

Experimental, subject to change. Returns a (fn format [signal]) that:

  • Takes a Telemere signal (map).
  • Returns a human-readable signal string.

Options: :incl-newline? - Include terminating system newline? (default true) :preamble-fn - (fn [signal]) => signal preamble string, see [1] :content-fn - (fn [signal]) => signal content string, see [2]

[1] taoensso.telemere.utils/signal-preamble-fn, etc. [2] taoensso.telemere.utils/signal-content-fn, etc.

See also pr-signal-fn for an alternative to format-signal-fn that produces machine-readable output (edn, JSON, etc.).

Experimental, subject to change.
Returns a (fn format [signal]) that:
  - Takes a Telemere signal (map).
  - Returns a human-readable signal string.

Options:
  `:incl-newline?` - Include terminating system newline? (default true)
  `:preamble-fn`   - (fn [signal]) => signal preamble string, see [1]
  `:content-fn`    - (fn [signal]) => signal content  string, see [2]

[1] `taoensso.telemere.utils/signal-preamble-fn`, etc.
[2] `taoensso.telemere.utils/signal-content-fn`,  etc.

See also `pr-signal-fn` for an alternative to `format-signal-fn`
that produces machine-readable output (edn, JSON, etc.).
raw docstring

get-envclj/smacro

(get-env {:keys [as default return] :or {as :str return :value}} spec)

Flexible cross-platform util to return an environmental config value.

Given an id (const keyword/string) 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: <.platform> => ".clj" / ".cljs" <platform-> => "clj-" / "cljs-", etc.

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

For Cljs: resulting config value must be something that can be safely embedded in code during macro expansion!

Advanced: if resulting config value is a single top-level symbol, it will be evaluated during macro 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.

Flexible cross-platform util to return an environmental config value.

Given an id (const keyword/string) 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:
  `<.platform>` => ".clj" / ".cljs"
  `<platform->` => "clj-" / "cljs-", etc.

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 (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 (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 (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 (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`).

For Cljs: resulting config value must be something that can be safely
          embedded in code during macro expansion!

Advanced: if resulting config value is a single top-level symbol, it will
          be evaluated during macro 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.
raw docstring

get-filtersclj/s

(get-filters)

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

Returns current ?{:keys [compile-time runtime]} filter config.
raw docstring

get-handlersclj/s

(get-handlers)

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

Returns ?{<handler-id> {:keys [dispatch-opts handler-fn handler-stats_]}}
for all registered signal handlers.
raw docstring

get-handlers-statsclj/s

(get-handlers-stats)

Alpha, subject to change. Returns ?{<handler-id> {:keys [handling-nsecs counts]}} for all registered signal handlers that have the :track-stats? dispatch option enabled (it is by default).

Stats include:

:handling-nsecs - Summary stats of nanosecond handling times, keys: :min - Minimum handling time :max - Maximum handling time :mean - Arithmetic mean handling time :mad - Mean absolute deviation of handling time (measure of dispersion) :var - Variance of handling time (measure of dispersion) :p50 - 50th percentile of handling time (50% of times <= this) :p90 - 90th percentile of handling time (90% of times <= this) :p99 - 99th percentile of handling time :last - Most recent handling time ...

:counts - Integer counts for handler outcomes, keys (chronologically):

`:dropped`       - Noop handler calls due to stopped handler
`:back-pressure` - Handler calls that experienced (async) back-pressure
                   (possible noop, depending on back-pressure mode)

 `:sampled`      - Noop  handler calls due to sample rate
 `:filtered`     - Noop  handler calls due to kind/ns/id/level/when filtering
 `:rate-limited` - Noop  handler calls due to rate limit
 `:disallowed`   - Noop  handler calls due to sampling/filtering/rate-limiting
 `:allowed`      - Other handler calls    (no sampling/filtering/rate-limiting)

 `:suppressed`   - Noop handler calls due to nil middleware result
 `:handled`      - Handler calls that completed successfully
 `:errors`       - Handler calls that threw an error

 Note that for performance reasons returned counts are not mutually atomic,
 e.g. `:sampled` count may be incremented before `:disallowed` count is.

Useful for understanding/debugging how your handlers behave in practice, especially when they're under stress (high-volumes, etc.).

Handler stats are tracked from the time each handler is last registered (e.g. with an add-handler! call).

Alpha, subject to change.
Returns ?{<handler-id> {:keys [handling-nsecs counts]}} for all registered
signal handlers that have the `:track-stats?` dispatch option enabled
(it is by default).

Stats include:

  `:handling-nsecs` - Summary stats of nanosecond handling times, keys:
    `:min`  - Minimum handling time
    `:max`  - Maximum handling time
    `:mean` - Arithmetic mean handling time
    `:mad`  - Mean absolute deviation of handling time (measure of dispersion)
    `:var`  - Variance                of handling time (measure of dispersion)
    `:p50`  - 50th percentile of handling time (50% of times <= this)
    `:p90`  - 90th percentile of handling time (90% of times <= this)
    `:p99`  - 99th percentile of handling time
    `:last` - Most recent        handling time
    ...

  `:counts` - Integer counts for handler outcomes, keys (chronologically):

    `:dropped`       - Noop handler calls due to stopped handler
    `:back-pressure` - Handler calls that experienced (async) back-pressure
                       (possible noop, depending on back-pressure mode)

     `:sampled`      - Noop  handler calls due to sample rate
     `:filtered`     - Noop  handler calls due to kind/ns/id/level/when filtering
     `:rate-limited` - Noop  handler calls due to rate limit
     `:disallowed`   - Noop  handler calls due to sampling/filtering/rate-limiting
     `:allowed`      - Other handler calls    (no sampling/filtering/rate-limiting)

     `:suppressed`   - Noop handler calls due to nil middleware result
     `:handled`      - Handler calls that completed successfully
     `:errors`       - Handler calls that threw an error

     Note that for performance reasons returned counts are not mutually atomic,
     e.g. `:sampled` count may be incremented before `:disallowed` count is.

Useful for understanding/debugging how your handlers behave in practice,
especially when they're under stress (high-volumes, etc.).

Handler stats are tracked from the time each handler is last registered
(e.g. with an `add-handler!` call).
raw docstring

get-min-levelsclj/s

(get-min-levels)
(get-min-levels kind)
(get-min-levels kind ns)

Returns current ?{:keys [compile-time runtime]} minimum signal levels.

Returns current ?{:keys [compile-time runtime]} minimum signal levels.
raw docstring

handler:consoleclj/s≠

clj
(handler:console)
(handler:console {:keys [stream output-fn]
                  :or {stream :auto output-fn (utils/format-signal-fn)}})

Experimental, subject to change.

Returns a signal handler that:

  • Takes a Telemere signal (map).
  • Writes the signal as a string to specified stream.

A general-purpose println-style handler that's well suited for outputting signals as human or machine-readable (edn, JSON) strings.

Options: :output-fn - (fn [signal]) => string, see format-signal-fn or pr-signal-fn :stream - java.io.writer Defaults to *err* if utils/error-signal? is true, and *out* otherwise.

Experimental, subject to change.

Returns a signal handler that:
  - Takes a Telemere signal (map).
  - Writes the signal as a string to specified stream.

A general-purpose `println`-style handler that's well suited for outputting
signals as human or machine-readable (edn, JSON) strings.

Options:
  `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
  `:stream`    - `java.io.writer`
    Defaults to `*err*` if `utils/error-signal?` is true, and `*out*` otherwise.
cljs
(handler:console)
(handler:console {:keys [output-fn] :or {output-fn (utils/format-signal-fn)}})

Experimental, subject to change.

If js/console exists, returns a signal handler that:

  • Takes a Telemere signal (map).
  • Writes the signal as a string to JavaScript console.

A general-purpose println-style handler that's well suited for outputting signals as human or machine-readable (edn, JSON) strings.

Options: :output-fn - (fn [signal]) => string, see format-signal-fn or pr-signal-fn

Experimental, subject to change.

If `js/console` exists, returns a signal handler that:
  - Takes a Telemere signal (map).
  - Writes the signal as a string to JavaScript console.

A general-purpose `println`-style handler that's well suited for outputting
signals as human or machine-readable (edn, JSON) strings.

Options:
  `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
raw docstring

handler:console-rawcljs

(handler:console-raw)
(handler:console-raw {:keys [preamble-fn format-nsecs-fn]
                      :as opts
                      :or {preamble-fn (utils/signal-preamble-fn)
                           format-nsecs-fn (utils/format-nsecs-fn)}})

Experimental, subject to change.

If js/console exists, returns a signal handler that:

  • Takes a Telemere signal (map).
  • Writes the raw signal to JavaScript console.

Intended for use with browser formatting tools like binaryage/devtools, Ref. https://github.com/binaryage/cljs-devtools.

Options: :preamble-fn - (fn [signal]) => string, see [1]. :format-nsecs-fn - (fn [nanosecs]) => string.

[1] taoensso.telemere.utils/signal-preamble-fn, etc.

Experimental, subject to change.

If `js/console` exists, returns a signal handler that:
  - Takes a Telemere signal (map).
  - Writes the raw signal to JavaScript console.

Intended for use with browser formatting tools like `binaryage/devtools`,
Ref. <https://github.com/binaryage/cljs-devtools>.

Options:
  `:preamble-fn`     - (fn [signal])   => string, see [1].
  `:format-nsecs-fn` - (fn [nanosecs]) => string.

[1] `taoensso.telemere.utils/signal-preamble-fn`, etc.
raw docstring

handler:fileclj

(handler:file)
(handler:file {:keys [output-fn path interval max-file-size max-num-parts
                      max-num-intervals gzip-archives?]
               :or {output-fn (utils/format-signal-fn)
                    path "logs/telemere.log"
                    interval :monthly
                    max-file-size (* 1024 1024 4)
                    max-num-parts 8
                    max-num-intervals 6
                    gzip-archives? true}})

Experimental, subject to change.

Returns a signal handler that:

  • Takes a Telemere signal (map).
  • Writes (appends) the signal as a string to file specified by path.

Depending on options, archives may be maintained:

  • logs/app.log.n.gz (for nil :interval, non-nil :max-file-size)
  • logs/app.log-YYYY-MM-DDd.n.gz (for non-nil :interval) ; d=daily/w=weekly/m=monthly

Can output signals as human or machine-readable (edn, JSON) strings.

Example files with default options: /logs/telemere.log ; Current file /logs/telemere.log-2020-01-01m.1.gz ; Archive for Jan 2020, part 1 (newest entries) ... /logs/telemere.log-2020-01-01m.8.gz ; Archive for Jan 2020, part 8 (oldest entries)

Options: :output-fn- (fn [signal]) => string, see format-signal-fn or pr-signal-fn :path - Path string of the target output file (default logs/telemere.log)

:interval - ∈ #{nil :daily :weekly :monthly} (default :monthly) When non-nil, causes interval-based archives to be maintained.

:max-file-size ∈ #{nil <pos-int>} (default 4MB) When path file size > ~this many bytes, rotates old content to numbered archives.

:max-num-parts ∈ #{nil <pos-int>} (default 8) Maximum number of numbered archives to retain for any particular interval.

:max-num-intervals ∈ #{nil <pos-int>} (default 6) Maximum number of intervals (days/weeks/months) to retain.

Experimental, subject to change.

Returns a signal handler that:
  - Takes a Telemere signal (map).
  - Writes (appends) the signal as a string to file specified by `path`.

Depending on options, archives may be maintained:
  - `logs/app.log.n.gz`             (for     nil `:interval`, non-nil `:max-file-size`)
  - `logs/app.log-YYYY-MM-DDd.n.gz` (for non-nil `:interval`) ; d=daily/w=weekly/m=monthly

Can output signals as human or machine-readable (edn, JSON) strings.

Example files with default options:
  `/logs/telemere.log`                  ; Current file
  `/logs/telemere.log-2020-01-01m.1.gz` ; Archive for Jan 2020, part 1 (newest entries)
  ...
  `/logs/telemere.log-2020-01-01m.8.gz` ; Archive for Jan 2020, part 8 (oldest entries)

Options:
  `:output-fn`- (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
  `:path`     - Path string of the target output file (default `logs/telemere.log`)

  `:interval` - ∈ #{nil :daily :weekly :monthly} (default `:monthly`)
    When non-nil, causes interval-based archives to be maintained.

  `:max-file-size` ∈ #{nil <pos-int>} (default 4MB)
    When `path` file size > ~this many bytes, rotates old content to numbered archives.

  `:max-num-parts` ∈ #{nil <pos-int>} (default 8)
    Maximum number of numbered archives to retain for any particular interval.

  `:max-num-intervals` ∈ #{nil <pos-int>} (default 6)
    Maximum number of intervals (days/weeks/months) to retain.
raw docstring

help:environmental-configclj/s

Telemere supports extensive environmental config via JVM properties, environment variables, or classpath resources.

Environmental filter config includes:

Kind filter: JVM property: taoensso.telemere.rt-kind-filter Env variable: TAOENSSO_TELEMERE_RT_KIND_FILTER Classpath resource: taoensso.telemere.rt-kind-filter

Namespace filter: JVM property: taoensso.telemere.rt-ns-filter Env variable: TAOENSSO_TELEMERE_RT_NS_FILTER Classpath resource: taoensso.telemere.rt-ns-filter

Id filter: JVM property: taoensso.telemere.rt-id-filter Env variable: TAOENSSO_TELEMERE_RT_ID_FILTER Classpath resource: taoensso.telemere.rt-id-filter

Minimum level: JVM property: taoensso.telemere.rt-min-level Env variable: TAOENSSO_TELEMERE_RT_MIN_LEVEL Classpath resource: taoensso.telemere.rt-min-level

Values are edn, examples:

taoensso.telemere.rt-min-level -> ":info" TAOENSSO_TELEMERE_RT_NS_FILTER -> "{:disallow "taoensso.*"}" taoensso.telemere.rt-id-filter.cljs -> "#{:my-id1 :my-id2}" TAOENSSO_TELEMERE_RT_KIND_FILTER_CLJ -> "nil"

For other (non-filter) environmental config, see the relevant docstrings.

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.

  • Optional ".edn" / "_EDN" suffixes may be added for clarity.

  • To get the right edn 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.

Telemere supports extensive environmental config via JVM properties,
environment variables, or classpath resources.

Environmental filter config includes:

  Kind filter:
          JVM property: `taoensso.telemere.rt-kind-filter`
          Env variable: `TAOENSSO_TELEMERE_RT_KIND_FILTER`
    Classpath resource: `taoensso.telemere.rt-kind-filter`

  Namespace filter:
          JVM property: `taoensso.telemere.rt-ns-filter`
          Env variable: `TAOENSSO_TELEMERE_RT_NS_FILTER`
    Classpath resource: `taoensso.telemere.rt-ns-filter`

  Id filter:
          JVM property: `taoensso.telemere.rt-id-filter`
          Env variable: `TAOENSSO_TELEMERE_RT_ID_FILTER`
    Classpath resource: `taoensso.telemere.rt-id-filter`

  Minimum level:
          JVM property: `taoensso.telemere.rt-min-level`
          Env variable: `TAOENSSO_TELEMERE_RT_MIN_LEVEL`
    Classpath resource: `taoensso.telemere.rt-min-level`

Values are edn, examples:

  `taoensso.telemere.rt-min-level`       -> ":info"
  `TAOENSSO_TELEMERE_RT_NS_FILTER`       -> "{:disallow \"taoensso.*\"}"
  `taoensso.telemere.rt-id-filter.cljs`  -> "#{:my-id1 :my-id2}"
  `TAOENSSO_TELEMERE_RT_KIND_FILTER_CLJ` -> "nil"

For other (non-filter) environmental config, see the relevant docstrings.

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.

  - Optional ".edn" / "_EDN" suffixes may be added for clarity.

  - To get the right edn 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.
raw docstring

help:filtersclj/s

A signal will be provided to a handler iff ALL of the following are true:

  1. Signal creation is allowed by "signal filters": a. Compile-time: sample rate, kind, ns, id, level, when form, rate limit b. Runtime: sample rate, kind, ns, id, level, when form, rate limit

  2. Signal handling is allowed by "handler filters": a. Compile-time: not applicable b. Runtime: sample rate, kind, ns, id, level, when fn, rate limit

  3. Signal middleware (fn [signal]) => ?modified-signal does not return nil

  4. Handler middleware (fn [signal]) => ?modified-signal does not return nil

Note that middleware provides a flexible way to filter signals by arbitrary signal data/content conditions (return nil to filter signal).

Config:

To set signal filters (1a, 1b):

Use:
  `set-kind-filter!`, `with-kind-filter`
  `set-ns-filter!`,   `with-ns-filter`
  `set-id-filter!`,   `with-id-filter`
  `set-min-level!`,   `with-min-level`
  or see `help:environmental-config`.

To set handler filters (2b) or handler middleware (4):

Provide relevant opts when calling `add-handler!` or `with-handler/+`.
See `help:handler-dispatch-options` for details.

Note: signal filters (1a, 1b) should generally be AT LEAST as permissive as
handler filters (2b), otherwise signals will be filtered before even
reaching handlers.

To set signal middleware (3): use set-middleware!, with-middleware

Compile-time vs runtime filters:

Compile-time filters are an advanced feature that can be tricky to set and use correctly. Most folks will want ONLY runtime filters.

Compile-time filters works by eliding (completely removing the code for) disallowed signals. This means zero performance cost for these signals, but also means that compile-time filters are PERMANENT once applied.

So if you set :info as the compile-time minimum level, that'll REMOVE CODE for every signal below :info level. To decrease that minimum level, you'll need to rebuild.

Compile-time filters can be set ONLY with environmental config (see help:environmental-config for details).

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 final (multiplicative) rate is helpfully reflected in each signal's :sample-rate value.

For more info:

  • On signal filters, see: help:filters
  • On handler filters, see: help:handler-dispatch-options

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

A signal will be provided to a handler iff ALL of the following are true:

  1. Signal creation is allowed by "signal filters":
    a. Compile-time: sample rate, kind, ns, id, level, when form, rate limit
    b. Runtime:      sample rate, kind, ns, id, level, when form, rate limit

  2. Signal handling is allowed by "handler filters":
    a. Compile-time: not applicable
    b. Runtime:      sample rate, kind, ns, id, level, when fn, rate limit

  3. Signal  middleware (fn [signal]) => ?modified-signal does not return nil
  4. Handler middleware (fn [signal]) => ?modified-signal does not return nil

Note that middleware provides a flexible way to filter signals by arbitrary
signal data/content conditions (return nil to filter signal).

Config:

  To set signal filters (1a, 1b):

    Use:
      `set-kind-filter!`, `with-kind-filter`
      `set-ns-filter!`,   `with-ns-filter`
      `set-id-filter!`,   `with-id-filter`
      `set-min-level!`,   `with-min-level`
      or see `help:environmental-config`.

  To set handler filters (2b) or handler middleware (4):

    Provide relevant opts when calling `add-handler!` or `with-handler/+`.
    See `help:handler-dispatch-options` for details.

    Note: signal filters (1a, 1b) should generally be AT LEAST as permissive as
    handler filters (2b), otherwise signals will be filtered before even
    reaching handlers.

  To set signal middleware (3): use `set-middleware!`, `with-middleware`

Compile-time vs runtime filters:

  Compile-time filters are an advanced feature that can be tricky to set
  and use correctly. Most folks will want ONLY runtime filters.

  Compile-time filters works by eliding (completely removing the code for)
  disallowed signals. This means zero performance cost for these signals,
  but also means that compile-time filters are PERMANENT once applied.

  So if you set `:info` as the compile-time minimum level, that'll REMOVE
  CODE for every signal below `:info` level. To decrease that minimum level,
  you'll need to rebuild.

  Compile-time filters can be set ONLY with environmental config
  (see `help:environmental-config` for details).

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 final (multiplicative) rate is helpfully reflected in each signal's
  `:sample-rate` value.

For more info:

  - On signal  filters, see: `help:filters`
  - On handler filters, see: `help:handler-dispatch-options`

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

help:handler-dispatch-optionsclj/s

Dispatch options can be provided for each signal handler when calling add-handler! or with-handler/+. These options will be merged over the defaults specified by default-handler-dispatch-opts.

All handlers support the same dispatch options, including:

:async (Clj only) options include:

`:buffer-size` (default 1024)
  Size of request buffer, and the max number of pending requests before
  configured back-pressure behaviour is triggered (see `:mode`).

`:mode` (default `:blocking`)
  Back-pressure mode ∈ #{:blocking :dropping :sliding}.
  Controls what happens when a new request is made while request buffer is full:
    `:blocking` => Blocks caller until buffer space is available
    `:dropping` => Drops the newest request (noop)
    `:sliding`  => Drops the oldest request

`:n-threads` (default 1)
  Number of threads to use for executing fns (servicing request buffer).
  NB execution order may be non-sequential when n > 1.

`:drain-msecs` (default 6000 msecs)
  Maximum time (in milliseconds) to try allow pending execution requests to
  complete when stopping handler. nil => no maximum.

:priority (default 100) Optional handler priority ∈ℤ. Handlers will be called in descending priority order (larger ints first).

:track-stats? (default true) Should handler track statistics (e.g. handling times) for reporting by get-handlers-stats?

:sample-rate (default nil => no sampling) 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 (default nil => always allow) 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. Useful for filtering based on external state/context.

See `:middleware` for an alternative that takes a signal argument.

:rate-limit (default nil => no 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 (default nil => no middleware) Optional (fn [signal]) => ?modified-signal to apply before handling signal. When middleware returns nil, skips handler.

Compose multiple middleware fns together with `comp-middleware`.

:error-fn - (fn [{:keys [handler-id signal error]}]) to call on handler error. :backp-fn - (fn [{:keys [handler-id ]}]) to call on handler back-pressure.

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

Dispatch options can be provided for each signal handler when calling
`add-handler!` or `with-handler/+`. These options will be merged over the
defaults specified by `default-handler-dispatch-opts`.

All handlers support the same dispatch options, including:

  `:async` (Clj only) options include:

    `:buffer-size` (default 1024)
      Size of request buffer, and the max number of pending requests before
      configured back-pressure behaviour is triggered (see `:mode`).

    `:mode` (default `:blocking`)
      Back-pressure mode ∈ #{:blocking :dropping :sliding}.
      Controls what happens when a new request is made while request buffer is full:
        `:blocking` => Blocks caller until buffer space is available
        `:dropping` => Drops the newest request (noop)
        `:sliding`  => Drops the oldest request

    `:n-threads` (default 1)
      Number of threads to use for executing fns (servicing request buffer).
      NB execution order may be non-sequential when n > 1.

    `:drain-msecs` (default 6000 msecs)
      Maximum time (in milliseconds) to try allow pending execution requests to
      complete when stopping handler. nil => no maximum.

  `:priority` (default 100)
    Optional handler priority ∈ℤ.
    Handlers will be called in descending priority order (larger ints first).

  `:track-stats?` (default true)
    Should handler track statistics (e.g. handling times) for
    reporting by `get-handlers-stats`?

  `:sample-rate` (default nil => no sampling)
    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` (default nil => always allow)
    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. Useful for filtering based on external state/context.

    See `:middleware` for an alternative that takes a signal argument.

  `:rate-limit` (default nil => no 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` (default nil => no middleware)
    Optional (fn [signal]) => ?modified-signal to apply before
    handling signal. When middleware returns nil, skips handler.

    Compose multiple middleware fns together with `comp-middleware`.

  `:error-fn` - (fn [{:keys [handler-id signal error]}]) to call on handler error.
  `:backp-fn` - (fn [{:keys [handler-id             ]}]) to call on handler back-pressure.

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

help:handlersclj/s

Signal handlers process created signals to do something with them (analyse them, write them to console/file/queue/db, etc.).

Manage handlers with:

get-handlers - Returns info on registered handlers (dispatch options, etc.) get-handlers-stats - Returns stats for registered handlers (handling times, etc.)

add-handler! - Registers given handler remove-handler! - Unregisters given handler

with-handler - Executes form with ONLY the given handler registered with-handler+ - Executes form with the given handler (also) registered

stop-handlers! - Stops registered handlers NB you should always call stop-handlers! somewhere appropriate - usually near the end of your -main or shutdown procedure, AFTER all other code has completed that could create signals.

See the relevant docstrings for details. See help:handler-dispatch-options for handler filters, etc.

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

Signal handlers process created signals to do something with them (analyse them,
      write them to console/file/queue/db, etc.).

Manage handlers with:

  `get-handlers`       - Returns info  on  registered handlers (dispatch options, etc.)
  `get-handlers-stats` - Returns stats for registered handlers (handling times,   etc.)

  `add-handler!`       - Registers   given handler
  `remove-handler!`    - Unregisters given handler

  `with-handler`       - Executes form with ONLY the given handler        registered
  `with-handler+`      - Executes form with      the given handler (also) registered

  `stop-handlers!`     - Stops registered handlers
    NB you should always call `stop-handlers!` somewhere appropriate - usually
    near the end of your `-main` or shutdown procedure, AFTER all other code has
    completed that could create signals.

See the relevant docstrings for details.
See `help:handler-dispatch-options` for handler filters, etc.

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

help:signal-contentclj/s

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 :slf4j :tools-logging <app-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 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 :error ------- Arb app-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 app-level state) when signal was created :parent ------ ?{:keys [id uid]} of parent signal, present in nested signals when tracing :root -------- ?{:keys [id uid]} of root 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)

:host -------- (Clj only) {:keys [name ip]} info for network host :thread ------ (Clj only) {:keys [name id group]} info for thread that created signal

:sample-rate - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all)

<kvs> ---------- Other arb app-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

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 :slf4j :tools-logging <app-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 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
`:error` ------- Arb app-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 app-level state) when signal was created
`:parent` ------ ?{:keys [id uid]} of parent signal, present in nested signals when tracing
`:root` -------- ?{:keys [id uid]} of root   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)

`:host` -------- (Clj only) {:keys [name ip]}       info for network host
`:thread` ------ (Clj only) {:keys [name id group]} info for thread that created signal

`:sample-rate` - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all)

<kvs> ---------- Other arb app-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`
raw docstring

help:signal-creatorsclj/s

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:

event! -------- [id ] or [id opts/level] => true iff signal was created (allowed) log! ---------- [msg ] or [opts/level msg] => true iff signal was created (allowed) error! -------- [error] or [opts/id error] => given error (unconditional) trace! -------- [form ] or [opts/id form] => form result (value/throw) (unconditional) spy! ---------- [form ] or [opts/level form] => form result (value/throw) (unconditional) catch->error! - [form ] or [opts/id form] => 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-filters - (by ns/kind/id/level, sampling, etc.)

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:

  `event!` -------- [id   ] or [id   opts/level] => true iff signal was created (allowed)
  `log!` ---------- [msg  ] or [opts/level  msg] => true iff signal was created (allowed)
  `error!` -------- [error] or [opts/id   error] => given error (unconditional)
  `trace!` -------- [form ] or [opts/id    form] => form result (value/throw) (unconditional)
  `spy!` ---------- [form ] or [opts/level form] => form result (value/throw) (unconditional)
  `catch->error!` - [form ] or [opts/id    form] => 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-filters` - (by ns/kind/id/level, sampling, etc.)
raw docstring

help:signal-optionsclj/s

Signal options (shared by all signal creators):

:inst -------- Platform instant [1] when signal was created, ∈ #{nil :auto <[1]>} :level ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...} :kind -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy <app-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) Defaults to :auto for tracing signals, and nil otherwise

:msg --------- Arb app-level ?message to incl. in signal: str or vec of strs to join (with \space) :data -------- Arb app-level ?data to incl. in signal: usu. a map :error ------- Arb app-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!)

:parent ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal tracing info :root -------- Custom ?{:keys [id uid]} to override auto (dynamic) root signal tracing info :location ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location :ctx --------- Custom ?val to override auto (dynamic *ctx*) in signal, as per with-ctx :ctx+ -------- Custom ?val to update auto (dynamic *ctx*) in signal, as per with-ctx+

: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 :rate-limit-by When present, rate limits will be enforced independently for each id (any Clojure value!) :middleware -- Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per with-middleware :middleware+ - Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per with-middleware+ :trace? ------ Should tracing be enabled for :run form?

<kvs> ---------- Other arb app-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.

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

Signal options (shared by all signal creators):

`:inst` -------- Platform instant [1] when signal was created, ∈ #{nil :auto <[1]>}
`:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy <app-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`)
                 Defaults to `:auto` for tracing signals, and nil otherwise

`:msg` --------- Arb app-level ?message to incl. in signal: str or vec of strs to join (with `\space`)
`:data` -------- Arb app-level ?data    to incl. in signal: usu. a map
`:error` ------- Arb app-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!)

`:parent` ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal tracing info
`:root` -------- Custom ?{:keys [id uid]} to override auto (dynamic) root   signal tracing info
`:location` ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location
`:ctx` --------- Custom ?val to override auto (dynamic `*ctx*`) in signal, as per `with-ctx`
`:ctx+` -------- Custom ?val to update   auto (dynamic `*ctx*`) in signal, as per `with-ctx+`

`: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
`:rate-limit-by` When present, rate limits will be enforced independently for each id (any Clojure value!)
`:middleware` -- Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-middleware`
`:middleware+` - Optional (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-middleware+`
`:trace?` ------ Should tracing be enabled for `:run` form?

<kvs> ---------- Other arb app-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.

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`
raw docstring

level-aliasesclj/s≠

clj

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

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

log!clj/smacro

(log! msg)
(log! level msg)
(log! {:as opts
       :keys [elidable? location inst uid middleware middleware+ sample-rate
              kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
              root 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-filters - (by ns/kind/id/level, sampling, etc.)

"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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

msg-skipclj/s≠

clj

For use within signal message vectors. Special value that will be ignored (noop) when creating message. Useful for conditionally skipping parts of message content, etc.:

(signal! {:msg ["Hello" (if <cond> <then> msg-skip) "world"] <...>}) or (log! ["Hello" (if <cond> <then> msg-skip) "world"]), etc.

%> {:msg_ "Hello world" <...>}
For use within signal message vectors.
Special value that will be ignored (noop) when creating message.
Useful for conditionally skipping parts of message content, etc.:

  (signal! {:msg ["Hello" (if <cond> <then> msg-skip) "world"] <...>}) or
  (log!          ["Hello" (if <cond> <then> msg-skip) "world"]), etc.

    %> {:msg_ "Hello world" <...>}
raw docstring

msg-spliceclj/s

(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"}
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"}
raw docstring

newlineclj/s

Single system newline

Single system newline
raw docstring

otel-default-providers_clj


otel-tracing?clj

Experimental, subject to change. Feedback welcome!

Should Telemere's tracing signal creators (trace!, spy!, etc.) interop with OpenTelemetry Java [1]? This will affect relevant Telemere macro expansions.

Defaults to true iff OpenTelemetry Java is present when this namespace is evaluated/compiled.

If false:

  1. Telemere's OpenTelemetry handler will NOT emit to SpanExporters.
  2. Telemere and OpenTelemetry will NOT recognize each other's spans.

If true:

  1. Telemere's OpenTelemetry handler WILL emit to SpanExporters.
  2. Telemere and OpenTelemetry WILL recognize each other's spans.

Override default by setting one of the following to "true" or "false": JVM property: taoensso.telemere.otel-tracing Env variable: TAOENSSO_TELEMERE_otel-tracing Classpath resource: taoensso.telemere.otel-tracing

See also: otel-default-providers_, *otel-tracer*, taoensso.telemere.open-telemere/handler:open-telemetry.

[1] Ref. https://github.com/open-telemetry/opentelemetry-java

Experimental, subject to change. Feedback welcome!

Should Telemere's tracing signal creators (`trace!`, `spy!`, etc.)
interop with OpenTelemetry Java [1]? This will affect relevant
Telemere macro expansions.

Defaults to `true` iff OpenTelemetry Java is present when this
namespace is evaluated/compiled.

If `false`:
  1. Telemere's   OpenTelemetry handler will NOT emit to `SpanExporter`s.
  2. Telemere and OpenTelemetry will NOT recognize each other's spans.

If `true`:
  1. Telemere's   OpenTelemetry handler WILL emit to `SpanExporter`s.
  2. Telemere and OpenTelemetry WILL recognize each other's spans.

Override default by setting one of the following to "true" or "false":
        JVM property: `taoensso.telemere.otel-tracing`
        Env variable: `TAOENSSO_TELEMERE_otel-tracing`
  Classpath resource: `taoensso.telemere.otel-tracing`

See also: `otel-default-providers_`, `*otel-tracer*`,
  `taoensso.telemere.open-telemere/handler:open-telemetry`.

[1] Ref. <https://github.com/open-telemetry/opentelemetry-java>
raw docstring

pr-signal-fnclj/s

(pr-signal-fn)
(pr-signal-fn {:keys [pr-fn clean-fn incl-newline?]
               :as opts
               :or {pr-fn :edn clean-fn (clean-signal-fn) incl-newline? true}})

Experimental, subject to change. Returns a (fn pr [signal]) that:

  • Takes a Telemere signal (map).
  • Returns a machine-readable signal string.

Options: :pr-fn - ∈ #{<unary-fn> :edn (default) :json (Cljs only)} :clean-fn - (fn [signal]) => clean signal map, see [1] :incl-newline? - Include terminating system newline? (default true)

Examples:

;; To print as edn: (pr-signal-fn {:pr-fn :edn})

;; To print as JSON: ;; Ref. https://github.com/metosin/jsonista (or any alt JSON lib) #?(:clj (require '[jsonista.core :as jsonista])) (pr-signal-fn {:pr-fn #?(:cljs :json ; Use js/JSON.stringify :clj jsonista/write-value-as-string)})

[1] taoensso.telemere.utils/clean-signal-fn, etc.

See also format-signal-fn for an alternative to pr-signal-fn that produces human-readable output.

Experimental, subject to change.
Returns a (fn pr [signal]) that:
  - Takes a Telemere signal (map).
  - Returns a machine-readable signal string.

Options:
  `:pr-fn`         - ∈ #{<unary-fn> :edn (default) :json (Cljs only)}
  `:clean-fn`      - (fn [signal]) => clean signal map, see [1]
  `:incl-newline?` - Include terminating system newline? (default true)

Examples:

  ;; To print as edn:
  (pr-signal-fn {:pr-fn :edn})

  ;; To print as JSON:
  ;; Ref.  <https://github.com/metosin/jsonista> (or any alt JSON lib)
  #?(:clj (require '[jsonista.core :as jsonista]))
  (pr-signal-fn
    {:pr-fn
      #?(:cljs :json ; Use js/JSON.stringify
         :clj  jsonista/write-value-as-string)})

[1] `taoensso.telemere.utils/clean-signal-fn`, etc.

See also `format-signal-fn` for an alternative to `pr-signal-fn`
that produces human-readable output.
raw docstring

rate-limiterclj/s

(rate-limiter spec)
(rate-limiter opts spec)

Takes a spec of form [ [<n-max-reqs> <msecs-window>] ...] or ; Unnamed limits {<limit-id> [<n-max-reqs> <msecs-window>]} ; Named limits and returns stateful (fn a-rate-limiter [] [req-id] [command req-id]).

Call the returned limiter fn with a request id (any Clojure value!) to enforce limits independently for each id.

For example, (limiter-fn <ip-address-string>) will return:

  • Falsey when allowed (all limits pass for given IP), or
  • Truthy when disallowed (any limits fail for given IP): [<worst-limit-id> <worst-backoff-msecs> {<limit-id> <backoff-msecs>}]

Or call the returned limiter fn with an extra command argument: (limiter-fn :rl/peek <req-id) - Check limits WITHOUT incrementing count (limiter-fn :rl/reset <req-id) - Reset all limits for given req-id

Takes a spec of form
  [           [<n-max-reqs> <msecs-window>] ...] or ; Unnamed limits
  {<limit-id> [<n-max-reqs> <msecs-window>]}        ;   Named limits
and returns stateful (fn a-rate-limiter [] [req-id] [command req-id]).

Call the returned limiter fn with a request id (any Clojure value!) to
enforce limits independently for each id.

For example, (limiter-fn <ip-address-string>) will return:
  - Falsey when    allowed (all limits pass for given IP), or
  - Truthy when disallowed (any limits fail for given IP):
    [<worst-limit-id> <worst-backoff-msecs> {<limit-id> <backoff-msecs>}]

Or call the returned limiter fn with an extra command argument:
  (limiter-fn :rl/peek  <req-id) - Check limits WITHOUT incrementing count
  (limiter-fn :rl/reset <req-id) - Reset all limits for given req-id
raw docstring

remove-handler!clj/s

(remove-handler! handler-id)

Stops and deregisters signal handler with given id, and returns ?{<handler-id> {:keys [dispatch-opts handler-fn]}} for all handlers still registered.

Stops and deregisters signal handler with given id, and returns
?{<handler-id> {:keys [dispatch-opts handler-fn]}} for all handlers
still registered.
raw docstring

set-ctx!clj/s

(set-ctx! root-ctx-val)

Set *ctx* var's default (root) value. See *ctx* for details.

Set `*ctx*` var's default (root) value. See `*ctx*` for details.
raw docstring

set-id-filter!clj/s

(set-id-filter! id-filter)

Sets signal id filter based on given id-filter spec. id-filter may be:

  • A regex pattern of id/s to allow

  • A str/kw/sym to allow, with "" and "(.)" as wildcards: "foo." will allow "foo.bar" "foo(.)" will allow "foo.bar" and "foo"

  • A set/vector of above (allow on any match)

  • A map, {:allow <spec> :disallow <spec>} with specs as above: If present, :allow spec MUST match, AND If present, :disallow spec MUST NOT match.

Sets signal id filter based on given `id-filter` spec.
`id-filter` may be:

  - A regex pattern of id/s to allow
  - A str/kw/sym to allow, with "*" and "(.*)" as wildcards:
    "foo.*"   will allow "foo.bar"
    "foo(.*)" will allow "foo.bar" and "foo"

  - A set/vector of above (allow on any match)
  - A map, {:allow <spec> :disallow <spec>} with specs as above:
    If present, `:allow`    spec MUST     match, AND
    If present, `:disallow` spec MUST NOT match.
raw docstring

set-kind-filter!clj/s

(set-kind-filter! kind-filter)

Sets signal kind filter based on given kind-filter spec. kind-filter may be:

  • A regex pattern of kind/s to allow

  • A str/kw/sym to allow, with "" and "(.)" as wildcards: "foo." will allow "foo.bar" "foo(.)" will allow "foo.bar" and "foo"

  • A set/vector of above (allow on any match)

  • A map, {:allow <spec> :disallow <spec>} with specs as above: If present, :allow spec MUST match, AND If present, :disallow spec MUST NOT match.

Sets signal kind filter based on given `kind-filter` spec.
`kind-filter` may be:

  - A regex pattern of kind/s to allow
  - A str/kw/sym to allow, with "*" and "(.*)" as wildcards:
    "foo.*"   will allow "foo.bar"
    "foo(.*)" will allow "foo.bar" and "foo"

  - A set/vector of above (allow on any match)
  - A map, {:allow <spec> :disallow <spec>} with specs as above:
    If present, `:allow`    spec MUST     match, AND
    If present, `:disallow` spec MUST NOT match.
raw docstring

set-middleware!clj/s

(set-middleware! ?root-middleware-fn)

Set *middleware* var's default (root) value. See *middleware* for details.

Set `*middleware*` var's default (root) value. See `*middleware*` for details.
raw docstring

set-min-level!clj/s

(set-min-level! min-level)
(set-min-level! kind min-level)
(set-min-level! kind ns-filter min-level)

Sets minimum signal 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 => all kinds) (set-min-level! nil ns :debug)

Sets minimum signal 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` => all kinds)
  (set-min-level! nil *ns* :debug)
raw docstring

set-ns-filter!clj/s

(set-ns-filter! ns-filter)

Sets signal namespace filter based on given ns-filter spec. ns-filter may be:

  • A namespace.

  • A regex pattern of namespaces/s to allow

  • A str/kw/sym to allow, with "" and "(.)" as wildcards: "foo." will allow "foo.bar" "foo(.)" will allow "foo.bar" and "foo"

  • A set/vector of above (allow on any match)

  • A map, {:allow <spec> :disallow <spec>} with specs as above: If present, :allow spec MUST match, AND If present, :disallow spec MUST NOT match.

Sets signal namespace filter based on given `ns-filter` spec.
`ns-filter` may be:

  - A namespace.
  - A regex pattern of namespaces/s to allow
  - A str/kw/sym to allow, with "*" and "(.*)" as wildcards:
    "foo.*"   will allow "foo.bar"
    "foo(.*)" will allow "foo.bar" and "foo"

  - A set/vector of above (allow on any match)
  - A map, {:allow <spec> :disallow <spec>} with specs as above:
    If present, `:allow`    spec MUST     match, AND
    If present, `:disallow` spec MUST NOT match.
raw docstring

set-var-root!clj/smacro

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

Sets root binding (value) of the var identified by given symbol, and returns
the new value. Cross-platform. See also `update-var-root!`.
raw docstring

signal!clj/smacro

(signal! {:as opts
          :keys [elidable? location inst uid middleware middleware+ sample-rate
                 kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
                 root 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-filters - (by ns/kind/id/level, sampling, etc.)

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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

signal-allowed?clj/smacro

(signal-allowed? {:as opts
                  :keys [elidable? location sample-rate kind ns id level when
                         rate-limit rate-limit-by]})

Returns true iff signal with given opts would meet filtering conditions: (when (signal-allowed? {:level :warn, <...>}) (my-custom-code))

Allows you to use Telemere's rich filtering system for conditionally executing arbitrary code. Also handy for batching multiple signals under a single set of conditions (incl. rate-limiting, sampling, etc.):

;; Logs exactly 2 or 0 messages (never 1): (when (signal-allowed? {:level :info, :sample-rate 0.5}) (log! {:allow? true} "Message 1") (log! {:allow? true} "Message 2"))

Returns true iff signal with given opts would meet filtering conditions:
 (when (signal-allowed? {:level :warn, <...>}) (my-custom-code))

Allows you to use Telemere's rich filtering system for conditionally
executing arbitrary code. Also handy for batching multiple signals
under a single set of conditions (incl. rate-limiting, sampling, etc.):

  ;; Logs exactly 2 or 0 messages (never 1):
  (when (signal-allowed? {:level :info, :sample-rate 0.5})
    (log! {:allow? true} "Message 1")
    (log! {:allow? true} "Message 2"))
raw docstring

spy!clj/smacro

(spy! form)
(spy! level form)
(spy! {:as opts
       :keys [elidable? location inst uid middleware middleware+ sample-rate
              kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
              root 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.).

Enables tracing of given form arg:

  • Resulting signal will include {:keys [run-form run-val run-nsecs]}.
  • Nested signals will include this signal's id and uid under :parent.

Limitations:

  1. Traced code (form arg) is usually expected to be synchronous and eager. So no lazy seqs, async calls, or inversion of flow control (IoC) macros like core.async go blocks, etc.

  2. Tracing call (spy!) is usually expected to occur within normally flowing code. IoC macros can arbitrarily (and often opaquely) alter program flow and tracing across flow boundaries can be fragile or even fundamentally illogical.

    So use within IoC macro bodies might not make conceptual sense, or could produce errors or unreliable/confusing results.

    Basically- if possible, prefer tracing normal Clojure fns running within normal Clojure fns unless you deeply understand what your IoC macros are up to.

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

  • Runtime of async or lazy code in form will intentionally NOT be included in resulting signal's :run-nsecs value. If you want to measure such runtimes, make sure that your form wraps where the relevant costs are actually realized. Compare: (spy! (delay (my-slow-code))) ; Doesn't measure slow code (spy! @(delay (my-slow-code))) ; Does measure slow code

  • See also Tufte (https://www.taoensso.com/tufte) for a complementary/partner Clj/s library that offers more advanced performance measurment and shares the same signal engine (filtering and handler API) as Telemere.


[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-filters - (by ns/kind/id/level, sampling, etc.)

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

Enables tracing of given `form` arg:

  - Resulting signal  will include {:keys [run-form run-val run-nsecs]}.
  - Nested    signals will include this signal's id and uid under `:parent`.

Limitations:

  1. Traced code (`form` arg) is usually expected to be synchronous and eager.
     So no lazy seqs, async calls, or inversion of flow control (IoC) macros like
     core.async `go` blocks, etc.

  2. Tracing call (`spy!`) is usually expected to occur *within* normally flowing code.
     IoC macros can arbitrarily (and often opaquely) alter program flow and tracing
     across flow boundaries can be fragile or even fundamentally illogical.

     So use within IoC macro bodies might not make conceptual sense, or could produce
     errors or unreliable/confusing results.

     Basically- if possible, prefer tracing normal Clojure fns running within normal
     Clojure fns unless you deeply understand what your IoC macros are up to.

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

  - Runtime of async or lazy code in `form` will intentionally NOT be included
    in resulting signal's `:run-nsecs` value. If you want to measure such
    runtimes, make sure that your form wraps where the relevant costs are
    actually realized. Compare:
      (spy!  (delay (my-slow-code))) ; Doesn't measure slow code
      (spy! @(delay (my-slow-code))) ; Does    measure slow code

  - See also Tufte (https://www.taoensso.com/tufte) for a complementary/partner
    Clj/s library that offers more advanced performance measurment and shares
    the same signal engine (filtering and handler API) as Telemere.

----------------------------------------------------------------------
[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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

stop-handlers!clj/s

(stop-handlers!)

Stops registered signal handlers in parallel by calling each handler-fn with no arguments. This gives each handler the opportunity to flush buffers, close files, etc.

Each handler will immediately stop accepting new signals, nooping if called.

Blocks to return ?{<handler-id> {:keys [okay error]}}, honouring each handler's :drain-msecs value (see help:handler-dispatch-options).

NB you should always call stop-handlers! somewhere appropriate - usually near the end of your -main or shutdown procedure, AFTER all other code has completed that could create signals.

Stops registered signal handlers in parallel by calling each
handler-fn with no arguments. This gives each handler the opportunity
to flush buffers, close files, etc.

Each handler will immediately stop accepting new signals, nooping if called.

Blocks to return ?{<handler-id> {:keys [okay error]}}, honouring each
handler's `:drain-msecs` value (see `help:handler-dispatch-options`).

NB you should always call `stop-handlers!` somewhere appropriate - usually
near the end of your `-main` or shutdown procedure, AFTER all other code has
completed that could create signals.
raw docstring

streams->reset!clj

(streams->reset!)

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

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

streams->telemere!clj

(streams->telemere!)
(streams->telemere! {:keys [out err]
                     :or {out default-out-opts err default-err-opts}})

Experimental, subject to change.

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.

Experimental, subject to change.

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`.
raw docstring

trace!clj/smacro

(trace! form)
(trace! id form)
(trace! {:as opts
         :keys [elidable? location inst uid middleware middleware+ sample-rate
                kind ns id level when rate-limit rate-limit-by ctx ctx+ parent
                root 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.).

Enables tracing of given form arg:

  • Resulting signal will include {:keys [run-form run-val run-nsecs]}.
  • Nested signals will include this signal's id and uid under :parent.

Limitations:

  1. Traced code (form arg) is usually expected to be synchronous and eager. So no lazy seqs, async calls, or inversion of flow control (IoC) macros like core.async go blocks, etc.

  2. Tracing call (trace!) is usually expected to occur within normally flowing code. IoC macros can arbitrarily (and often opaquely) alter program flow and tracing across flow boundaries can be fragile or even fundamentally illogical.

    So use within IoC macro bodies might not make conceptual sense, or could produce errors or unreliable/confusing results.

    Basically- if possible, prefer tracing normal Clojure fns running within normal Clojure fns unless you deeply understand what your IoC macros are up to.

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.

  • Runtime of async or lazy code in form will intentionally NOT be included in resulting signal's :run-nsecs value. If you want to measure such runtimes, make sure that your form wraps where the relevant costs are actually realized. Compare: (trace! (delay (my-slow-code))) ; Doesn't measure slow code (trace! @(delay (my-slow-code))) ; Does measure slow code

  • See also Tufte (https://www.taoensso.com/tufte) for a complementary/partner Clj/s library that offers more advanced performance measurment and shares the same signal engine (filtering and handler API) as Telemere.


[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-filters - (by ns/kind/id/level, sampling, etc.)

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

Enables tracing of given `form` arg:

  - Resulting signal  will include {:keys [run-form run-val run-nsecs]}.
  - Nested    signals will include this signal's id and uid under `:parent`.

Limitations:

  1. Traced code (`form` arg) is usually expected to be synchronous and eager.
     So no lazy seqs, async calls, or inversion of flow control (IoC) macros like
     core.async `go` blocks, etc.

  2. Tracing call (`trace!`) is usually expected to occur *within* normally flowing code.
     IoC macros can arbitrarily (and often opaquely) alter program flow and tracing
     across flow boundaries can be fragile or even fundamentally illogical.

     So use within IoC macro bodies might not make conceptual sense, or could produce
     errors or unreliable/confusing results.

     Basically- if possible, prefer tracing normal Clojure fns running within normal
     Clojure fns unless you deeply understand what your IoC macros are up to.

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.

  - Runtime of async or lazy code in `form` will intentionally NOT be included
    in resulting signal's `:run-nsecs` value. If you want to measure such
    runtimes, make sure that your form wraps where the relevant costs are
    actually realized. Compare:
      (trace!  (delay (my-slow-code))) ; Doesn't measure slow code
      (trace! @(delay (my-slow-code))) ; Does    measure slow code

  - See also Tufte (https://www.taoensso.com/tufte) for a complementary/partner
    Clj/s library that offers more advanced performance measurment and shares
    the same signal engine (filtering and handler API) as Telemere.

----------------------------------------------------------------------
[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-filters`  - (by ns/kind/id/level, sampling, etc.)
raw docstring

uncaught->error!clj/smacro

(uncaught->error!)
(uncaught->error! id)
(uncaught->error! {:as opts
                   :keys [elidable? location inst uid middleware middleware+
                          sample-rate kind ns id level when rate-limit
                          rate-limit-by ctx ctx+ parent root 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.

Uses `uncaught->handler!` so that `error!` will be called for
uncaught JVM errors.

See `uncaught->handler!` and `error!` for details.
raw docstring

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

Sets JVM's global `DefaultUncaughtExceptionHandler` to given
  (fn handler [`<java.lang.Thread>` `<java.lang.Throwable>`]).

See also `uncaught->error!`.
raw docstring

update-var-root!clj/smacro

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

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

with-ctxclj/smacro

(with-ctx ctx-val form)

Evaluates given form with given *ctx* value. See *ctx* for details.

Evaluates given form with given `*ctx*` value. See `*ctx*` for details.
raw docstring

with-ctx+clj/smacro

(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.

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.
raw docstring

with-err->telemereclj/smacro

(with-err->telemere form)
(with-err->telemere opts form)

Executes form with *err* bound to flush to Telemere signals with given opts.

Executes form with `*err*` bound to flush to Telemere signals with given opts.
raw docstring

with-handlerclj/smacro

(with-handler handler-id handler-fn form)
(with-handler handler-id handler-fn dispatch-opts form)

Executes form with ONLY the given signal handler registered. Stops handler after use. Useful for tests/debugging.

See help:handler-dispatch-options for handler filters, etc. See also with-handler+.

Executes form with ONLY the given signal handler registered.
Stops handler after use. Useful for tests/debugging.

See `help:handler-dispatch-options` for handler filters, etc.
See also `with-handler+`.
raw docstring

with-handler+clj/smacro

(with-handler+ handler-id handler-fn form)
(with-handler+ handler-id handler-fn dispatch-opts form)

Executes form with the given signal handler (also) registered. Stops handler after use. Useful for tests/debugging.

See help:handler-dispatch-options for handler filters, etc. See also with-handler.

Executes form with the given signal handler (also) registered.
Stops handler after use. Useful for tests/debugging.

See `help:handler-dispatch-options` for handler filters, etc.
See also `with-handler`.
raw docstring

with-id-filterclj/smacro

(with-id-filter id-filter form)

Executes form with given signal id filter in effect. See set-id-filter! for details.

Executes form with given signal id filter in effect.
See `set-id-filter!` for details.
raw docstring

with-kind-filterclj/smacro

(with-kind-filter kind-filter form)

Executes form with given signal kind filter in effect. See set-kind-filter! for details.

Executes form with given signal kind filter in effect.
See `set-kind-filter!` for details.
raw docstring

with-middlewareclj/smacro

(with-middleware ?middleware-fn form)

Evaluates given form with given *middleware* value. See *middleware* for details.

Evaluates given form with given `*middleware*` value.
See `*middleware*` for details.
raw docstring

with-middleware+clj/smacro

(with-middleware+ ?middleware-fn form)

Evaluates given form with composed *middleware* value. Same as (with-middleware (comp-middleware middleware ?middleware-fn) ...). See *middleware* for details.

Evaluates given form with composed `*middleware*` value.
Same as (with-middleware (comp-middleware *middleware* ?middleware-fn) ...).
See `*middleware*` for details.
raw docstring

with-min-levelclj/smacro

(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 level in effect. See set-min-level! for details.

Executes form with given minimum signal level in effect.
See `set-min-level!` for details.
raw docstring

with-ns-filterclj/smacro

(with-ns-filter ns-filter form)

Executes form with given signal namespace filter in effect. See set-ns-filter! for details.

Executes form with given signal namespace filter in effect.
See `set-ns-filter!` for details.
raw docstring

with-out->telemereclj/smacro

(with-out->telemere form)
(with-out->telemere opts form)

Executes form with *out* bound to flush to Telemere signals with given opts.

Executes form with `*out*` bound to flush to Telemere signals with given opts.
raw docstring

with-signalclj/smacro

(with-signal form)
(with-signal trap-signals? form)
(with-signal raw-msg? trap-signals? form)

Experimental, subject to change. 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.

Experimental, subject to change.
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`.
raw docstring

with-signalsclj/smacro

(with-signals form)
(with-signals trap-signals? form)
(with-signals raw-msgs? trap-signals? form)

Experimental, subject to change. Like with-signal but returns [[<form-value> <form-error>] [<signal1> ...]]. Useful for tests/debugging.

Experimental, subject to change.
Like `with-signal` but returns [[<form-value> <form-error>] [<signal1> ...]].
Useful for tests/debugging.
raw docstring

with-streams->telemereclj/smacro

(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.

Executes form with `*out*` and/or `*err*` bound to flush to Telemere signals
with given opts.
raw docstring

without-filtersclj/smacro

(without-filters form)

Executes form without any runtime signal filters.

Executes form without any runtime signal filters.
raw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close