[nop] Housekeeping

This commit is contained in:
Peter Taoussanis 2024-05-05 14:15:09 +02:00
parent 19d447c44c
commit 0ff8dafaf3
13 changed files with 195 additions and 141 deletions

View file

@ -13,7 +13,7 @@ It helps enable Clojure/Script systems that are **observable**, **robust**, and
## Latest release/s ## Latest release/s
- `v1.0.0-beta7`: [release info](../../releases/tag/v1.0.0-beta7) - `v1.0.0-beta7`: [release info](../../releases/tag/v1.0.0-beta7) (for early adopters)
[![Main tests][Main tests SVG]][Main tests URL] [![Main tests][Main tests SVG]][Main tests URL]
[![Graal tests][Graal tests SVG]][Graal tests URL] [![Graal tests][Graal tests SVG]][Graal tests URL]
@ -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). - 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 [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, TCP/UDP sockets, Logstash, etc. - Included [handlers](../../wiki/4-Handlers#included-handlers) for consoles, files, email, Redis, Slack, sockets, and more.
#### Scaling #### Scaling

View file

@ -161,33 +161,49 @@
;;; Writing handlers ;;; Writing handlers
(defn handler:my-handler ; Note naming convention (defn handler:my-handler ; Note naming convention
"Returns a (fn handler [signal] that: "Needs `some-lib`, Ref. <https://github.com/example/some-lib>.
- Takes a Telemere signal.
- Does something with it. Returns a (fn handler [signal] that:
- Takes a Telemere signal (map).
- Does something with the signal.
Options: Options:
`:option1` - Description `:option1` - Option description
`:option2` - Description" `:option2` - Option description
([] (handler:my-handler nil)) ; Use default opts Tips:
- Tip 1
- Tip 2"
([] (handler:my-handler nil)) ; Use default opts (when defaults viable)
([{:as constructor-opts}] ([{:as constructor-opts}]
;; Do option validation and expensive prep *outside* returned handler ;; Do option validation and other prep here, i.e. try to keep expensive work
;; fn whenever possible - i.e. at (one-off) construction time rather than ;; outside handler function when possible.
;; at every handler call.
(let []
(fn a-handler:my-handler ; Note naming convention (let [handler-fn
(fn a-handler:my-handler ; Note naming convention
;; Shutdown arity - called by Telemere exactly once when the handler is ;; Shutdown arity - called by Telemere exactly once when the handler
;; to be shut down. This is your opportunity to finalize/free resources, etc. ;; is to be shut down.
([]) ([]
;; Can no-op, or finalize/free resources as necessary.
)
;; Main arity - called by Telemere whenever the handler should handle the ;; Main arity - called by Telemere whenever the handler should handle
;; given signal. Never called after shutdown. ;; the given signal. Never called after shutdown.
([signal] ([signal]
;; TODO Do something with given signal ;; Do something with given signal (write to console/file/queue/db, etc.).
))))) ;; Return value is ignored.
))
;; (Advanced) optional default handler dispatch opts,
;; see `add-handler!` for full list of possible opts
default-dispatch-opts
{:min-level :info
:rate-limit [[1 (enc/msecs :min 1)]]}]
(with-meta handler-fn default-dispatch-opts))))
;;; Message building ;;; Message building

View file

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

View file

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

View file

@ -32,7 +32,7 @@
(remove-ns 'taoensso.telemere) (remove-ns 'taoensso.telemere)
(:api (enc/interns-overview))) (:api (enc/interns-overview)))
(enc/assert-min-encore-version [3 107 0]) (enc/assert-min-encore-version [3 108 0])
;;;; TODO ;;;; TODO
;; - Add handlers: Logstash, Slack, Carmine, Datadog, Kafka ;; - Add handlers: Logstash, Slack, Carmine, Datadog, Kafka
@ -66,6 +66,7 @@
;;;; Aliases ;;;; Aliases
(enc/defaliases (enc/defaliases
;; Encore
#?(:clj enc/set-var-root!) #?(:clj enc/set-var-root!)
#?(:clj enc/update-var-root!) #?(:clj enc/update-var-root!)
#?(:clj enc/get-env) #?(:clj enc/get-env)
@ -74,23 +75,26 @@
enc/newline enc/newline
enc/comp-middleware enc/comp-middleware
;; Impl
impl/msg-splice impl/msg-splice
impl/msg-skip impl/msg-skip
#?(:clj impl/with-signal) #?(:clj impl/with-signal)
#?(:clj impl/with-signals) #?(:clj impl/with-signals)
#?(:clj impl/signal!) #?(:clj impl/signal!)
utils/error-signal?
;; Utils
utils/format-signal-fn
utils/pr-signal-fn utils/pr-signal-fn
utils/format-signal-fn) utils/error-signal?)
;;;; Help ;;;; Help
(impl/defhelp help:signal-creators :signal-creators) (impl/defhelp help:signal-creators :signal-creators)
(impl/defhelp help:signal-options :signal-options) (impl/defhelp help:signal-options :signal-options)
(impl/defhelp help:signal-flow :signal-flow) (impl/defhelp help:signal-flow :signal-flow)
(impl/defhelp help:signal-content :signal-content) (impl/defhelp help:signal-content :signal-content)
(enc/defalias help:signal-filters help:filters) ; Via Encore (enc/defalias help:signal-filters help:filters) ; Via Encore
(enc/defalias help:signal-handlers help:handlers) ; Via Encore (enc/defalias help:signal-handlers help:handlers) ; Via Encore
;;;; Context ;;;; Context
@ -151,7 +155,7 @@
"Optional (fn [signal]) => ?modified-signal to apply (once) when "Optional (fn [signal]) => ?modified-signal to apply (once) when
signal is created. When middleware returns nil, skips all handlers. signal is created. When middleware returns nil, skips all handlers.
Compose multiple middleware fns together with `comp-middleware. Compose multiple middleware fns together with `comp-middleware`.
Re/bind dynamic value using `with-middleware`, `binding`. Re/bind dynamic value using `with-middleware`, `binding`.
Modify root (base) value using `set-middleware!`." Modify root (base) value using `set-middleware!`."

View file

@ -14,17 +14,17 @@
#?(:clj #?(:clj
(defn ^:public handler:console (defn ^:public handler:console
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Writes formatted signal string to stream. - Writes the signal as a string to specified stream.
A general-purpose `println`-style handler that's well suited for outputting A general-purpose `println`-style handler that's well suited for outputting
signals formatted as edn, JSON, or human-readable strings. signals as human or machine-readable (edn, JSON) strings.
Options: Options:
`:output-fn` - (fn [signal]) => output string, see `format-signal-fn` or `pr-signal-fn` `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
`:stream` - `java.io.writer` `:stream` - `java.io.writer`
Defaults to `*err*` if `utils/error-signal?` is true, and `*out*` otherwise." Defaults to `*err*` if `utils/error-signal?` is true, and `*out*` otherwise."
@ -46,17 +46,17 @@
:cljs :cljs
(defn ^:public handler:console (defn ^:public handler:console
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
If `js/console` exists, returns a (fn handler [signal]) that: If `js/console` exists, returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Writes formatted signal string to JavaScript console. - Writes the signal as a string to JavaScript console.
A general-purpose `println`-style handler that's well suited for outputting A general-purpose `println`-style handler that's well suited for outputting
signals formatted as edn, JSON, or human-readable strings. signals as human or machine-readable (edn, JSON) strings.
Options: Options:
`:output-fn` - (fn [signal]) => output string, see `format-signal-fn` or `pr-signal-fn`" `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`"
([] (handler:console nil)) ([] (handler:console nil))
([{:keys [output-fn] ([{:keys [output-fn]
@ -83,21 +83,24 @@
#?(:cljs #?(:cljs
(defn ^:public handler:console-raw (defn ^:public handler:console-raw
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
If `js/console` exists, returns a (fn handler [signal]) that: If `js/console` exists, returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Writes raw signal data to JavaScript console. - Writes the raw signal to JavaScript console.
Intended for use with browser formatting tools like `binaryage/devtools`, Intended for use with browser formatting tools like `binaryage/devtools`,
Ref. <https://github.com/binaryage/cljs-devtools>." Ref. <https://github.com/binaryage/cljs-devtools>.
Options:
`:preamble-fn` - (fn [signal]) => string.
`:format-nsecs-fn` - (fn [nanosecs]) => string."
([] (handler:console-raw nil)) ([] (handler:console-raw nil))
([{:keys [preamble-fn format-nsecs-fn] :as opts ([{:keys [preamble-fn format-nsecs-fn] :as opts
:or :or
{preamble-fn (utils/signal-preamble-fn) {preamble-fn (utils/signal-preamble-fn)
format-nsecs-fn (utils/format-nsecs-fn) ; (fn [nanosecs]) format-nsecs-fn (utils/format-nsecs-fn)}}]
}}]
(when (and (exists? js/console) (exists? js/console.group)) (when (and (exists? js/console) (exists? js/console.group))
(let [js-console-logger utils/js-console-logger (let [js-console-logger utils/js-console-logger

View file

@ -266,17 +266,18 @@
;;;; Handler ;;;; Handler
(defn ^:public handler:file (defn ^:public handler:file
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Writes formatted signal string to file. - Writes (appends) the signal as a string to file specified by `path`.
Signals will be appended to file specified by `path`.
Depending on options, archives may be maintained: Depending on options, archives may be maintained:
- `logs/app.log.n.gz` (for nil `:interval`, non-nil `:max-file-size`) - `logs/app.log.n.gz` (for nil `:interval`, non-nil `:max-file-size`)
- `logs/app.log-YYYY-MM-DDd.n.gz` (for non-nil `:interval`) ; d=daily/w=weekly/m=monthly - `logs/app.log-YYYY-MM-DDd.n.gz` (for non-nil `:interval`) ; d=daily/w=weekly/m=monthly
Can output signals as human or machine-readable (edn, JSON) strings.
Example files with default options: Example files with default options:
`/logs/telemere.log` ; Current file `/logs/telemere.log` ; Current file
`/logs/telemere.log-2020-01-01m.1.gz` ; Archive for Jan 2020, part 1 (newest entries) `/logs/telemere.log-2020-01-01m.1.gz` ; Archive for Jan 2020, part 1 (newest entries)
@ -284,7 +285,7 @@
`/logs/telemere.log-2020-01-01m.8.gz` ; Archive for Jan 2020, part 8 (oldest entries) `/logs/telemere.log-2020-01-01m.8.gz` ; Archive for Jan 2020, part 8 (oldest entries)
Options: Options:
`:output-fn`- (fn [signal]) => output string, see `format-signal-fn` or `pr-signal-fn` `:output-fn`- (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
`:path` - Path string of the target output file (default `logs/telemere.log`) `:path` - Path string of the target output file (default `logs/telemere.log`)
`:interval` - #{nil :daily :weekly :monthly} (default `:monthly`) `:interval` - #{nil :daily :weekly :monthly} (default `:monthly`)

View file

@ -263,7 +263,7 @@
(enc/defonce ^:dynamic *sig-handlers* "?[<wrapped-handler-fn>]" nil) (enc/defonce ^:dynamic *sig-handlers* "?[<wrapped-handler-fn>]" nil)
(defn force-msg-in-sig [sig] (defn force-msg-in-sig [sig]
(if-not (map? sig) (if-not (map? sig)
sig sig
(if-let [e (find sig :msg_)] (if-let [e (find sig :msg_)]
(assoc sig :msg_ (force (val e))) (assoc sig :msg_ (force (val e)))
@ -276,11 +276,11 @@
Useful for tests/debugging. Useful for tests/debugging.
Options: Options:
`trap-signals?` (default: false) `trap-signals?` (default false)
Should ALL signals created by form be trapped to prevent normal dispatch Should ALL signals created by form be trapped to prevent normal dispatch
to registered handlers? to registered handlers?
`raw-msg?` (default: false) `raw-msg?` (default false)
Should delayed `:msg_` in returned signal be retained as-is? Should delayed `:msg_` in returned signal be retained as-is?
Delay is otherwise replaced by realized string. Delay is otherwise replaced by realized string.

View file

@ -191,9 +191,9 @@
Ref. <https://github.com/open-telemetry/opentelemetry-java>. Ref. <https://github.com/open-telemetry/opentelemetry-java>.
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Emits signal content to the `io.opentelemetry.api.logs.Logger` - Emits the signal to `io.opentelemetry.api.logs.Logger` returned
returned by given `io.opentelemetry.api.logs.LoggerProvider`. by given `io.opentelemetry.api.logs.LoggerProvider`.
Options: Options:
`:logger-provider` - `io.opentelemetry.api.logs.LoggerProvider` `:logger-provider` - `io.opentelemetry.api.logs.LoggerProvider`

View file

@ -16,8 +16,8 @@
(defn signal-subject-fn (defn signal-subject-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn format [signal]) that: Returns a (fn format [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Returns a formatted email subject like: - Returns an email subject string like:
\"INFO EVENT :taoensso.telemere.postal/ev-id1 - msg\"" \"INFO EVENT :taoensso.telemere.postal/ev-id1 - msg\""
([] (signal-subject-fn nil)) ([] (signal-subject-fn nil))
([{:keys [max-len subject-signal-key] ([{:keys [max-len subject-signal-key]
@ -46,14 +46,13 @@
;;;; Handler ;;;; Handler
(defn handler:postal (defn handler:postal
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Needs `postal`, Needs `postal`, Ref. <https://github.com/drewr/postal>.
Ref. <https://github.com/drewr/postal>.
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Sends formatted signal string as email to specified recipient. - Sends the signal as an email to specified recipient.
Useful for emailing important alerts to admins, etc. Useful for emailing important alerts to admins, etc.
@ -61,15 +60,14 @@
See tips section re: protecting against unexpected costs. See tips section re: protecting against unexpected costs.
Options: Options:
`:postal/conn-opts` - Map of connection opts given to `postal/send-message`
`:postal/conn-opts` - Map of connection opts provided to `postal`
Examples: Examples:
{:host \"mail.isp.net\", :user \"jsmith\", :pass \"a-secret\"}, {:host \"mail.isp.net\", :user \"jsmith\", :pass \"a-secret\"},
{:host \"smtp.gmail.com\", :user \"jsmith@gmail.com\", :pass \"a-secret\" :port 587 :tls true}, {:host \"smtp.gmail.com\", :user \"jsmith@gmail.com\", :pass \"a-secret\" :port 587 :tls true},
{:host \"email-smtp.us-east-1.amazonaws.com\", :port 587, :tls true {:host \"email-smtp.us-east-1.amazonaws.com\", :port 587, :tls true
:user \"AKIAIDTP........\" :pass \"AikCFhx1P.......\"} :user \"AKIAIDTP........\" :pass \"AikCFhx1P.......\"}
`:postal/msg-opts` - Map of message options `:postal/msg-opts` - Map of message options given to `postal/send-message`
Examples: Examples:
{:from \"foo@example.com\", :to \"bar@example.com\"}, {:from \"foo@example.com\", :to \"bar@example.com\"},
{:from \"Alice <foo@example.com\", :to \"Bob <bar@example.com>\"}, {:from \"Alice <foo@example.com\", :to \"Bob <bar@example.com>\"},
@ -79,10 +77,10 @@
:X-MyHeader \"A custom header\"} :X-MyHeader \"A custom header\"}
`:subject-fn` - (fn [signal]) => email subject string `:subject-fn` - (fn [signal]) => email subject string
`:body-fn` - (fn [signal]) => email body content string, see `format-signal-fn` or `pr-signal-fn` `:body-fn` - (fn [signal]) => email body content string,
see `format-signal-fn` or `pr-signal-fn`
Tips: Tips:
- Sending emails can incur financial costs! - Sending emails can incur financial costs!
Use appropriate dispatch filtering options when calling `add-handler!` to prevent Use appropriate dispatch filtering options when calling `add-handler!` to prevent
handler from sending unnecessary emails! handler from sending unnecessary emails!
@ -101,7 +99,7 @@
- Ref. <https://github.com/drewr/postal> for more info on `postal` options." - Ref. <https://github.com/drewr/postal> for more info on `postal` options."
([] (handler:postal nil)) ;; ([] (handler:postal nil))
([{:keys ([{:keys
[postal/conn-opts [postal/conn-opts
postal/msg-opts postal/msg-opts
@ -112,8 +110,8 @@
{subject-fn (signal-subject-fn) {subject-fn (signal-subject-fn)
body-fn (utils/format-signal-fn)}}] body-fn (utils/format-signal-fn)}}]
(when-not conn-opts (throw (ex-info "No `:postal/conn-opts` was provided" {}))) (when-not conn-opts (throw (ex-info "No `:postal/conn-opts` was given" {})))
(when-not msg-opts (throw (ex-info "No `:postal/msg-opts` was provided" {}))) (when-not msg-opts (throw (ex-info "No `:postal/msg-opts` was given" {})))
(let [] (let []
(defn a-handler:postal (defn a-handler:postal

View file

@ -19,18 +19,20 @@
;;;; Handlers ;;;; Handlers
(defn handler:tcp-socket (defn handler:tcp-socket
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Sends formatted signal string to specified TCP socket. - Sends the signal as a string to specified TCP socket.
Can output signals as human or machine-readable (edn, JSON) strings.
Options: Options:
`host` - Destination TCP socket hostname string `host` - Destination TCP socket hostname string
`port` - Destination TCP socket port int `port` - Destination TCP socket port int
`:socket-opts` - {:keys [ssl? connect-timeout-msecs]} `:socket-opts` - {:keys [ssl? connect-timeout-msecs]}
`:output-fn` - (fn [signal]) => output string, see `format-signal-fn` or `pr-signal-fn` `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
Limitations: Limitations:
- Failed writes will be retried only once. - Failed writes will be retried only once.
@ -53,14 +55,16 @@
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change. Feedback welcome!
Returns a (fn handler [signal]) that: Returns a (fn handler [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Sends formatted signal string to specified UDP socket. - Sends the signal as a string to specified UDP socket.
Can output signals as human or machine-readable (edn, JSON) strings.
Options: Options:
`host` - Destination UDP socket hostname string `host` - Destination UDP socket hostname string
`port` - Destination UDP socket port int `port` - Destination UDP socket port int
`:output-fn` - (fn [signal]) => output string, see `format-signal-fn` or `pr-signal-fn` `:output-fn` - (fn [signal]) => string, see `format-signal-fn` or `pr-signal-fn`
`:max-packet-bytes` - Max packet size (in bytes) before truncating output (default 512) `:max-packet-bytes` - Max packet size (in bytes) before truncating output (default 512)
`:truncation-warning-fn` - Optional (fn [{:keys [max actual signal]}]) to call whenever `:truncation-warning-fn` - Optional (fn [{:keys [max actual signal]}]) to call whenever
output is truncated. Should be appropriately rate-limited! output is truncated. Should be appropriately rate-limited!

View file

@ -127,7 +127,7 @@
(comment (error-in-signal->maps {:level :info :error (ex-info "Ex" {})})) (comment (error-in-signal->maps {:level :info :error (ex-info "Ex" {})}))
(defn remove-kvs (defn remove-kvs
"Returns the given signal without user-level kvs." "Returns given signal without user-level kvs."
[signal] [signal]
(if-let [kvs (get signal :kvs)] (if-let [kvs (get signal :kvs)]
(reduce-kv (fn [m k _v] (dissoc m k)) (dissoc signal :kvs) kvs) (reduce-kv (fn [m k _v] (dissoc m k)) (dissoc signal :kvs) kvs)
@ -137,7 +137,7 @@
(defn minify-signal (defn minify-signal
"Experimental, subject to change. "Experimental, subject to change.
Returns minimal signal map, removing: Returns minimal signal, removing:
- Keys with nil values, and - Keys with nil values, and
- Keys with redundant values (`:kvs`, `:location`, `:file`). - Keys with redundant values (`:kvs`, `:location`, `:file`).
@ -186,14 +186,13 @@
#?(:clj #?(:clj
(defn ^:no-doc file-stream (defn ^:no-doc file-stream
"Private, don't use. "Private, don't use.
Returns a new `java.io.FileOutputStream` for given `java.io.File`, etc." Returns new `java.io.FileOutputStream` for given `java.io.File`."
^java.io.FileOutputStream [file append?] ^java.io.FileOutputStream [file append?]
(java.io.FileOutputStream. (as-file file) (boolean append?)))) (java.io.FileOutputStream. (as-file file) (boolean append?))))
#?(:clj #?(:clj
(defn file-writer (defn file-writer
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Opens the specified file and returns a stateful fn of 2 arities: Opens the specified file and returns a stateful fn of 2 arities:
[content] => Writes given content to file, or no-ops if closed. [content] => Writes given content to file, or no-ops if closed.
[] => Closes the writer. [] => Closes the writer.
@ -286,27 +285,26 @@
#?(:clj #?(:clj
(defn tcp-socket-writer (defn tcp-socket-writer
"Experimental, subject to change. Feedback welcome! "Experimental, subject to change.
Connects to specified TCP socket and returns a stateful fn of 2 arities:
[content] => Writes given content to socket, or no-ops if closed.
[] => Closes the writer.
Connects to specified TCP socket and returns a stateful fn of 2 arities: Useful for basic handlers that write to a TCP socket, etc.
[content] => Writes given content to socket, or no-ops if closed.
[] => Closes the writer.
Useful for basic handlers that write to a TCP socket, etc. Options:
`:ssl?` - Use SSL/TLS?
`:connect-timeout-msecs` - Connection timeout (default 3000 msecs)
`:socket-fn` - (fn [host port timeout]) => `java.net.Socket`
`:ssl-socket-fn` - (fn [socket host port]) => `java.net.Socket`
Options: Notes:
`:ssl?` - Use SSL/TLS? - Writer should be manually closed after use (with zero-arity call).
`:connect-timeout-msecs` - Connection timeout (default 3000 msecs) - Flushes after every write.
`:socket-fn` - (fn [host port timeout]) => `java.net.Socket` - Will retry failed writes once, then drop.
`:ssl-socket-fn` - (fn [socket host port]) => `java.net.Socket` - Thread safe, locks on single socket stream.
- Advanced users may want a custom implementation using a connection
Notes: pool and/or more sophisticated retry semantics, etc."
- Writer should be manually closed after use (with zero-arity call).
- Flushes after every write.
- Will retry failed writes once, then drop.
- Thread safe, locks on single socket stream.
- Advanced users may want a custom implementation using a connection
pool and/or more sophisticated retry semantics, etc."
[host port [host port
{:keys {:keys
@ -394,7 +392,7 @@
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn format [nanosecs]) that: Returns a (fn format [nanosecs]) that:
- Takes a long nanoseconds (e.g. runtime). - Takes a long nanoseconds (e.g. runtime).
- Returns a formatted human-readable string like: - Returns a human-readable string like:
\"1.00m\", \"4.20s\", \"340ms\", \"822μs\", etc." \"1.00m\", \"4.20s\", \"340ms\", \"822μs\", etc."
([] (format-nsecs-fn nil)) ([] (format-nsecs-fn nil))
([{:as _opts}] (fn format-nsecs [nanosecs] (enc/format-nsecs nanosecs)))) ([{:as _opts}] (fn format-nsecs [nanosecs] (enc/format-nsecs nanosecs))))
@ -421,7 +419,7 @@
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn format [error]) that: Returns a (fn format [error]) that:
- Takes a platform error (`Throwable` or `js/Error`). - Takes a platform error (`Throwable` or `js/Error`).
- Returns a formatted human-readable string" - Returns a human-readable error string."
([] (format-error-fn nil)) ([] (format-error-fn nil))
([{:as _opts}] ([{:as _opts}]
(let [nl enc/newline (let [nl enc/newline
@ -457,11 +455,12 @@
(defn signal-preamble-fn (defn signal-preamble-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn preamble [signal]) that: Returns a (fn preamble [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Returns a signal preamble ?string like: - Returns a signal preamble ?string like:
\"2024-03-26T11:14:51.806Z INFO EVENT Hostname taoensso.telemere(2,21) ::ev-id - msg\" \"2024-03-26T11:14:51.806Z INFO EVENT Hostname taoensso.telemere(2,21) ::ev-id - msg\"
See arglists for options." Options:
`:format-inst-fn` - (fn format [instant]) => string."
([] (signal-preamble-fn nil)) ([] (signal-preamble-fn nil))
([{:keys [format-inst-fn] ([{:keys [format-inst-fn]
:or {format-inst-fn (format-inst-fn)}}] :or {format-inst-fn (format-inst-fn)}}]
@ -477,7 +476,7 @@
(if kind (s+spc (upper-qn kind)) (s+spc "DEFAULT")) (if kind (s+spc (upper-qn kind)) (s+spc "DEFAULT"))
#?(:clj (s+spc (hostname))) #?(:clj (s+spc (hostname)))
;; "<ns>:(<line>,<column>)" ;; "<ns>(<line>,<column>)"
(when-let [base (or ns (get signal :file))] (when-let [base (or ns (get signal :file))]
(let [s+ (partial enc/sb-append sb)] ; Without separator (let [s+ (partial enc/sb-append sb)] ; Without separator
(s+ " " base) (s+ " " base)
@ -497,10 +496,16 @@
(defn signal-content-fn (defn signal-content-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn content [signal]) that: Returns a (fn content [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Returns a signal content ?string (incl. data, ctx, etc.) - Returns a signal content ?string (incl. data, ctx, etc.).
Options:
`:incl-thread?` - Include signal `:thread` info? (default false)
`:incl-kvs?` - Include signal `:kvs` info? (default false)
`:raw-error?` - Retain unformatted error? (default false)
`:format-nsecs-fn` - (fn [nanosecs]) => string.
`:format-error-fn` - (fn [error]) => string."
See arglists for options."
([] (signal-content-fn nil)) ([] (signal-content-fn nil))
([{:keys ([{:keys
[incl-thread? incl-kvs? raw-error?, [incl-thread? incl-kvs? raw-error?,
@ -566,13 +571,15 @@
(defn pr-signal-fn (defn pr-signal-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn pr-signal [signal]) that: Returns a (fn pr [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Returns machine-readable serialized string of the (minified) signal. - Returns a machine-readable (minified) signal string.
Options include: Options:
`pr-fn` ∈ #{<unary-fn> :edn :json (Cljs only)} `pr-fn` - ∈ #{<unary-fn> :edn :json (Cljs only)}
See arglists for more. `:incl-thread?` - Include signal `:thread` info? (default false)
`:incl-kvs?` - Include signal `:kvs` info? (default false)
`:incl-newline?` - Include terminating system newline? (default true)
Examples: Examples:
(pr-signal-fn :edn {<opts>}) (pr-signal-fn :edn {<opts>})
@ -627,8 +634,13 @@
(defn format-signal-fn (defn format-signal-fn
"Experimental, subject to change. "Experimental, subject to change.
Returns a (fn format [signal]) that: Returns a (fn format [signal]) that:
- Takes a Telemere signal. - Takes a Telemere signal (map).
- Returns human-readable formatted string. - Returns a human-readable signal string.
Options:
`:incl-newline?` - Include terminating system newline? (default true)
`:preamble-fn` - (fn [signal]) => signal preamble string.
`:content-fn` - (fn [signal]) => signal content string.
See also `pr-signal-fn` for machine-readable output." See also `pr-signal-fn` for machine-readable output."
([] (format-signal-fn nil)) ([] (format-signal-fn nil))

View file

@ -153,33 +153,49 @@ 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: "Needs `some-lib`, Ref. <https://github.com/example/some-lib>.
- Takes a Telemere signal.
- Does something with it. Returns a (fn handler [signal] that:
- Takes a Telemere signal (map).
- Does something with the signal.
Options: Options:
`:option1` - Description `:option1` - Option description
`:option2` - Description" `:option2` - Option description
([] (handler:my-handler nil)) ; Use default opts Tips:
- Tip 1
- Tip 2"
([] (handler:my-handler nil)) ; Use default opts (when defaults viable)
([{:as constructor-opts}] ([{:as constructor-opts}]
;; Do option validation and expensive prep *outside* returned handler ;; Do option validation and other prep here, i.e. try to keep expensive work
;; fn whenever possible - i.e. at (one-off) construction time rather than ;; outside handler function when possible.
;; at every handler call.
(let []
(fn a-handler:my-handler ; Note naming convention (let [handler-fn
(fn a-handler:my-handler ; Note naming convention
;; Shutdown arity - called by Telemere exactly once when the handler is ;; Shutdown arity - called by Telemere exactly once when the handler
;; to be shut down. This is your opportunity to finalize/free resources, etc. ;; is to be shut down.
([]) ([]
;; Can no-op, or finalize/free resources as necessary.
)
;; Main arity - called by Telemere whenever the handler should handle the ;; Main arity - called by Telemere whenever the handler should handle
;; given signal. Never called after shutdown. ;; the given signal. Never called after shutdown.
([signal] ([signal]
;; TODO Do something with given signal ;; Do something with given signal (write to console/file/queue/db, etc.).
))))) ;; Return value is ignored.
))
;; (Advanced) optional default handler dispatch opts,
;; see `add-handler!` for full list of possible opts
default-dispatch-opts
{:min-level :info
:rate-limit [[1 (enc/msecs :min 1)]]}]
(with-meta handler-fn default-dispatch-opts))))
``` ```
- See [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) for signal map content. - See [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) for signal map content.