Liking cljdoc? Tell your friends :D

taoensso.tufte

A simple, fast, monitoring profiler for Clojure/Script.

Usage: wrap+name interesting body exprs with the `p` macro. Then activate
profiling of these wrapped exprs using the `profiled` or `profile` macros:

  (profiled {} (p :my-fn (my-fn))) ; Returns [<body-result> <?pstats>]
  (profile  {} (p :my-fn (my-fn))) ; Returns  <body-result> and dispatches a
                                   ; profiling signal (map) to all registered handlers.

Provides extensive facilities for compile-time elision and runtime filtering.

See the relevant docstrings for more info:
  `p`, `profiled`, `profile`, `add-handler!`, etc.

  (p        [opts & body] [id & body]) ; e.g. `(p ::my-id (do-work))`
  (profiled [opts & body])             ; e.g. `(profiled {:level :info} (my-fn))`
  (profile  [opts & body])             ; e.g. `(profiled {:level :info} (my-fn))`

  (add-handler! [handler-id handler-fn dispatch-opts])

How/where to use this library:
  Tufte profiling is highly optimized: even without elision, you can usually
  leave profiling active in production (e.g. for sampled profiling, or to
  detect unusual performance behaviour). Tufte's `pstats` data is well suited
  to programmatic monitoring.

*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.
source

*xfn*clj/s

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

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

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

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

Examples:

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

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

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

  ;; Dynamic transform for specific signal/s:
  (binding [*xfn* (fn [signal] ...)]
    (...))

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

add-handler!clj/s

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

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

capture-time!clj/smacro

(capture-time! id nano-secs-elapsed)
(capture-time! pdata id nano-secs-elapsed)
Low-level primitive for advanced users.
Useful when tracking time across thread boundaries and/or for
async jobs / callbacks / etc.

See `new-pdata` for more info on low-level primitives.
See also `capture-time!*`.
source

capture-time!*clj/s

(capture-time!* id nano-secs-elapsed)
(capture-time!* pdata id nano-secs-elapsed)
Like `capture-time!` but a function and does not collect callsite location info.
source

chanceclj/s

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

comp-xfnclj/s

(comp-xfn fs)
(comp-xfn f1 f2)
(comp-xfn f1 f2 f3)
(comp-xfn f1 f2 f3 & fs)
Returns a composite unary signal transform fn (xfn).
Like `core/comp` but takes only unary fns, applies functions left->right(!),
and composite immediately returns nil if any given fn returns nil.
source

default-handler-dispatch-optsclj/s

See `help:handler-dispatch-opts` for details.
source

defnpclj/smacro

(defnp name doc-string? attr-map? [params*] prepost-map? body)
(defnp name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)
Like `defn` but wraps fn bodies with `p` macro.
source

defnp-clj/smacro

(defnp- name doc-string? attr-map? [params*] prepost-map? body)
(defnp- name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?)
Like `defn-` but wraps fn bodies with `p` macro.
source

fnpclj/smacro

(fnp name? ([params*] prepost-map? body) +)
(fnp name? [params*] prepost-map? body)
Like `fn` but wraps fn bodies with `p` macro.
source

format-grouped-pstatsclj/s

(format-grouped-pstats m)
(format-grouped-pstats m
                       {:keys [group-sort-fn format-pstats-opts]
                        :or {group-sort-fn (fn [m]
                                               (get-in m [:clock :total] 0))}})
Alpha, subject to change.
Takes a map of {<profiling-id> <pstats>} and formats a combined
output string using `format-pstats`.

See also example Clj project.
source

format-id-abbr-fnclj/s

(format-id-abbr-fn)
(format-id-abbr-fn n-full)
Returns a cached (fn [id]) => abbreviated id with at most `n-full`
unabbreviated namespace parts.

Example:
  ((format-id-abbr 0)  :foo.bar/baz)   => :f.b/baz
  ((format-id-abbr 1)  'foo.bar/baz)   => 'f.bar/baz
  ((format-id-abbr 2) "foo.bar/baz") => "foo.bar/baz"
source

format-pstatsclj/s

(format-pstats ps)
(format-pstats ps
               {:keys [incl-newline? columns sort-fn format-id-fn max-id-width]
                :as opts
                :or {incl-newline? true
                     columns default-format-columns
                     sort-fn (fn [ss] (get (enc/force-ref ss) :sum))
                     format-id-fn (fn [id] (str id))}})
Formats given `pstats` to a string table.
  Accounted < Clock => Some work was done that wasn't tracked by any `p` forms.
  Accounted > Clock => Nested `p` forms, and/or parallel threads.

Options include:
  `:incl-newline?` - Include terminating system newline? (default true)
  `:columns` ------- Default [:n :min #_:p25 :p50 #_:p75 :p90 :p95 :p99 :max :mean :mad :clock :sum]
source

format-signal-fnclj/s

(format-signal-fn)
(format-signal-fn
  {:keys [incl-newline? format-inst-fn format-pstats-opts incl-keys]
   :or {incl-newline? true format-inst-fn (enc/format-inst-fn)}})
Alpha, subject to change.
Returns a (fn format [signal]) that:
  - Takes a Tufte profiling signal (map).
  - Returns a human-readable signal string.

Options:
  `:incl-newline?` ------ Include terminating system newline? (default true)
  `:format-inst-fn` ----- (fn format [instant]) => string (default ISO8601)
  `:format-pstats-opts` - Opts map provided to `format-pstats` (default nil)
  `:incl-keys` ---------- Subset of profiling signal keys to retain from those
                          otherwise excluded by default: #{:host :thread}
source

get-envclj/smacro

(get-env {:keys [as default return] :or {as :str return :value}} spec)
Flexible cross-platform environmental value util.

Given a compile-time id (keyword/string) or vector of desc-priority
ids, parse and return the first of the following that exists, or nil:
  1. JVM         property value   for id
  2. Environment variable value   for id
  3. Classpath   resource content for id

Ids may include optional platform tag for auto replacement, e.g.:
  `<.platform>` -> ".clj", ".cljs", or nil

Clj/s: if resulting value is a single symbol, it will be evaluated.
Cljs:     resulting value will be embedded in code during macro expansion!

Options:
  `:as`      - Parse encountered 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`).
               Use `:explain` to verify/debug, handy for tests/REPL!

Example:
  (get-env {:as :edn} [:my-app/id1<.platform> :my-app/id2]) will parse
  and return the first of the following that exists, or nil:

    id1 with platform:
      `my-app.id1.clj` JVM         property value
      `MY_APP_id1_CLJ` environment variable value
      `my-app.id1.clj` classpath   resource content

    id1 without platform:
      `my-app.id1`     JVM         property value
      `MY_APP_id1`     environment variable value
      `my-app.id1`     classpath   resource content

    id2 with    platform: ...
    id2 without platform: ...
source

get-filtersclj/s

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

get-handlersclj/s

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

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 transform (xfn) 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).
source

get-min-levelsclj/s

(get-min-levels)
(get-min-levels ns)
Returns current ?{:keys [compile-time runtime]} minimum call levels
for given/current namespace.
source

handler:accumulatingclj/s

(handler:accumulating sacc)
Alpha, subject to change.
Returns a signal handler that:
   - Takes a Tufte profiling signal (map).
   - Merges the signal's `pstats` into the given accumulator.

See `stats-accumulator` for more info.
source

handler:consoleclj/s≠

clj
(handler:console)
(handler:console {:keys [stream output-fn]
                  :or {stream :out output-fn (format-signal-fn)}})
Alpha, subject to change.
Returns a signal handler that:
  - Takes a Tufte profiling 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`.
  `:stream` ---- `java.io.writer` (default `*out*`).
cljs
(handler:console)
(handler:console {:keys [output-fn] :or {output-fn (format-signal-fn)}})
Alpha, subject to change.
If `js/console` exists, returns a signal handler that:
  - Takes a Tufte profiling 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`.
source (clj)source (cljs)

help:environmental-configclj/s

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

Environmental filter config includes:

  1. Minimum level (see signal `:level`):
    a.       JVM property: `taoensso.tufte.rt-min-level`
    b.       Env variable: `TAOENSSO_TUFTE_RT_MIN_LEVEL`
    c. Classpath resource: `taoensso.tufte.rt-min-level`

  2. Namespace filter (see signal `:ns`):
    a.       JVM property: `taoensso.tufte.rt-ns-filter`
    b.       Env variable: `TAOENSSO_TUFTE_RT_NS_FILTER`
    c. Classpath resource: `taoensso.tufte.rt-ns-filter`

  3. Id filter (see signal `:id`):
    a.       JVM property: `taoensso.tufte.rt-id-filter`
    b.       Env variable: `TAOENSSO_TUFTE_RT_ID_FILTER`
    c. Classpath resource: `taoensso.tufte.rt-id-filter`

Config values are parsed as edn, examples:

  `taoensso.tufte.rt-min-level`      => ":info"
  `TAOENSSO_TUFTE_RT_NS_FILTER`      => "{:disallow \"taoensso.*\"}"
  `taoensso.tufte.rt-id-filter.cljs` => "#{:my-id1 :my-id2}"
  `TAOENSSO_TUFTE_RT_ID_FILTER_CLJ`  => "nil"

Runtime vs compile-time filters

  The above filters (1..4) all apply at RUNTIME ("rt").
  This is typically what you want, since it allows you to freely adjust filtering
  (making it less OR MORE permissive) through later API calls like `set-min-level!`.

  As an advanced option, you can instead/additionally ELIDE (entirely omit) filtered
  callsites at COMPILE-TIME ("ct") by replacing "rt"->"ct" / "RT"->"CT" in the config
  ids above. Compile-time filters CANNOT be made MORE permissive at runtime.

Tips:

  - The above config ids will affect both Clj AND Cljs.
    For platform-specific filters, use
      ".clj"  / "_CLJ"  or
      ".cljs" / "_CLJS" suffixes instead.
      e.g. "taoensso.tufte.rt-min-level.cljs".

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

help:filtersclj/s

Tufte profiling is activated using the `profiled` or  `profile` macros:

  - `profiled` returns [<body-result> <?pstats>].
    Handy when you want to consume profiling results directly at the callsite.

  - `profile`  returns <body-result> and dispatches a profiling signal (map)
    to all registered handlers. This map includes `:pstats` and other info.

    Handy when you want to consume profiling results later/elsewhere.

Profiling is activated only when ALL of the following are true:

    1. Call filters pass (relevant for both `profile/d`):
      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. Handler filters pass (relevant only for `profile`):
      a. Compile-time: not applicable
      b. Runtime:      sample rate, kind, ns, id, level, when fn, rate limit

    (Relevant only for `profile`):
    3. Call    transform (fn [signal]) => ?modified-signal returns non-nil
    4. Handler transform (fn [signal]) => ?modified-signal returns non-nil

  Transform fns provides a flexible way to modify and/or filter signals by
  arbitrary signal data/content conditions (return nil to skip handling).

  Config:

    To set call 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 transform (4):

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

      Note: call filters (1a, 1b) should generally be AT LEAST as permissive
      as handler filters (2b) since they're always applied first.

    To set call transform (3): use `set-xfn!`, `with-xfn`.

  Compile-time vs runtime filtering:

    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 calls. This means zero performance cost for these calls, 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 call 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 calls 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%).

    When sampling is active, the final (combined multiplicative) rate is
    helpfully reflected in each signal's `:sample` rate value ∈ℝ[0,1].

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

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) - may be `nil` (=> synchronous) or map with options:

    `: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 handling order guaranteed to be be sequential iff 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` (default nil => no sampling)
    Optional sample rate ∈ℝ[0,1], or (fn dyamic-sample-rate []) => ℝ[0,1].
    When present, handle only this (random) proportion of signals:
      1.0 => handle 100% of signals (same as nil rate, default)
      0.0 => hanel    0% of signals (noop all)
      0.5 => handle  50% of signals (random)

  `: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 `:xfn` for an alternative that takes a signal argument!

  `: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

  `:xfn` (default nil => no transform)
    Optional transform (fn [signal]) => ?modified-signal to apply before
    handling signal. When transform returns nil, skips handler.

    Compose multiple transform fns together with `comp-some`.

  `: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!
source

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

help:pstats-contentclj/s

Profiling stats (`pstats`)

When profiling (activated by `profile/d`) is complete, you'll get back a
profiling stats (`pstats`) object that can be derefed and/or merged
with other `pstats`:

  - @pstats                 => {:clock {:keys [t0 t1 total]}, :stats {<id> {:keys [n sum ...]}}}
  - @(merge-pstats ps1 ps2) => {:clock {:keys [t0 t1 total]}, :stats {<id> {:keys [n sum ...]}}}

Full set of keys in the above `:stats` maps:
  :n :min :max :mean :mad :sum :p25 :p50 :p75 :p90 :p95 :p99 :loc :last

  All values are numerical (longs or doubles), except for `:loc` which is
  a map of `p` callsite location information, or set of such maps, e.g.:
  #{{:ns \"my-ns\", :line 122, :column 21}}
source

help:signal-contentclj/s

Tufte profiling signals are maps with {:keys [inst id ns level data ...]},
though they can be modified by call and/or handler transforms (xfns).

Default signal keys:

`:schema` ----------- Int version of signal schema (current: 1)
`:inst` ------------- Platform instant [1] when `profile` called, monotonicity depends on system clock
`:ns` --------------- ?str namespace of `profile` callsite
`:coords` ----------- ?[line column] of `profile` callsite

`:level` ------------ Profiling level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
`:id` --------------- Profiling ?id (usu. keyword)

`:data` ------------- Arb app-level data ?val (usu. a map) given to `profile` call
`:ctx` -------------- ?val of `*ctx*` (arb app-level state) when `profile` was called

`:body-result` ------ Return value of the body wrapped by `profile` call
`:pstats` ----------- Profiling stats object that can be derefed and/or merged (see `help:pstats-content`)
`:format-pstats-fn` - Cached (fn [pstats]) => formatted table string function

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

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

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

[1] `java.time.Instant` or `js/Date`
source

keep-callsiteclj/smacro

(keep-callsite inner-form)
CLJ-865 means that it's not possible for an inner macro to access `&form`
metadata (incl. {:keys [line column]}) of a wrapping outer macro:

  (defmacro inner [] (meta &form))
  (defmacro outer [] `(inner))
  (outer) => nil

This util offers a workaround for authors of the outer macro, preserving
the outer `&form` metadata for the inner macro:

  (defmacro inner [] (meta &form))
  (defmacro outer [] (keep-callsite `(inner)))
  (outer) => {:keys [line column ...]}
source

level-aliasesclj/s≠

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

merge-pstatsclj/s

(merge-pstats)
(merge-pstats ps0)
(merge-pstats ps0 ps1)
(merge-pstats nmax ps0 ps1)
Merges given `pstats`, compacting as necessary.
Merged statistics are lossless unless data to merge are very large.
source

new-pdataclj/s

(new-pdata)
(new-pdata {:keys [dynamic? nmax] :or {dynamic? true nmax default-nmax}})
(new-pdata dynamic? nmax)
Low-level primitive for advanced users.
Returns a new pdata object for use with `with-profiling` and/or `capture-time!`.
Deref to get pstats:

  (let [pd (new-pdata)
        t0 (System/nanoTime)]
    (with-profiling pd {}
      (p :foo (Thread/sleep 100))
      (capture-time! pd :bar (- t0 (System/nanoTime))))
    (deref pd))

Dynamic (thread-safe) by default.
*WARNING*: don't change this default unless you're very sure the resulting
pdata object will not be concurrently modified across threads. Concurrent
modification will lead to bad data and/or exceptions!
source

newlineclj/s

Single system newline
source

pclj/smacro

(p id & body)
(p {:keys [id level]} & body)
Profiling spy.

Use this macro to wrap forms that should be timed during active profiling.
A unique form id (keyword) must be provided, e.g.:

  (p      ::my-form  (do-something))
  (p {:id ::my-form} (do-something))
  (p {:id ::my-form
      :level :debug} (do-something))

`p` will ALWAYS execute its body and return the body's result, even when
profiling isn't active.

Options include:
  `:id` ---- Unique id for this form in resulting `pstats` (e.g. `::my-fn-call`)
  `:level` - Profiling level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
             (default `:info`)
source

profileclj/smacro

(profile {:keys [dynamic? nmax elidable? sample ns id level when limit limit-by
                 ctx ctx+ data xfn xfn+]}
         &
         body)
Use this to conditionally activate profiling for given body:

- ALWAYS executes body and returns <body-result>.
- When filtering conditions are met (see `help:filters`), records execution times
  of all `p` forms in body and dispatches a profiling signal map (see `help:signal-content`)
  to any registered handlers (see `help:handlers`).

Handy when you want to consume profiling results asynchronously and/or away from
the callsite, otherwise prefer `profile`.

Options include:

  `:dynamic?` --- Perform multi-threaded profiling with binding conveyance? (default false)
  `:level` ------ Profiling level (default `:info`), must be >= active minimum level to profile
  `:id` --------- Profiling ?id for filtering, etc. (e.g. `::my-profiling-id`)

  `:data` ------- Arb app-level ?data to incl. in signal: usu. a map
  `: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+`
  `:xfn` -------- Optional       transform (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-xfn`
  `:xfn+` ------- Optional extra transform (fn [signal]) => ?modified-signal to apply when signal is created, as per `with-xfn+`

  `:sample` ----- Sample rate ∈ℝ[0,1], profile only this random proportion of calls (0.75 => 75%, nil => all)
  `:when` ------- Arb ?form; when present, form must return truthy to allow profiling
  `:limit` ------ Rate limit ?spec given to `taoensso.tufte/rate-limiter`, see its docstring for details
  `:limit-by` --- When present, rate limits will be enforced independently for each value (any Clojure value!)

  `:nmax` ------- Max captures per `p` id before compaction (default 8e5).
  `:elidable?` -- Should signal be subject to compile-time elision? (default true)

Laziness in body:

  Lazy seqs and other forms of laziness (e.g. delays) in body will only
  contribute to profiling results if/when EVALUATION ACTUALLY OCCURS.
  This is intentional and a useful property. Compare:

    (profile {}  (delay (Thread/sleep 2000))) ; Doesn't count sleep
    (profile {} @(delay (Thread/sleep 2000))) ; Does    count sleep

Async code in body:

  Execution time of any code in body that runs asynchronously on a
  different thread will generally NOT be automatically captured by default.

  `:dynamic?` can be used to support capture in cases where Clojure's
  binding conveyance applies (e.g. futures, agents, pmap). Just make sure
  that all work you want to capture has COMPLETED before the `profile`
  form ends- for example, by blocking on pending futures.

  In other advanced cases (notably core.async `go` blocks), please see
  `with-profiling` and `capture-time!`.

`core.async` warning:

   `core.async` code can be difficult to profile correctly without a deep
   understanding of precisely what it's doing under-the-covers.

   Some general recommendations that can help keep things simple:

     - Try minimize the amount of code + logic in `go` blocks. Use `go`
       blocks for un/parking to get the data you need, then pass the data
       to external fns. Profile these fns (or in these fns), not in your
       `go` blocks.

     - In particular: you MUST NEVER have parking calls inside
       `(profile {:dynamic? false} ...)`.

       This can lead to concurrency exceptions.

       If you must profile code within a go block, and you really want to
       include un/parking times, use `(profile {:dynamic? true} ...)`
       instead.
source

profiledclj/smacro

(profiled {:keys [dynamic? nmax elidable? sample ns id level when limit
                  limit-by]}
          &
          body)
Use this to conditionally activate profiling for given body:

- ALWAYS executes body and returns [<body-result> <?pstats>].
- When filtering conditions are met (see `help:filters`), records execution times
  of all `p` forms in body and includes resulting `pstats` object in return value.

Handy when you want to consume profiling results directly at the callsite,
otherwise prefer `profile`.

Options include:

  `:dynamic?` --- Perform multi-threaded profiling with binding conveyance? (default false)
  `:level` ------ Profiling level (default `:info`), must be >= active minimum level to profile
  `:id` --------- Profiling ?id for filtering, etc. (e.g. `::my-profiling-id`)

  `:sample` ----- Sample rate ∈ℝ[0,1], profile only this random proportion of calls (0.75 => 75%, nil => all)
  `:when` ------- Arb ?form; when present, form must return truthy to allow profiling
  `:limit` ------ Rate limit ?spec given to `taoensso.tufte/rate-limiter`, see its docstring for details
  `:limit-by` --- When present, rate limits will be enforced independently for each value (any Clojure value!)

  `:nmax` ------- Max captures per `p` id before compaction (default 8e5).
  `:elidable?` -- Should profiling be subject to compile-time elision? (default true)

Laziness in body:

  Lazy seqs and other forms of laziness (e.g. delays) in body will only
  contribute to profiling results if/when EVALUATION ACTUALLY OCCURS.
  This is intentional and a useful property. Compare:

    (profiled {}  (delay (Thread/sleep 2000))) ; Doesn't count sleep
    (profiled {} @(delay (Thread/sleep 2000))) ; Does    count sleep

Async code in body:

  Execution time of any code in body that runs asynchronously on a
  different thread will generally NOT be automatically captured by default.

  `:dynamic?` can be used to support capture in cases where Clojure's
  binding conveyance applies (e.g. futures, agents, pmap). Just make sure
  that all work you want to capture has COMPLETED before the `profiled`
  form ends- for example, by blocking on pending futures.

  In other advanced cases (notably core.async `go` blocks), please see
  `with-profiling` and `capture-time!`.

`core.async` warning:

   `core.async` code can be difficult to profile correctly without a deep
   understanding of precisely what it's doing under-the-covers.

   Some general recommendations that can help keep things simple:

     - Try minimize the amount of code + logic in `go` blocks. Use `go`
       blocks for un/parking to get the data you need, then pass the data
       to external fns. Profile these fns (or in these fns), not in your
       `go` blocks.

     - In particular: you MUST NEVER have parking calls inside
       `(profiled {:dynamic? false} ...)`.

       This can lead to concurrency exceptions.

       If you must profile code within a go block, and you really want to
       include un/parking times, use `(profiled {:dynamic? true} ...)`
       instead.
source

profiling?clj/s

(profiling?)
Returns e/o #{nil :thread :dynamic}.
source

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
source

refer-tufteclj/smacro

(refer-tufte)
(require '[taoensso.tufte :as tufte :refer [defnp p profiled profile]])
source

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

set-ctx!clj/s

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

set-id-filter!clj/s

(set-id-filter! id-filter)
Sets call id filter based on given `id-filter` spec.
`id-filter` may be:

  - A regex pattern of id/s to allow
  - A str/kw/sym 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.
source

set-kind-filter!clj/s

source

set-ns-filter!clj/s

(set-ns-filter! ns-filter)
Sets call 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.
source

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

set-xfn!clj/s

(set-xfn! ?root-xfn)
Set `*xfn*` var's default (root) value. See `*xfn*` for details.
source

stats-accumulatorclj/s

(stats-accumulator)
Experimental, subject to change. Feedback welcome!
Small util to help merge `pstats` from multiple runs and/or threads.

Returns a stateful `StatsAccumulator` (`sacc`) with:
  - (sacc <profiling-id> <pstats>) ; Merges given pstats under given profile id
  - @sacc                          ; Drains accumulator and returns drained
                                   ; {<profiling-id> <merged-pstats>}

Note that for performance reasons, you'll likely want some kind of
async/buffer/serialization mechanism in front of merge calls.

One common pattern using `handler:accumulating` is to create a
system-wide accumulator that you deref every n minutes/etc. to get
a view of system-wide performance over the period, e.g.:

  (defonce my-sacc (stats-accumulator) ; Create an accumulator
  (add-handler! :my-sacc (handler:accumulating my-sacc)) ; Register handler

  (defonce my-sacc-drainer
    ;; Drain and print formatted stats every minute
    (future
      (while true
        (when-let [m (not-empty @my-sacc)]
          (println (format-grouped-pstats m)))
        (Thread/sleep 60000))))

  (profile ...) ; Used elsewhere in your application, e.g.
                ; wrapping relevant Ring routes in a web application.

See example clj project for more details.
source

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

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

with-ctxclj/smacro

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

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

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+`.
source

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

with-id-filterclj/smacro

(with-id-filter id-filter form)
Executes form with given call id filter in effect.
See `set-id-filter!` for details.
source

with-kind-filterclj

source

with-ns-filterclj/smacro

(with-ns-filter ns-filter form)
Executes form with given call namespace filter in effect.
See `set-ns-filter!` for details.
source

with-profilingclj/smacro

(with-profiling pdata {:as opts :keys [dynamic?]} & body)
Low-level primitive for advanced users.
Executes body with profiling active, and returns <body-result>.

If `:dynamic?` is false (default), body's evaluation MUST begin
and end without interruption on the same thread. This means that
body CANNOT contain any parking IoC style (e.g. `core.async`)
macros.

See `new-pdata` for more info on low-level primitives.
source

with-xfnclj/smacro

(with-xfn ?xfn form)
Evaluates given form with given `*xfn*` value, see `*xfn*` for details.
source

with-xfn+clj/smacro

(with-xfn+ ?xfn form)
Evaluates given form with composed `*xfn*` value.
Same as (with-xfn (comp-xfn *xfn* ?xfn) ...).
See `*xfn*` for details.
source

without-filtersclj/smacro

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

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

× close