From b7b3a25a821bb06688d6f7a29ca2681d26b0b9ac Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Thu, 19 Jun 2025 18:13:51 +0200 Subject: [PATCH] [doc] Updates for Trove, simplify examples --- README.md | 106 ++++++++++++++---------- SECURITY.md | 2 +- examples.cljc | 45 +++++----- main/resources/docs/signal-creators.txt | 4 +- wiki/1-Getting-started.md | 52 ++++++------ wiki/3-Config.md | 4 +- wiki/4-Handlers.md | 23 ++--- wiki/6-FAQ.md | 10 +-- wiki/7-Tips.md | 2 +- wiki/9-Authors.md | 25 ++++-- 10 files changed, 157 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index e087b4b..4a84562 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,18 @@ It's small, super fast, easy to learn, easy to use, and **absurdly flexible**. +An example call: + +```clojure +(tel/log! {:level :info, :id :auth/login, :data {:user-id 1234}, :msg "User logged in!"}) +``` + Use it alone, or as part of a suite of complementary **observability tools** for modern Clojure/Script applications: - [Telemere](https://www.taoensso.com/telemere) for logging, tracing, and general telemetry - [Tufte](https://www.taoensso.com/tufte) for performance monitoring - [Truss](https://www.taoensso.com/truss) for assertions and error handling +- [Trove](https://www.taoensso.com/trove) for library authors that want to do structured logging Together these help enable Clojure/Script systems that are **robust**, **fast**, and **easily debugged**. @@ -56,29 +63,30 @@ It enables you to write code that is **information-verbose by default**.
Create signals
```clojure -(require '[taoensso.telemere :as t]) +(require '[taoensso.telemere :as tel]) ;; No config needed for typical use cases!! ;; Signals print to console by default for both Clj and Cljs -;; Without structured data -(t/log! :info "Hello world!") ; %> Basic log signal (has message) -(t/event! ::my-id :debug) ; %> Basic event signal (just id) +;; Traditional style logging (data formatted into message string): +(tel/log! {:level :info, :msg (str "User " 1234 " logged in!")}) -;; With structured data -(t/log! {:level :info, :data {...}} "Hello again!") -(t/event! ::my-id {:level :debug, :data {...}}) +;; Modern/structured style logging (explicit id and data) +(tel/log! {:level :info, :id :auth/login, :data {:user-id 1234}}) + +;; Mixed style (explicit id and data, with message string) +(tel/log! {:level :info, :id :auth/login, :data {:user-id 1234}, :msg "User logged in!"}) ;; Trace (can interop with OpenTelemetry) ;; Tracks form runtime, return value, and (nested) parent tree -(t/trace! {:id ::my-id :data {...}} +(tel/trace! {:id ::my-id :data {...}} (do-some-work)) ;; Check resulting signal content for debug/tests -(t/with-signal (t/event! ::my-id)) ; => {:keys [ns level id data msg_ ...]} +(tel/with-signal (tel/log! {...})) ; => {:keys [ns level id data msg_ ...]} ;; Getting fancy (all costs are conditional!) -(t/log! +(tel/log! {:level :debug :sample 0.75 ; 75% sampling (noop 25% of the time) :when (my-conditional) @@ -106,33 +114,33 @@ It enables you to write code that is **information-verbose by default**. ```clojure ;; Set minimum level -(t/set-min-level! :warn) ; For all signals -(t/set-min-level! :log :debug) ; For `log!` signals only +(tel/set-min-level! :warn) ; For all signals +(tel/set-min-level! :log :debug) ; For `log!` signals specifically ;; Set id and namespace filters -(t/set-id-filter! {:allow #{::my-particular-id "my-app/*"}}) -(t/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"}) +(tel/set-id-filter! {:allow #{::my-particular-id "my-app/*"}}) +(tel/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"}) ;; SLF4J signals will have their `:ns` key set to the logger's name ;; (typically a source class) -(t/set-ns-filter! {:disallow "com.noisy.java.package.*"}) +(tel/set-ns-filter! {:disallow "com.noisy.java.package.*"}) -;; Set minimum level for `event!` signals for particular ns pattern -(t/set-min-level! :event "taoensso.sente.*" :warn) +;; Set minimum level for `log!` signals for particular ns pattern +(tel/set-min-level! :log "taoensso.sente.*" :warn) ;; Use transforms (xfns) to filter and/or arbitrarily modify signals ;; by signal data/content/etc. -(t/set-xfn! +(tel/set-xfn! (fn [signal] (if (-> signal :data :skip-me?) nil ; Filter signal (don't handle) (assoc signal :transformed? true)))) -(t/with-signal (t/event! ::my-id {:data {:skip-me? true}})) ; => nil -(t/with-signal (t/event! ::my-id {:data {:skip-me? false}})) ; => {...} +(tel/with-signal (tel/log! {... :data {:skip-me? true}})) ; => nil +(tel/with-signal (tel/log! {... :data {:skip-me? false}})) ; => {...} -;; See `t/help:filters` docstring for more filtering options +;; See `tel/help:filters` docstring for more filtering options ```
@@ -141,13 +149,13 @@ It enables you to write code that is **information-verbose by default**. ```clojure ;; Add your own signal handler -(t/add-handler! :my-handler +(tel/add-handler! :my-handler (fn ([signal] (println signal)) ([] (println "Handler has shut down")))) ;; Use `add-handler!` to set handler-level filtering and back-pressure -(t/add-handler! :my-handler +(tel/add-handler! :my-handler (fn ([signal] (println signal)) ([] (println "Handler has shut down"))) @@ -158,27 +166,27 @@ It enables you to write code that is **information-verbose by default**. :min-level :info :ns-filter {:disallow "taoensso.*"} :limit {"1 per sec" [1 1000]} - ;; See `t/help:handler-dispatch-options` for more + ;; See `tel/help:handler-dispatch-options` for more }) ;; See current handlers -(t/get-handlers) ; => { {:keys [handler-fn handler-stats_ dispatch-opts]}} +(tel/get-handlers) ; => { {:keys [handler-fn handler-stats_ dispatch-opts]}} ;; Add console handler to print signals as human-readable text -(t/add-handler! :my-handler - (t/handler:console - {:output-fn (t/format-signal-fn {})})) +(tel/add-handler! :my-handler + (tel/handler:console + {:output-fn (tel/format-signal-fn {})})) ;; Add console handler to print signals as edn -(t/add-handler! :my-handler - (t/handler:console - {:output-fn (t/pr-signal-fn {:pr-fn :edn})})) +(tel/add-handler! :my-handler + (tel/handler:console + {:output-fn (tel/pr-signal-fn {:pr-fn :edn})})) ;; Add console handler to print signals as JSON ;; Ref. (or any alt JSON lib) #?(:clj (require '[jsonista.core :as jsonista])) -(t/add-handler! :my-handler - (t/handler:console +(tel/add-handler! :my-handler + (tel/handler:console {:output-fn #?(:cljs :json ; Use js/JSON.stringify :clj jsonista/write-value-as-string)})) @@ -235,19 +243,29 @@ It enables you to write code that is **information-verbose by default**. ## API overview -See relevant docstrings (links below) for usage info- - ### Creating signals -| Name | Kind | Args | Returns | -| :---------------------------------------------------------------------------------------------------------- | :--------- | :--------------- | :--------------------------- | -| [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) | `:log` | `?level` + `msg` | nil | -| [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) | `:event` | `id` + `?level` | nil | -| [`trace!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#trace!) | `:trace` | `?id` + `run` | Form result | -| [`spy!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#spy!) | `:spy` | `?level` + `run` | Form result | -| [`error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#error!) | `:error` | `?id` + `error` | Given error | -| [`catch->error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#catch-%3Eerror!) | `:error` | `?id` | Form value or given fallback | -| [`signal!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#signal!) | `:generic` | `opts` | Depends on opts | +Telemere's signals are all created using the low-level `signal!` macro. You can use that directly, or one of the wrapper macros like `log!`. + +Several different wrapper macros are provided. The only difference between them: + + 1. They create signals with a different `:kind` value (which can be handy for filtering, etc.). + 2. They have different positional arguments and/or return values optimised for concise calling in different use cases. + +**NB:** ALL wrapper macros can also just be called with a single [opts](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) map! + +See the linked docstrings below for more info: + + +| Name | Args | Returns | +| :---------------------------------------------------------------------------------------------------------- | :------------------------- | :--------------------------- | +| [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) | `[opts]` or `[?level msg]` | nil | +| [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) | `[opts]` or `[id ?level]` | nil | +| [`trace!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#trace!) | `[opts]` or `[?id run]` | Form result | +| [`spy!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#spy!) | `[opts]` or `[?level run]` | Form result | +| [`error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#error!) | `[opts]` or `[?id error]` | Given error | +| [`catch->error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#catch-%3Eerror!) | `[opts]` or `[?id error]` | Form value or given fallback | +| [`signal!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#signal!) | `[opts]` | Depends on opts | ### Internal help diff --git a/SECURITY.md b/SECURITY.md index f75c342..f9eea8a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,4 +10,4 @@ Please report possible security vulnerabilities [via GitHub](https://github.com/ Thank you! -\- [Peter Taoussanis](https://www.taoensso.com) +\- [Peter Taoussanis](https://www.taoensso.com) \ No newline at end of file diff --git a/examples.cljc b/examples.cljc index 7115e45..87afecf 100644 --- a/examples.cljc +++ b/examples.cljc @@ -8,23 +8,25 @@ (require '[taoensso.telemere :as tel]) -;; (Just works / no config necessary for typical use cases) +;; No config needed for typical use cases!! +;; Signals print to console by default for both Clj and Cljs -;; Without structured data -(tel/log! :info "Hello world!") ; %> Basic log signal (has message) -(tel/event! ::my-id :debug) ; %> Basic event signal (just id) +;; Traditional style logging (data formatted into message string): +(tel/log! {:level :info, :msg (str "User " 1234 " logged in!")}) -;; With structured data -(tel/log! {:level :info, :data {}} "Hello again!") -(tel/event! ::my-id {:level :debug, :data {}}) +;; Modern/structured style logging (explicit id and data) +(tel/log! {:level :info, :id :auth/login, :data {:user-id 1234}}) -;; Trace (auto interops with OpenTelemetry) +;; Mixed style (explicit id and data, with message string) +(tel/log! {:level :info, :id :auth/login, :data {:user-id 1234}, :msg "User logged in!"}) + +;; Trace (can interop with OpenTelemetry) ;; Tracks form runtime, return value, and (nested) parent tree -(tel/trace! {:id ::my-id :data {}} +(tel/trace! {:id ::my-id :data {...}} (do-some-work)) ;; Check resulting signal content for debug/tests -(tel/with-signal (tel/event! ::my-id)) ; => {:keys [ns level id data msg_ ...]} +(tel/with-signal (tel/log! {...})) ; => {:keys [ns level id data msg_ ...]} ;; Getting fancy (all costs are conditional!) (tel/log! @@ -47,20 +49,25 @@ ;; Message string or vector to join as string ["Something interesting happened!" formatted]) +) ;; Set minimum level (tel/set-min-level! :warn) ; For all signals -(tel/set-min-level! :log :debug) ; For `log!` signals only +(tel/set-min-level! :log :debug) ; For `log!` signals specifically -;; Set namespace and id filters -(tel/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"}) +;; Set id and namespace filters (tel/set-id-filter! {:allow #{::my-particular-id "my-app/*"}}) +(tel/set-ns-filter! {:disallow "taoensso.*" :allow "taoensso.sente.*"}) -;; Set minimum level for `event!` signals for particular ns pattern -(tel/set-min-level! :event "taoensso.sente.*" :warn) +;; SLF4J signals will have their `:ns` key set to the logger's name +;; (typically a source class) +(tel/set-ns-filter! {:disallow "com.noisy.java.package.*"}) + +;; Set minimum level for `log!` signals for particular ns pattern +(tel/set-min-level! :log "taoensso.sente.*" :warn) ;; Use transforms (xfns) to filter and/or arbitrarily modify signals -;; by signal data/contentel/etc. +;; by signal data/content/etc. (tel/set-xfn! (fn [signal] @@ -68,13 +75,11 @@ nil ; Filter signal (don't handle) (assoc signal :transformed? true)))) -(tel/with-signal (tel/event! ::my-id {:data {:skip-me? true}})) ; => nil -(tel/with-signal (tel/event! ::my-id {:data {:skip-me? false}})) ; => {...} +(tel/with-signal (tel/log! {... :data {:skip-me? true}})) ; => nil +(tel/with-signal (tel/log! {... :data {:skip-me? false}})) ; => {...} ;; See `tel/help:filters` docstring for more filtering options -;;;; README "More examples" - ;; Add your own signal handler (tel/add-handler! :my-handler (fn diff --git a/main/resources/docs/signal-creators.txt b/main/resources/docs/signal-creators.txt index 99ed5c5..cfc0093 100644 --- a/main/resources/docs/signal-creators.txt +++ b/main/resources/docs/signal-creators.txt @@ -11,8 +11,8 @@ various keys: - All signal creators offer the same options [2], and - All signal kinds can contain the same content [3] -Creators vary only in in their default options and call APIs (expected args -and return values), making them more/less convenient for certain use cases: +Creators vary only in in their default `:kind` value and call APIs (expected +args and return values), making them more/less convenient for certain use cases: `log!` ------------- ?level + msg => nil `event!` ----------- id + ?level => nil diff --git a/wiki/1-Getting-started.md b/wiki/1-Getting-started.md index d855a8d..6567be5 100644 --- a/wiki/1-Getting-started.md +++ b/wiki/1-Getting-started.md @@ -83,7 +83,7 @@ deps.edn: com.taoensso/telemere {:mvn/version "x-y-z"} And setup your namespace imports: ```clojure -(ns my-app (:require [taoensso.telemere :as t])) +(ns my-app (:require [taoensso.telemere :as tel])) ``` # Default config @@ -127,30 +127,34 @@ Interop can be tough to get configured correctly so the [`check-interop`](https: ## Creating signals -Use whichever signal creator is most convenient for your needs: +Telemere's signals are all created using the low-level `signal!` macro. You can use that directly, or one of the wrapper macros like `log!`. -| Name | Kind | Args | Returns | -| :---------------------------------------------------------------------------------------------------------- | :--------- | :--------------- | :--------------------------- | -| [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) | `:log` | `?level` + `msg` | nil | -| [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) | `:event` | `id` + `?level` | nil | -| [`trace!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#trace!) | `:trace` | `?id` + `run` | Form result | -| [`spy!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#spy!) | `:spy` | `?level` + `run` | Form result | -| [`error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#error!) | `:error` | `?id` + `error` | Given error | -| [`catch->error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#catch-%3Eerror!) | `:error` | `?id` | Form value or given fallback | -| [`signal!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#signal!) | `:generic` | `opts` | Depends on opts | - -- See relevant docstrings (links above) for usage info. -- See [`help:signal-creators`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-creators) for more about signal creators. -- See [`help:signal-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) for options shared by all signal creators. -- See [examples.cljc](https://github.com/taoensso/telemere/blob/master/examples.cljc) for REPL-ready examples. +Several different wrapper macros are provided. The only difference between them: + + 1. They create signals with a different `:kind` value (which can be handy for filtering, etc.). + 2. They have different positional arguments and/or return values optimised for concise calling in different use cases. + +**NB:** ALL wrapper macros can also just be called with a single [opts](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) map! + +See the linked docstrings below for more info: + +| Name | Args | Returns | +| :---------------------------------------------------------------------------------------------------------- | :------------------------- | :--------------------------- | +| [`log!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#log!) | `[opts]` or `[?level msg]` | nil | +| [`event!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#event!) | `[opts]` or `[id ?level]` | nil | +| [`trace!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#trace!) | `[opts]` or `[?id run]` | Form result | +| [`spy!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#spy!) | `[opts]` or `[?level run]` | Form result | +| [`error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#error!) | `[opts]` or `[?id error]` | Given error | +| [`catch->error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#catch-%3Eerror!) | `[opts]` or `[?id error]` | Form value or given fallback | +| [`signal!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#signal!) | `[opts]` | Depends on opts | ## Checking signals Use the [`with-signal`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#with-signal) or (advanced) [`with-signals`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#with-signals) utils to help test/debug the signals that you're creating: ```clojure -(t/with-signal - (t/log! +(tel/with-signal + (tel/log! {:let [x "x"] :data {:x x}} ["My msg:" x])) @@ -185,15 +189,15 @@ A signal will be provided to a handler iff **ALL** of the following are true: Quick examples of some basic filtering: ```clojure -(t/set-min-level! :info) ; Set global minimum level -(t/with-signal (t/event! ::my-id1 :info)) ; => {:keys [inst id ...]} -(t/with-signal (t/event! ::my-id1 :debug)) ; => nil (signal not allowed) +(tel/set-min-level! :info) ; Set global minimum level +(tel/with-signal (tel/log! {:level :info ...})) ; => {:keys [inst id ...]} +(tel/with-signal (tel/log! {:level :debug ...})) ; => nil (signal not allowed) -(t/with-min-level :trace ; Override global minimum level - (t/with-signal (t/event! ::my-id1 :debug))) ; => {:keys [inst id ...]} +(tel/with-min-level :trace ; Override global minimum level + (tel/with-signal (tel/log! {:level :debug ...})) ; => {:keys [inst id ...]} ;; Disallow all signals in matching namespaces -(t/set-ns-filter! {:disallow "some.nosy.namespace.*"}) +(tel/set-ns-filter! {:disallow "some.nosy.namespace.*"}) ``` - Filtering is always O(1), except for rate limits which are O(n_windows). diff --git a/wiki/3-Config.md b/wiki/3-Config.md index 4238dfd..6f20910 100644 --- a/wiki/3-Config.md +++ b/wiki/3-Config.md @@ -132,7 +132,7 @@ Telemere can easily incorporate Tufte performance data in its signals, just like ```clojure (let [[_ perf-data] (tufte/profiled
)] - (t/log! {:perf-data perf-data} "Performance data")) + (tel/log! {:perf-data perf-data} "Performance data")) ``` Telemere and Tufte work great together: @@ -149,7 +149,7 @@ Telemere can easily incorporate Truss assertion failure information in its signa The [`catch->error!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#catch-%3Eerror!) signal creator can be particularly convenient for this: ```clojure -(t/catch->error! ) +(tel/catch->error! ) ``` Telemere also uses [Truss contextual exceptions](https://cljdoc.org/d/com.taoensso/truss/CURRENT/api/taoensso.truss#ex-info) when relevant. \ No newline at end of file diff --git a/wiki/4-Handlers.md b/wiki/4-Handlers.md index 9c09cab..98cb09f 100644 --- a/wiki/4-Handlers.md +++ b/wiki/4-Handlers.md @@ -71,11 +71,11 @@ By default it writes formatted strings intended for human consumption: ```clojure ;; Create a test signal (def my-signal - (t/with-signal - (t/log! {:id ::my-id, :data {:x1 :x2}} "My message"))) + (tel/with-signal + (tel/log! {:id ::my-id, :data {:x1 :x2}} "My message"))) ;; Create console handler with default opts (writes formatted string) -(def my-handler (t/handler:console {})) +(def my-handler (tel/handler:console {})) ;; Test handler, remember it's just a (fn [signal]) (my-handler my-signal) ; %> @@ -90,8 +90,8 @@ To instead writes signals as [edn](https://github.com/edn-format/edn): ```clojure ;; Create console handler which writes signals as edn (def my-handler - (t/handler:console - {:output-fn (t/pr-signal-fn {:pr-fn :edn})})) + (tel/handler:console + {:output-fn (tel/pr-signal-fn {:pr-fn :edn})})) (my-handler my-signal) ; %> ;; {:inst #inst "2024-04-11T10:54:57.202869Z", :msg_ "My message", :ns "examples", ...} @@ -105,9 +105,9 @@ To instead writes signals as JSON: ;; Ref. (or any alt JSON lib) #?(:clj (require '[jsonista.core :as jsonista])) (def my-handler - (t/handler:console + (tel/handler:console {:output-fn - (t/pr-signal-fn + (tel/pr-signal-fn {:pr-fn #?(:cljs :json ; Use js/JSON.stringify :clj jsonista/write-value-as-string)})})) @@ -125,9 +125,10 @@ Telemere includes a handy mechanism for including arbitrary app-level data/opts Any *non-standard* (app-level) keys you include in your signal constructor opts will automatically be included in created signals, e.g.: ```clojure -(t/with-signal - (t/event! ::my-id - {:my-data-for-xfn "foo" +(tel/with-signal + (tel/log! + {... + :my-data-for-xfn "foo" :my-data-for-handler "bar"})) ;; %> @@ -250,7 +251,7 @@ If you're making a customizable handler for use by others, it's often handy to d # Example output ```clojure -(t/log! {:id ::my-id, :data {:x1 :x2}} "My message") => +(tel/log! {:id ::my-id, :data {:x1 :x2}} "My message") => ``` ## Clj console handler diff --git a/wiki/6-FAQ.md b/wiki/6-FAQ.md index 07dbb00..0b2036d 100644 --- a/wiki/6-FAQ.md +++ b/wiki/6-FAQ.md @@ -76,18 +76,18 @@ Examples: ```clojure ;; A fixed message (string arg) -(t/log! "A fixed message") ; %> {:msg "A fixed message"} +(tel/log! "A fixed message") ; %> {:msg "A fixed message"} ;; A joined message (vector arg) (let [user-arg "Bob"] - (t/log! ["User" (str "`" user-arg "`") "just logged in!"])) + (tel/log! ["User" (str "`" user-arg "`") "just logged in!"])) ;; %> {:msg_ "User `Bob` just logged in!` ...} ;; With arg prep (let [user-arg "Bob" usd-balance-str "22.4821"] - (t/log! + (tel/log! {:let [username (clojure.string/upper-case user-arg) usd-balance (parse-double usd-balance-str)] @@ -100,10 +100,10 @@ Examples: ;; %> {:msg "User BOB has balance: $22" ...} -(t/log! (str "This message " "was built " "by `str`")) +(tel/log! (str "This message " "was built " "by `str`")) ;; %> {:msg "This message was built by `str`"} -(t/log! (format "This message was built by `%s`" "format")) +(tel/log! (format "This message was built by `%s`" "format")) ;; %> {:msg "This message was built by `format`"} ``` diff --git a/wiki/7-Tips.md b/wiki/7-Tips.md index f114854..17d3d49 100644 --- a/wiki/7-Tips.md +++ b/wiki/7-Tips.md @@ -114,7 +114,7 @@ Consider the [differences](https://www.youtube.com/watch?v=oyLBGkS5ICk) between Any non-standard [options](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) you give to a signal creator call will be added to the signal it creates: ```clojure - (t/with-signal (t/log! {:my-key "foo"} "My message"))) + (tel/with-signal (tel/log! {:my-key "foo"} "My message"))) ;; => {:my-key "foo", :kvs {:my-key "foo", ...}, ...} ``` diff --git a/wiki/9-Authors.md b/wiki/9-Authors.md index 831f874..a77a21b 100644 --- a/wiki/9-Authors.md +++ b/wiki/9-Authors.md @@ -1,17 +1,30 @@ Are you a library author/maintainer that's considering **using Telemere in your library**? -You have **two options** below- +You have **a few options** below- # Options -## 1. Common logging facade (basic logging only) -Many libraries need only basic logging. In these cases it can be beneficial to do your logging through a common logging facade like [tools.logging](https://github.com/clojure/tools.logging) or [SLF4J](https://www.slf4j.org/). +## Modern logging facade -This'll limit you to basic features (e.g. no structured logging or [rich filtering](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#get-filters)) - but your users will have the freedom to choose and configure their **preferred backend** ([incl. Telemere if they like](./3-Config#interop)). +[Trove](https://www.taoensso.com/trove) is a minimal, modern alternative to [tools.logging](https://github.com/clojure/tools.logging) that supports all of Telemere's structured logging and rich filtering features. -## 2. Telemere as a transitive dependency +Basically: -Include [Telemere](https://clojars.org/com.taoensso/telemere) in your **library's dependencies**. Your library (and users) will then have access to the full Telemere API. +1. You include the (very small) Trove dependency with your library +2. Your library logs using the [Trove API](https://github.com/taoensso/trove#to-choose-a-backend) +3. Your users then [choose](https://github.com/taoensso/trove#to-choose-a-backend) their preferred backend (Telemere, etc.) + +This would be my first recommendation, and is what I'm planning to use for future updates to [Sente](https://www.taoensso.com/sente), [Carmine](https://www.taoensso.com/carmine), etc. + +## Traditional logging facade (basic logging only) + +Many libraries need only basic logging. In these cases it can be beneficial to do your logging through a common traditional logging facade like [tools.logging](https://github.com/clojure/tools.logging) or [SLF4J](https://www.slf4j.org/). + +Though these'll limit you to basic features (e.g. no structured logging or [rich filtering](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#get-filters)). + +## Telemere as a transitive dependency + +You could just include [Telemere](https://clojars.org/com.taoensso/telemere) in your **library's dependencies**. Your library (and users) will then have access to the full Telemere API. Telemere's [default config](./1-Getting-started#default-config) is sensible (with println-like console output), so your users are unlikely to need to configure or interact with Telemere much unless they choose to.