[nop] Housekeeping, docs

This commit is contained in:
Peter Taoussanis 2024-05-08 09:54:08 +02:00
parent f2ae522c62
commit 7847bd1348
7 changed files with 119 additions and 145 deletions

View file

@ -1,5 +1,5 @@
<a href="https://www.taoensso.com/clojure" title="More stuff by @ptaoussanis at www.taoensso.com"><img src="https://www.taoensso.com/open-source.png" alt="Taoensso open source" width="340"/></a>
[**Documentation**](#documentation) | [Latest releases](#latest-releases) | [Slack channel][]
[**API**][cljdoc docs] | [**Wiki**][GitHub wiki] | [Latest releases](#latest-releases) | [Slack channel][]
# <img src="https://raw.githubusercontent.com/taoensso/telemere/master/imgs/telemere-logo.svg" alt="Telemere logo" width="360"/>
@ -32,7 +32,7 @@ See [here][GitHub releases] for earlier releases.
- 1st-class **out-the-box interop** with [SLF4J v2](https://www.slf4j.org/), [clojure.tools.logging](https://github.com/clojure/tools.logging), [OpenTelemetry](https://opentelemetry.io/), and [Tufte](https://www.taoensso.com/tufte).
- Included [shim](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.timbre) for easy/gradual [migration from Timbre](../../wiki/5-Migrating).
- Included [handlers](../../wiki/4-Handlers#included-handlers) for consoles, files, email, Redis, Slack, sockets, and more.
- Extensive set of [handlers](../../wiki/4-Handlers#included-handlers) included out-the-box.
#### Scaling
@ -61,7 +61,11 @@ See for intro and usage:
```clojure
(require '[taoensso.telemere :as t])
;; Start simple
(t/log! {:id ::my-id, :data {:x1 :x2}} "My message") %>
;; 2024-04-11T10:54:57.202869Z INFO LOG Schrebermann.local examples(56,1) ::my-id - My message
;; data: {:x1 :x2}
(t/log! "This will send a `:log` signal to the Clj/s console")
(t/log! :info "This will do the same, but only when the current level is >= `:info`")
@ -142,48 +146,30 @@ See relevant docstrings (links below) for usage info-
| [`help:signal-filters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-filters) | API for configuring signal filters |
| [`help:signal-handlers`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-handlers) | API for configuring signal handlers |
### Example handler output
### Included handlers
```clojure
(t/log! {:id ::my-id, :data {:x1 :x2}} "My message") =>
```
See linked docstrings below for features and usage:
#### Clj console handler
| 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*` | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw signals for [cljs-devtools](https://github.com/binaryage/cljs-devtools), etc. |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`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)) | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:slack`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.slack#handler:slack) | Clj | [Slack](https://slack.com/) (via [clj-slack](https://github.com/julienXX/clj-slack)) | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:tcp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:tcp-socket) | Clj | TCP socket | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:udp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:udp-socket) | Clj | UDP socket | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
String output:
```
2024-04-11T10:54:57.202869Z INFO LOG Schrebermann.local examples(56,1) ::my-id - My message
data: {:x1 :x2}
```
#### Cljs console handler
Chrome console:
<img src="https://raw.githubusercontent.com/taoensso/telemere/master/imgs/handler-output-cljs-console.png" alt="Default ClojureScript console handler output" width="640"/>
#### Cljs raw console handler
Chrome console, with [cljs-devtools](https://github.com/binaryage/cljs-devtools):
<img src="https://raw.githubusercontent.com/taoensso/telemere/master/imgs/handler-output-cljs-console-raw.png" alt="Raw ClojureScript console handler output" width="640"/>
#### Clj file handler
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"/>
See [here](../../wiki/4-Handlers) for more/upcoming handlers, community handlers, info on **writing your own handlers**, etc.
## Documentation
- [Wiki][GitHub wiki] (getting started, usage, etc.)
- API reference: [cljdoc][cljdoc docs] or [Codox][Codox docs]
- Support: [Slack channel][] or [GitHub issues][]
## Observability tips
See [here](../../wiki/7-Tips) for general advice re: building and maintaining observable Clojure/Script systems.
- [General observability tips](../../wiki/7-Tips) (advice on building and maintaining observable Clojure/Script systems, and getting the most out of Telemere)
## Benchmarks

View file

@ -8,7 +8,7 @@
:url "https://www.eclipse.org/legal/epl-v10.html"}
:dependencies
[[com.taoensso/encore "3.108.0"]]
[[com.taoensso/encore "3.109.0"]]
:test-paths ["test" #_"src"]

View file

@ -1,7 +1,7 @@
{;;:lein true
:source-paths ["src" "test"]
:dependencies
[[com.taoensso/encore "3.108.0"]
[[com.taoensso/encore "3.109.0"]
[cider/cider-nrepl "0.47.0"]
[binaryage/devtools "1.0.7"]]

View file

@ -32,7 +32,7 @@
(remove-ns 'taoensso.telemere)
(:api (enc/interns-overview)))
(enc/assert-min-encore-version [3 108 0])
(enc/assert-min-encore-version [3 109 0])
;;;; TODO
;; - Add handlers: Logstash, Carmine, Datadog, Kafka

View file

@ -112,58 +112,40 @@
(comment (error-signal? {:level :fatal}))
(defn error-in-signal->maps
"Experimental, subject to change.
Returns given signal with possible `:error` replaced by
[{:keys [type msg data]} ...] cause chain.
Useful when serializing signals to edn/JSON/etc."
[signal]
(enc/if-let [error (get signal :error)
chain (enc/ex-chain :as-map error)]
(assoc signal :error chain)
(do signal)))
(comment (error-in-signal->maps {:level :info :error (ex-info "Ex" {})}))
(defn remove-kvs
"Returns given signal without user-level kvs."
(defn ^:no-doc remove-signal-kvs
"Private, don't use.
Returns given signal without user-level kvs or `:kvs` key."
[signal]
(if-let [kvs (get signal :kvs)]
(reduce-kv (fn [m k _v] (dissoc m k)) (dissoc signal :kvs) kvs)
signal))
(comment (remove-kvs {:a :A, :b :B, :kvs {:a :A}}))
(defn minify-signal
"Experimental, subject to change.
Returns minimal signal, removing:
- Keys with nil values, and
- Keys with redundant values (`:kvs`, `:location`, `:file`).
Useful when serializing signals to edn/JSON/etc."
;; Note that while handlers typically don't include user-level kvs, we
;; DO retain these here since signal serialization often implies transit
;; to some other system that may still need/want this info before final
;; processing/storage/etc.
(defn ^:no-doc remove-signal-nils
"Private, don't use.
Returns given signal with nil-valued keys removed."
[signal]
(reduce-kv
(fn [m k v]
(if (nil? v)
m
(case k
(:kvs :location :file) m
(assoc m k v))))
nil signal))
(comment
(minify-signal (tel/with-signal (tel/event! ::ev-id1)))
(let [s (tel/with-signal (tel/event! ::ev-id1))]
(enc/qb 1e6 ; 683
(minify-signal s))))
(if (enc/editable? signal)
(persistent! (reduce-kv (fn [m k v] (if (nil? v) (dissoc! m k) m)) (transient signal) signal))
(persistent! (reduce-kv (fn [m k v] (if (nil? v) m (assoc! m k v))) (transient {}) signal))))
(defn ^:no-doc force-signal-msg
"Private, don't use.
Returns given signal with possible `:msg_` value forced (realized when a delay)."
[signal]
(if-let [msg_ (get signal :msg_)]
(assoc signal :msg_ (force msg_))
(do signal)))
(defn ^:no-doc expand-signal-error
"Private, don't use.
Returns given signal with possible `:error` replaced by
[{:keys [type msg data]} ...] cause chain."
[signal]
(enc/if-let [error (get signal :error)
chain (enc/ex-chain :as-map error)]
(assoc signal :error chain)
(do signal)))
;;;; Files
#?(:clj (defn ^:no-doc as-file ^java.io.File [file] (jio/as-file file)))
@ -604,8 +586,8 @@
{incl-newline? true
pr-fn :edn
prep-fn
(comp error-in-signal->maps
minify-signal)}}]
(comp expand-signal-error
remove-signal-nils)}}]
(let [nl newline
pr-fn

View file

@ -641,6 +641,14 @@
(is (= (utils/error-signal? {:level :fatal}) true))
(is (= (utils/error-signal? {:error? true}) true))])
(testing "Misc utils"
[(is (= (utils/remove-signal-kvs {:a :A, :b :B, :kvs {:b :B}}) {:a :A}))
(is (= (utils/remove-signal-nils {:a :A, :b nil}) {:a :A}))
(is (= (utils/force-signal-msg {:a :A, :msg_ (delay "msg")}) {:a :A, :msg_ "msg"}))
(is (= (utils/expand-signal-error {:level :info, :error ex2})
{:level :info, :error [{:type ex-info-type, :msg "Ex2", :data {:k2 "v2"}}
{:type ex-info-type, :msg "Ex1", :data {:k1 "v1"}}]}))])
#?(:clj
(testing "File writer"
(let [f (java.io.File/createTempFile "file-writer-test" ".txt")
@ -662,12 +670,7 @@
(is (true? (.delete f)))])))
(testing "Formatters, etc."
[(is (= (utils/error-in-signal->maps {:level :info, :error ex2})
{:level :info, :error [{:type ex-info-type, :msg "Ex2", :data {:k2 "v2"}}
{:type ex-info-type, :msg "Ex1", :data {:k1 "v1"}}]}))
(is (= (utils/minify-signal {:level :info, :location {:ns "ns"}, :file "file"}) {:level :info}))
(is (= ((utils/format-nsecs-fn) 1.5e9) "1.50s")) ; More tests in Encore
[(is (= ((utils/format-nsecs-fn) 1.5e9) "1.50s")) ; More tests in Encore
(is (= ((utils/format-inst-fn) t0) "2024-06-09T21:15:20.170Z"))
(testing "format-error-fn"
@ -680,47 +683,47 @@
(is (enc/str-contains? ex2-str "invoke") "Root stack trace includes content")]))
(testing "signal-preamble-fn"
(let [sig (with-sig (tel/event! ::ev-id {:inst t0}))
(let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t0, :msg ["a" "b"]}))
preamble ((utils/signal-preamble-fn) sig)] ; "2024-06-09T21:15:20.170Z INFO EVENT taoensso.telemere-tests(592,35) ::ev-id"
[(is (enc/str-starts-with? preamble "2024-06-09T21:15:20.170Z INFO EVENT"))
(is (enc/str-ends-with? preamble "::ev-id"))
(is (enc/str-ends-with? preamble "::ev-id - a b"))
(is (string? (re-find #"taoensso.telemere-tests\(\d+,\d+\)" preamble)))]))
(testing "pr-signal-fn"
(let [sig (with-sig (tel/event! ::ev-id {:inst t0}))]
[(testing ":edn"
(let [sig (update sig :inst enc/inst->udt)
sig*1 (enc/read-edn ((tel/pr-signal-fn {:pr-fn :edn}) sig))
sig*2 (enc/read-edn ((tel/pr-signal-fn) sig))]
[(testing ":edn"
(let [sig (update sig :inst enc/inst->udt)
sig*1 (enc/read-edn ((tel/pr-signal-fn {:pr-fn :edn}) sig))
sig*2 (enc/read-edn ((tel/pr-signal-fn) sig))]
[(is (= sig*1 sig*2) "Default :pr-fn is :edn")
(is
(enc/submap? sig*1
{:schema 1, :kind :event, :id ::ev-id, :level :info,
:ns "taoensso.telemere-tests"
:inst udt0
:line pnat-int?
:column pnat-int?}))]))
[(is (= sig*1 sig*2) "Default :pr-fn is :edn")
(is
(enc/submap? sig*1
{:schema 1, :kind :event, :id ::ev-id, :level :info,
:ns "taoensso.telemere-tests"
:inst udt0
:line pnat-int?
:column pnat-int?}))]))
#?(:cljs
(testing ":json"
(let [sig* (enc/read-json ((tel/pr-signal-fn {:pr-fn :json}) sig))]
(is
(enc/submap? sig*
{"schema" 1, "kind" "event", "id" "taoensso.telemere-tests/ev-id",
"level" "info", "ns" "taoensso.telemere-tests",
"inst" t0s
"line" pnat-int?
"column" pnat-int?})))))
#?(:cljs
(testing ":json"
(let [sig* (enc/read-json ((tel/pr-signal-fn {:pr-fn :json}) sig))]
(is
(enc/submap? sig*
{"schema" 1, "kind" "event", "id" "taoensso.telemere-tests/ev-id",
"level" "info", "ns" "taoensso.telemere-tests"
"inst" t0s
"line" pnat-int?
"column" pnat-int?})))))
(testing "user fn"
(is (= ((tel/pr-signal-fn {:pr-fn (fn [_] "str")}) sig) (str "str" utils/newline))))]))
(testing "user fn"
(is (= ((tel/pr-signal-fn {:pr-fn (fn [_] "str")}) sig) (str "str" utils/newline))))]))
(testing "format-signal-fn"
(let [sig (with-sig (tel/event! ::ev-id {:inst t0}))]
(is (enc/str-starts-with? ((tel/format-signal-fn) sig)
"2024-06-09T21:15:20.170Z INFO EVENT"))))])])
(let [sig (with-sig :raw :trap (tel/event! ::ev-id {:inst t0, :msg ["a" "b"]}))]
(is (enc/str-starts-with? ((tel/format-signal-fn) sig) "2024-06-09T21:15:20.170Z INFO EVENT"))
(is (enc/str-ends-with? ((tel/format-signal-fn) sig) "::ev-id - a b\n"))))])])
;;;; File handler

View file

@ -2,29 +2,32 @@ Signal handlers process created signals to **do something with them** (analyse t
# Included handlers
A number of signal handlers are included out-the box. Alphabetically:
Telemere includes a number of signal handlers out-the-box.
| Name | Platform | Output target | Output format |
| :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- |
| [`handler:carmine`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.carmine#handler:carmine) [0] | Clj | [Redis](https://redis.io/) (via [Carmine](https://www.taoensso.com/carmine)) | Serialized signals [1] |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Clj | `*out*` or `*err*` | String [2] |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | String [2] |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw signals [3] |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | String [2] |
| [`handler:logstash`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.logstash#handler:logstash) [0] | Clj | [Logstash](https://www.elastic.co/logstash) | TODO |
| [`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)) | String [2] |
| [`handler:slack`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.slack#handler:slack) | Clj | [Slack](https://slack.com/) (via [clj-slack](https://github.com/julienXX/clj-slack)) | String [2] |
| [`handler:tcp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:tcp-socket) | Clj | TCP socket | String [2] |
| [`handler:udp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:udp-socket) | Clj | UDP socket | String [2] |
[Writing your own handlers](#writing-handlers) is also often straight-forward, and [PRs](https://github.com/taoensso/telemere/pulls) are **very welcome** for additions to Telemere's included handlers, or to Telemere's [community resources](./8-Community).
- \[0] Coming soon
- \[1] Uses [Nippy](https://taoensso.com/nippy) to support all Clojure's rich data types
- \[2] [Human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) (default), or [machine-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) ([edn](https://github.com/edn-format/edn), [JSON](https://www.json.org/), etc.).
- \[3] 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!
It helps to know what people need! You can [vote on](https://www.taoensso.com/roadmap/vote) additional handlers to add, [ping me](https://github.com/taoensso/telemere/issues), or ask on the [`#telemere` Slack channel](https://www.taoensso.com/telemere/slack).
Current handlers, alphabetically (see linked docstrings below for features and usage):
| 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*` | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw signals for [cljs-devtools](https://github.com/binaryage/cljs-devtools), etc. |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`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)) | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:slack`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.slack#handler:slack) | Clj | [Slack](https://slack.com/) (via [clj-slack](https://github.com/julienXX/clj-slack)) | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:tcp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:tcp-socket) | Clj | TCP socket | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
| [`handler:udp-socket`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.sockets#handler:udp-socket) | Clj | UDP socket | [edn/JSON](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#pr-signal-fn) or [human-readable](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#format-signal-fn) |
Planned (upcoming) handlers:
| Name | Platform | Output target | Output format |
| :----------------------------------------------------------------------------------------------------------------------- | :------- | :--------------------------------------------------------------------------- | :----------------------------------------------- |
| [`handler:carmine`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.carmine#handler:carmine) | Clj | [Redis](https://redis.io/) (via [Carmine](https://www.taoensso.com/carmine)) | [Serialized](https://taoensso.com/nippy) signals |
| [`handler:logstash`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.logstash#handler:logstash) | Clj | [Logstash](https://www.elastic.co/logstash) | TODO |
# Configuring handlers
@ -35,7 +38,7 @@ There's two kinds of config relevant to all signal handlers:
## Dispatch opts
Dispatch opts includes dispatch priority, handler filtering, handler middleware, queue semantics, back-pressure opts, etc.
Handler dispatch opts includes dispatch priority, handler filtering, handler middleware, queue semantics, back-pressure opts, etc.
This is all specified when calling [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!) - and documented there.
@ -201,7 +204,7 @@ For more complex cases, or for handlers that you want to make available for use
- See [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) for signal map content.
- See the [utils namespace](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.utils) for tools useful for customizing and writing signal handlers.
- See section [8-Community](8-Community.md) for PRs to link to community-authored handlers.
- [PRs](https://github.com/taoensso/telemere/pulls) are **very welcome** for additions to Telemere's included handlers, or to Telemere's [community resources](./8-Community)
# Example output