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