[doc] Documentation improvements

This commit is contained in:
Peter Taoussanis 2024-04-25 09:37:55 +02:00
parent 28618f2115
commit f348c06a75
16 changed files with 165 additions and 83 deletions

View file

@ -41,7 +41,7 @@ See [here][GitHub releases] for earlier releases.
#### Flexibility #### Flexibility
- Config via plain **Clojure vals and fns** for easy customization, composition, and REPL debugging. - Config via plain **Clojure vals and fns** for easy customization, composition, and REPL debugging.
- Unmatched support for **system-level config** (JVM props, ENV vars, classpath resources). - Unmatched **environmental config** support (JVM properties, environment variables, or classpath resources).
- Expressive **per-call** and **per-handler** filtering at both **runtime** and **compile-time**. - Expressive **per-call** and **per-handler** filtering at both **runtime** and **compile-time**.
- Filter by namespace and id pattern, level, **level by namespace pattern**, etc. - Filter by namespace and id pattern, level, **level by namespace pattern**, etc.
- **Sampling**, **rate-limiting**, and **back-pressure monitoring**. - **Sampling**, **rate-limiting**, and **back-pressure monitoring**.

View file

@ -160,7 +160,8 @@
(defn handler:my-handler ; Note naming convention (defn handler:my-handler ; Note naming convention
"Returns a (fn handler [signal] that: "Returns a (fn handler [signal] that:
- Does something. - Takes a Telemere signal.
- Does something with it.
Options: Options:
`:option1` - Description `:option1` - Description
@ -169,8 +170,9 @@
([] (handler:my-handler nil)) ; Use default opts ([] (handler:my-handler nil)) ; Use default opts
([{:as constructor-opts}] ([{:as constructor-opts}]
;; Do expensive prep outside returned handler fn whenever possible - ;; Do option validation and expensive prep *outside* returned handler
;; i.e. at (one-off) construction time rather than handling time. ;; fn whenever possible - i.e. at (one-off) construction time rather than
;; at every handler call.
(let [] (let []
(fn a-handler:my-handler ; Note naming convention (fn a-handler:my-handler ; Note naming convention

View file

@ -0,0 +1,52 @@
Environmental filter config includes:
Kind filter:
JVM property: `taoensso.telemere.rt-kind-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_KIND_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-kind-filter.edn`
Namespace filter:
JVM property: `taoensso.telemere.rt-ns-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_NS_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-ns-filter.edn`
Id filter:
JVM property: `taoensso.telemere.rt-id-filter.edn`
Env variable: `TAOENSSO_TELEMERE_RT_ID_FILTER_EDN`
Classpath resource: `taoensso.telemere.rt-id-filter.edn`
Minimum level:
JVM property: `taoensso.telemere.rt-min-level.edn`
Env variable: `TAOENSSO_TELEMERE_RT_MIN_LEVEL_EDN`
Classpath resource: `taoensso.telemere.rt-min-level.edn`
Examples:
`taoensso.telemere.rt-min-level.edn` -> ":info"
`TAOENSSO_TELEMERE_RT_NS_FILTER_EDN` -> "{:deny \"taoensso.*\"}"
`taoensso.telemere.rt-id-filter.cljs.edn` -> "#{:my-id1 :my-id2}"
`TAOENSSO_TELEMERE_RT_KIND_FILTER_CLJ_EDN` -> "nil"
Tips:
- The above ids are for runtime filters (the most common).
For compile-time filters, change `rt`->`ct` / `RT`->`CT`.
- The above ids will affect both Clj AND Cljs.
For platform-specific filters, use
".clj.edn" / "_CLJ_EDN" or
".cljs.edn" / "_CLJS_EDN" suffixes instead.
- ".edn" / "_EDN" suffixes are optional.
- Config values should be edn. To get the right syntax, first set
your runtime filters using the standard utils (`set-min-level!`,
etc.). Then call `get-filters` and serialize the relevant parts
to edn with `pr-str`.
- All environmental config uses `get-env` underneath.
See the `get-env` docstring for more/advanced details.
- Classpath resources are files accessible on your project's
classpath. This usually includes files in your project's
`resources/` dir.

View file

@ -1,15 +0,0 @@
These include:
Compile-time:
ns-filter: (get-env {:as :edn} :taoensso.telemere/ct-ns-filter<.platform><.edn>)
id-filter: (get-env {:as :edn} :taoensso.telemere/ct-id-filter<.platform><.edn>)
min-level: (get-env {:as :edn} :taoensso.telemere/ct-min-level<.platform><.edn>)
Runtime:
ns-filter: (get-env {:as :edn} :taoensso.telemere/rt-ns-filter<.platform><.edn>)
id-filter: (get-env {:as :edn} :taoensso.telemere/rt-id-filter<.platform><.edn>)
min-level: (get-env {:as :edn, :default :info} :taoensso.telemere/rt-min-level<.platform><.edn>)
See `get-env` for details.

View file

@ -28,7 +28,9 @@ Default signal keys:
`:file` -------- ?str filename of signal creator callsite, same as (:file location) `:file` -------- ?str filename of signal creator callsite, same as (:file location)
`:sample-rate` - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all) `:sample-rate` - ?rate ∈ℝ[0,1] for combined signal AND handler sampling (0.75 => allow 75% of signals, nil => allow all)
<kvs> ---------- Arb other user-level ?kvs given to signal creator <kvs> ---------- Other arb user-level ?kvs given to signal creator. Typically NOT included
in handler output, so a great way to provide custom data/opts for use
(only) by custom middleware/handlers.
If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs! If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs!

View file

@ -1,4 +1,5 @@
A signal will be provided to a handler iff ALL of the following are true: A signal will be provided to a handler iff ALL of the following are true:
1. Signal (creation) is allowed by compile-time filters 1. Signal (creation) is allowed by compile-time filters
2. Signal (creation) is allowed by runtime filters 2. Signal (creation) is allowed by runtime filters
3. Signal (handling) is allowed by handler filters 3. Signal (handling) is allowed by handler filters
@ -7,18 +8,40 @@ A signal will be provided to a handler iff ALL of the following are true:
5. Handler middleware does not suppress the signal (return nil) 5. Handler middleware does not suppress the signal (return nil)
For 1-3, filtering may depend on (in order): For 1-3, filtering may depend on (in order):
Sample rate → namespace → kind → id → level → when form/fn → rate limit Sample rate → namespace → kind → id → level → when form/fn → rate limit
Note that sample rates are multiplicative: Compile-time vs runtime filtering:
If a signal is created with 20% sampling and a handler handles 50%
of given signals, then 10% of possible signals will be handled.
This multiplicative rate is helpfully reflected in each signal's final Compile-time filtering is an advanced feature that can be tricky to set
and use correctly. Most folks will want ONLY runtime filtering.
Compile-time filtering works by eliding (completely removing the code for)
disallowed signals. This means zero performance cost for these signals,
but also means that compile-time filtering is PERMANENT once applied.
So if you set `:info` as the compile-time minimum level, that'll REMOVE
CODE for every signal call below `:info` level. To decrease that minimum
level, you'll need to rebuild.
Compile-time filtering can be set ONLY with environmental config
(JVM properties, environment variables, or classpath resources).
Signal and handler sampling is multiplicative:
Both signals and handlers can have independent sample rates, and these
MULTIPLY!
If a signal is created with 20% sampling and a handler handles 50%
of received signals, then 10% of possible signals will be handled
(50% of 20%).
The multiplicative rate is helpfully reflected in each signal's final
`:sample-rate` value. `:sample-rate` value.
For a visual flowchart, see: Ref. <https://www.taoensso.com/telemere/flow>
For more info: For more info:
- Signal visual flowchart, Ref. <https://www.taoensso.com/telemere/flow>
- On signal filters, see: `help:signal-filters` docstring - On signal filters, see: `help:signal-filters` docstring
- On handler filters, see: `help:signal-handlers` docstring - On handler filters, see: `help:signal-handlers` docstring

View file

@ -18,14 +18,18 @@ Signal options (shared by all signal creators):
`:parent` ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal info in signal `:parent` ------ Custom ?{:keys [id uid]} to override auto (dynamic) parent signal info in signal
`:location` ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location `:location` ---- Custom ?{:keys [ns line column file]} to override auto signal creator callsite location
`:elidable?` --- Should signal be subject to compile-time elision? (Default: true). `: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) `: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 `: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` -- ?spec as given to `taoensso.telemere/rate-limiter`, see its docstring for details
`:middleware` -- ?[(fn [signal])=>modified-signal ...] signal middleware `:middleware` -- ?[(fn [signal])=>modified-signal ...] signal middleware
`:trace?` ------ Should tracing be enabled for `:run` form? `:trace?` ------ Should tracing be enabled for `:run` form?
<kvs> ---------- Arb other user-level ?kvs to incl. in signal <kvs> ---------- Other arb user-level ?kvs to incl. in signal. Typically NOT included in
handler output, so a great way to provide custom data/opts for use
(only) by custom middleware/handlers.
handler-specific data that can just be ignored by other handlers
If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs! If anything is unclear, please ping me (@ptaoussanis) so that I can improve these docs!

View file

@ -47,8 +47,8 @@
:ct-sig-filter impl/ct-sig-filter :ct-sig-filter impl/ct-sig-filter
:*rt-sig-filter* impl/*rt-sig-filter* :*rt-sig-filter* impl/*rt-sig-filter*
:*sig-handlers* impl/*sig-handlers* :*sig-handlers* impl/*sig-handlers*
:sig-filter-system-vals-info :sig-filter-env-config-help
(impl/signal-docstring :filter-system-vals)}) (impl/signal-docstring :filter-env-config)})
(comment help:filters) (comment help:filters)

View file

@ -34,29 +34,35 @@
;;;; Config ;;;; Config
#?(:clj #?(:clj
(let [base (enc/get-env {:as :edn} :taoensso.telemere/ct-filters<.platform><.edn>) (let [base (enc/get-env {:as :edn} :taoensso.telemere/ct-filters<.platform><.edn>)
ns-filter (enc/get-env {:as :edn} :taoensso.telemere/ct-ns-filter<.platform><.edn>) kind-filter (enc/get-env {:as :edn} :taoensso.telemere/ct-kind-filter<.platform><.edn>)
id-filter (enc/get-env {:as :edn} :taoensso.telemere/ct-id-filter<.platform><.edn>) ns-filter (enc/get-env {:as :edn} :taoensso.telemere/ct-ns-filter<.platform><.edn>)
min-level (enc/get-env {:as :edn} :taoensso.telemere/ct-min-level<.platform><.edn>)] id-filter (enc/get-env {:as :edn} :taoensso.telemere/ct-id-filter<.platform><.edn>)
min-level (enc/get-env {:as :edn} :taoensso.telemere/ct-min-level<.platform><.edn>)]
(enc/defonce ct-sig-filter (enc/defonce ct-sig-filter
"`SigFilter` used for compile-time elision, or nil." "`SigFilter` used for compile-time elision, or nil."
(sigs/sig-filter (sigs/sig-filter
{:ns-filter (or ns-filter (get base :ns-filter)) {:kind-filter (or kind-filter (get base :kind-filter))
:id-filter (or id-filter (get base :id-filter)) :ns-filter (or ns-filter (get base :ns-filter))
:min-level (or min-level (get base :min-level))})))) :id-filter (or id-filter (get base :id-filter))
:min-level (or min-level (get base :min-level))}))))
(let [base (enc/get-env {:as :edn} :taoensso.telemere/rt-filters<.platform><.edn>) (let [base (enc/get-env {:as :edn} :taoensso.telemere/rt-filters<.platform><.edn>)
ns-filter (enc/get-env {:as :edn} :taoensso.telemere/rt-ns-filter<.platform><.edn>) kind-filter (enc/get-env {:as :edn} :taoensso.telemere/rt-kind-filter<.platform><.edn>)
id-filter (enc/get-env {:as :edn} :taoensso.telemere/rt-id-filter<.platform><.edn>) ns-filter (enc/get-env {:as :edn} :taoensso.telemere/rt-ns-filter<.platform><.edn>)
min-level (enc/get-env {:as :edn, :default :info} :taoensso.telemere/rt-min-level<.platform><.edn>)] id-filter (enc/get-env {:as :edn} :taoensso.telemere/rt-id-filter<.platform><.edn>)
min-level (enc/get-env {:as :edn, :default :info} :taoensso.telemere/rt-min-level<.platform><.edn>)]
(enc/defonce ^:dynamic *rt-sig-filter* (enc/defonce ^:dynamic *rt-sig-filter*
"`SigFilter` used for runtime filtering, or nil." "`SigFilter` used for runtime filtering, or nil."
(sigs/sig-filter (sigs/sig-filter
{:ns-filter (or ns-filter (get base :ns-filter)) {:kind-filter (or kind-filter (get base :kind-filter))
:id-filter (or id-filter (get base :id-filter)) :ns-filter (or ns-filter (get base :ns-filter))
:min-level (or min-level (get base :min-level))}))) :id-filter (or id-filter (get base :id-filter))
:min-level (or min-level (get base :min-level))})))
(comment (enc/get-env {:as :edn, :return :explain} :taoensso.telemere/rt-filters<.platform><.edn>))
;;;; Context (optional arb app-level state) ;;;; Context (optional arb app-level state)
;; taoensso.telemere/*ctx* ;; taoensso.telemere/*ctx*

View file

@ -39,10 +39,10 @@
(defn tools-logging->telemere! (defn tools-logging->telemere!
"Configures `clojure.tools.logging` to use Telemere as its logging implementation. "Configures `clojure.tools.logging` to use Telemere as its logging implementation.
Called automatically if the following is true: Called automatically if one of the following is \"true\":
(get-env {:as :bool} :clojure.tools.logging/to-telemere) JVM property: `clojure.tools.logging.to-telemere`
Env variable: `CLOJURE_TOOLS_LOGGING_TO_TELEMERE`
See `get-env` for details." Classpath resource: `clojure.tools.logging.to-telemere`"
[] []
(impl/signal! (impl/signal!
{:kind :event {:kind :event

View file

@ -188,11 +188,11 @@ Quick examples of some basic filtering:
``` ```
- Filtering is always O(1), except for rate limits which are O(n_windows). - Filtering is always O(1), except for rate limits which are O(n_windows).
- Sample rates are *multiplicative*: if a signal is created with *20%* sampling and a handler handles *50%* of given signals, then *10%* of possible signals will be handled. This multiplicative rate is helpfully reflected in each signal's final `:sample-rate` value. - Signal and handler sampling is *multiplicative*: if a signal is created with *20%* sampling and a handler handles *50%* of received signals, then *10%* of possible signals will be handled. This multiplicative rate is helpfully reflected in each signal's final `:sample-rate` value.
- See [`help:signal-flow`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-flow) for internal docs on signal flow. - See [`help:signal-flow`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-flow) for internal docs on signal flow.
- See section [2-Architecture](./2-Architecture) for a flowchart / visual aid. - See section [2-Architecture](./2-Architecture) for a flowchart / visual aid.
Runtime signal filters can be configured with: Runtime signal filters can be set with:
| Global | Dynamic | Filters by | | Global | Dynamic | Filters by |
| :-------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | | :-------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- |
@ -202,7 +202,7 @@ Runtime signal filters can be configured with:
| [`set-min-level`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#set-min-level) | [`with-min-level`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#with-min-level) | Signal level (minimum can be specified by kind and/or ns) | | [`set-min-level`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#set-min-level) | [`with-min-level`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#with-min-level) | Signal level (minimum can be specified by kind and/or ns) |
- See relevant docstrings (links above) for usage info. - See relevant docstrings (links above) for usage info.
- Compile-time filters are controlled by system-level config, see section [3-Config](./3-Config). - Compile-time filters are set with environmental config, see section [3-Config](./3-Config).
# Internal help # Internal help

View file

@ -13,7 +13,7 @@ A signal will be provided to a handler iff ALL of the following are true:
For 1-3, filtering may depend on (in order): For 1-3, filtering may depend on (in order):
Sample rate → namespace → kind → id → level → when form/fn → rate limit Sample rate → namespace → kind → id → level → when form/fn → rate limit
- See [`help:signal-filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-filters) for info on signal creation filters. - See [`help:signal-filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-filters) for info on signal creation filters, **environmental config**, etc.
- See [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!) for info on signal handler filters. - See [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!) for info on signal handler filters.
# Signal handlers # Signal handlers
@ -29,7 +29,7 @@ See section [4-Handlers](./4-Handlers).
To do this: To do this:
1. Ensure that you have the `clojure.tools.logging` dependency, and 1. Ensure that you have the `clojure.tools.logging` dependency, and
2. Call [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.tools-logging#tools-logging-%3Etelemere!), or set the relevant system config as described in its docstring. 2. Call [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.tools-logging#tools-logging-%3Etelemere!), or set the relevant environmental config as described in its docstring.
Verify successful intake with [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes): Verify successful intake with [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes):

View file

@ -2,18 +2,22 @@ Signal handlers process created signals to *do something with them* (analyse the
# Included handlers # Included handlers
The following handlers are included out-the-box: The following signal handlers are currently included out-the-box:
| Name | Platform | Writes signals to | Writes signals as | | Name | Platform | Output target | Output format |
| :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Clj | `*out*` or `*err*` | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) | | [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Clj | `*out*` or `*err*` | Formatted string [1] |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) | | [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | Formatted string [1] |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw data (for [cljs-devtools](https://github.com/binaryage/cljs-devtools), etc.) | | [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw signal data [2] |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) | | [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | Formatted string [1] |
| [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.open-telemetry#handler:open-telemetry-logger) | Clj | [OpenTelemetry](https://opentelemetry.io/) [Java client](https://github.com/open-telemetry/opentelemetry-java) | [LogRecord](https://opentelemetry.io/docs/specs/otel/logs/data-model/) | | [`handler:postal`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.postal#handler:postal) | Clj | Email (via [postal](https://github.com/drewr/postal)) | Formatted string [1] |
| [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.open-telemetry#handler:open-telemetry-logger) | Clj | [OpenTelemetry](https://opentelemetry.io/) [Java client](https://github.com/open-telemetry/opentelemetry-java) | [LogRecord](https://opentelemetry.io/docs/specs/otel/logs/data-model/) |
- See relevant docstrings (links above) for more info. - \[1] [Configurable](https://cljdoc.org/d/com.taoensso/telemere/1.0.0-beta3/api/taoensso.telemere#help:signal-formatters): human-readable (default), [edn](https://github.com/edn-format/edn), [JSON](https://www.json.org/), etc.
- See section [8-Community](8-Community.md) for additional handlers. - \[2] For use with browser formatting tools like [cljs-devtools](https://github.com/binaryage/cljs-devtools).
- See relevant docstrings (links above) for features, usage, etc.
- See section [8-Community](8-Community.md) for more (community-supported) handlers.
- If there's other handlers you'd like to see, feel free to [ping me](https://github.com/taoensso/telemere/issues), or ask on the [`#telemere` Slack channel](https://www.taoensso.com/telemere/slack). It helps to know what people most need!
# Configuring handlers # Configuring handlers
@ -97,11 +101,11 @@ Want to add or remove a particular handler when your application starts?
Just make an appropriate call to [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!) or [`remove-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#remove-handler!). Just make an appropriate call to [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!) or [`remove-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#remove-handler!).
## System-level config ## Environmental config
If you want to manage handlers **conditionally** based on **system-level config** (e.g. JVM prop, ENV var, or classpath resource) - Telemere provides the highly flexible [`get-env`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#get-env) util. If you want to manage handlers **conditionally** based on **environmental config** (JVM properties, environment variables, or classpath resources) - Telemere provides the highly flexible [`get-env`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#get-env) util.
Use this to easily check your own cross-platform system config, and make whatever conditional handler management decisions you'd like. Use this to easily define your own arbitrary cross-platform config, and make whatever conditional handler management decisions you'd like.
# Writing handlers # Writing handlers
@ -120,7 +124,8 @@ For more complex cases, or for handlers that you want to make available for use
```clojure ```clojure
(defn handler:my-handler ; Note naming convention (defn handler:my-handler ; Note naming convention
"Returns a (fn handler [signal] that: "Returns a (fn handler [signal] that:
- Does something. - Takes a Telemere signal.
- Does something with it.
Options: Options:
`:option1` - Description `:option1` - Description
@ -129,8 +134,9 @@ For more complex cases, or for handlers that you want to make available for use
([] (handler:my-handler nil)) ; Use default opts ([] (handler:my-handler nil)) ; Use default opts
([{:as constructor-opts}] ([{:as constructor-opts}]
;; Do expensive prep outside returned handler fn whenever possible - ;; Do option validation and expensive prep *outside* returned handler
;; i.e. at (one-off) construction time rather than handling time. ;; fn whenever possible - i.e. at (one-off) construction time rather than
;; at every handler call.
(let [] (let []
(fn a-handler:my-handler ; Note naming convention (fn a-handler:my-handler ; Note naming convention
@ -181,4 +187,4 @@ Chrome console, with [cljs-devtools](https://github.com/binaryage/cljs-devtools)
MacOS terminal: MacOS terminal:
<img src="https://raw.githubusercontent.com/taoensso/telemere/master/imgs/handler-output-clj-file.png" alt="Default Clojure file handler output" width="640"/> <img src="https://raw.githubusercontent.com/taoensso/telemere/master/imgs/handler-output-clj-file.png" alt="Default Clojure file handler output" width="640"/>

View file

@ -26,7 +26,7 @@ If not, you may need to [write something yourself](./4-Handlers#writing-handlers
This may be easier than it sounds. Remember that signals are just plain Clojure/Script [maps](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content), and handlers just plain Clojure/Script functions that do something with those maps. This may be easier than it sounds. Remember that signals are just plain Clojure/Script [maps](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content), and handlers just plain Clojure/Script functions that do something with those maps.
Feel free to [ping me](https://github.com/taoensso/telemere/issues) for assistance, or ask on the [`#telemere` Slack channel](https://clojurians.slack.com/archives/C06ALA6EEUA). Feel free to [ping me](https://github.com/taoensso/telemere/issues) for assistance, or ask on the [`#telemere` Slack channel](https://www.taoensso.com/telemere/slack).
### 2. Imports ### 2. Imports

View file

@ -72,7 +72,7 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between
- [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) and [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) are both **good general-purpose** signal creators. - [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) and [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) are both **good general-purpose** signal creators.
- Try **always provide an id** for all signals you create. - **Provide an id** for all signals you create.
Qualified keywords are perfect! Downstream behaviour (e.g. alerts) can then look for these ids rather than messages (which are harder to match and more likely to change). Qualified keywords are perfect! Downstream behaviour (e.g. alerts) can then look for these ids rather than messages (which are harder to match and more likely to change).
@ -84,11 +84,13 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between
The result of signal middleware is cached and *shared between all handlers* making it an efficient place to transform signals. For this reason - prefer signal middleware to handler middleware when possible/convenient. The result of signal middleware is cached and *shared between all handlers* making it an efficient place to transform signals. For this reason - prefer signal middleware to handler middleware when possible/convenient.
- **Signal sampling** and **handler sampling** are **multiplicative**. - Signal and handler **sampling is multiplicative**.
If a signal is created with *20%* sampling and a handler handles *50%* of given signals, then *10%* of possible signals will be handled. Both signals and handlers can have independent sample rates, and these MULTIPLY!
This multiplicative rate is helpfully reflected in each signal's final `:sample-rate` value, making it possible to estimate unsampled cardinalities in relevant cases. 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%).
This multiplicative rate is helpfully reflected in each signal's final `:sample-rate` value, making it possible to estimate *unsampled* cardinalities in relevant cases.
So for `n` randomly sampled signals matching some criteria, you'd have seen an estimated `Σ(1.0/sample-rate_i)` such signals _without_ sampling, etc. So for `n` randomly sampled signals matching some criteria, you'd have seen an estimated `Σ(1.0/sample-rate_i)` such signals _without_ sampling, etc.
@ -117,7 +119,7 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between
Note that all user kvs will *also* be available *together* under the signal's `:kvs` key. Note that all user kvs will *also* be available *together* under the signal's `:kvs` key.
User kvs are a great way of controlling the per-signal behaviour of custom/advanced handlers. User kvs are typically *not* included in handler output, so are a great way of providing custom data/opts for use (only) by custom middleware or handlers.
- Signal `kind` can be useful in advanced cases. - Signal `kind` can be useful in advanced cases.

View file

@ -4,7 +4,7 @@ If there's demand, additional stuff can then be authored by Telemere's *communit
**PRs very welcome** to add links to this page for: **PRs very welcome** to add links to this page for:
- Handlers (see [Writing handlers](./4-Handlers#writing-handlers)) - Handler libraries or examples (see [Writing handlers](./4-Handlers#writing-handlers))
- Handler utils (formatters, etc.) - Handler utils (formatters, etc.)
- Middleware - Middleware
- Tutorials / demos / etc. - Tutorials / demos / etc.
@ -12,9 +12,9 @@ If there's demand, additional stuff can then be authored by Telemere's *communit
If you spot issues with any linked resources, please **contact the relevant authors** to let them know! Thank you! 🙏 If you spot issues with any linked resources, please **contact the relevant authors** to let them know! Thank you! 🙏
| Contributor | Link | Description | | Contributor | Link | Description |
| :--------------------------------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------ | | :--------------------------------------------- | :---------------------------------------------------------------- | :------------------------------------------------------------ |
| [@ptaoussanis](https://github.com/ptaoussanis) | [Official Slack channel](https://clojurians.slack.com/archives/C06ALA6EEUA) | For questions, support, etc. | | [@ptaoussanis](https://github.com/ptaoussanis) | [Official Slack channel](https://www.taoensso.com/telemere/slack) | For questions, support, etc. |
| [@ptaoussanis](https://github.com/ptaoussanis) | [GitHub issues](https://github.com/taoensso/telemere/issues) | For questions, support, bug reports, PRs, etc. | | [@ptaoussanis](https://github.com/ptaoussanis) | [GitHub issues](https://github.com/taoensso/telemere/issues) | For questions, support, bug reports, PRs, etc. |
| _ | _ | Your link here? [PRs](../wiki#contributions-welcome) welcome! | | _ | _ | Your link here? [PRs](../wiki#contributions-welcome) welcome! |
| [@username](https://github.com/username) | [Project](https://github.com/username/project) | Short description of resource | | [@username](https://github.com/username) | [Project](https://github.com/username/project) | Short description of resource |