[mod] Fix AOT support, don't alias conditional vars

This commit is contained in:
Peter Taoussanis 2024-04-23 11:25:15 +02:00
parent 3fe58d35c1
commit 9ccb815dd9
12 changed files with 186 additions and 153 deletions

View file

@ -29,10 +29,12 @@
[[org.clojure/clojure "1.11.2"]
[com.github.clj-easy/graal-build-time "1.0.5"]]}
:test {:aot [taoensso.telemere-tests]}
:dev
{:jvm-opts
["-server"
"-Dtaoensso.elide-deprecated=true"
"-Dtaoensso.telemere.auto-handlers=false"
"-Dclojure.tools.logging-to-telemere?=true"]
:global-vars

View file

@ -1,6 +1,6 @@
(ns ^:no-doc taoensso.telemere.slf4j
"Private ns, implementation detail.
Intake support: SLF4J -> Telemere.
(ns taoensso.telemere.slf4j
"Intake support for SLF4J -> Telemere.
Telemere will attempt to load this ns automatically when possible.
To use Telemere as your SLF4J backend/provider, just include the
`com.taoensso/slf4j-telemere` dependency on your classpath.
@ -18,7 +18,11 @@
(:require
[taoensso.encore :as enc :refer [have have?]]
[taoensso.telemere.impl :as impl]))
[taoensso.telemere.impl :as impl])
(:import
[org.slf4j Logger]
[com.taoensso.telemere.slf4j TelemereLogger]))
;;;; Utils
@ -40,10 +44,10 @@
(comment (enc/qb 1e6 (sig-level org.slf4j.event.Level/INFO))) ; 36.47
(defn get-marker "Private util for tests, etc."
(defn- get-marker "Private util for tests, etc."
^org.slf4j.Marker [n] (org.slf4j.MarkerFactory/getMarker n))
(defn est-marker!
(defn- est-marker!
"Private util for tests, etc.
Globally establishes (compound) `org.slf4j.Marker` with name `n` and mutates it
(all occurences!) to have exactly the given references. Returns the (compound) marker."
@ -55,7 +59,7 @@
(comment [(est-marker! "a1" "a2") (get-marker "a1") (= (get-marker "a1") (get-marker "a1"))])
(def marker-names
(def ^:private marker-names
"Returns #{<MarkerName>}. Cached => assumes markers NOT modified after creation."
;; We use `BasicMarkerFactory` so:
;; 1. Our markers are just labels (no other content besides their name).
@ -95,7 +99,7 @@
;;;; Intake fns (called by `TelemereLogger`)
(defn allowed?
(defn- allowed?
"Private, don't use.
Called by `com.taoensso.telemere.slf4j.TelemereLogger`."
[^org.slf4j.event.Level level]
@ -134,7 +138,7 @@
:slf4j/kvs kvs)})
nil)
(defn log!
(defn- log!
"Private, don't use.
Called by `com.taoensso.telemere.slf4j.TelemereLogger`."
@ -172,15 +176,27 @@
(org.slf4j.MDC/getCopyOfContextMap)
(org.slf4j.MDC/clear)))
(impl/add-intake-check! :slf4j
(fn []
(let [^org.slf4j.Logger sl
(org.slf4j.LoggerFactory/getLogger "IntakeTestTelemereLogger")
sending? (instance? com.taoensso.telemere.slf4j.TelemereLogger sl)
receiving?
(and sending?
(impl/test-intake! "SLF4J -> Telemere" #(.info sl %)))]
;;;;
{:present? true
:sending->telemere? sending?
:telemere-receiving? receiving?})))
(defn check-intake
"Returns {:keys [present? sending->telemere? telemere-receiving?]}."
[]
(let [^org.slf4j.Logger sl
(org.slf4j.LoggerFactory/getLogger "IntakeTestTelemereLogger")
sending? (instance? com.taoensso.telemere.slf4j.TelemereLogger sl)
receiving?
(and sending?
(impl/test-intake! "SLF4J -> Telemere" #(.info sl %)))]
{:present? true
:sending->telemere? sending?
:telemere-receiving? receiving?}))
(impl/add-intake-check! :slf4j check-intake)
(impl/on-init
(impl/signal!
{:kind :event
:level :info
:id :taoensso.telemere/slf4j->telemere!
:msg "Enabling intake: SLF4J -> Telemere"}))

View file

@ -372,25 +372,6 @@
streams/streams->telemere!
streams/streams->reset!))
#?(:clj
(enc/compile-when
(do (require '[taoensso.telemere.tools-logging :as ttl]) true)
(enc/defalias ttl/tools-logging->telemere!) ; Incl. `get-env` docs
(when (enc/get-env {:as :bool} :clojure.tools.logging-to-telemere?)
(ttl/tools-logging->telemere!))))
#?(:clj
(enc/compile-when
(and org.slf4j.Logger com.taoensso.telemere.slf4j.TelemereLogger)
(impl/signal!
{:kind :event
:level :info
:id :taoensso.telemere/slf4j->telemere!
:msg "Enabling intake: SLF4J -> Telemere"})
(require '[taoensso.telemere.slf4j :as slf4j])))
(comment (check-intakes))
;;;; Handlers
@ -400,20 +381,6 @@
#?(:cljs handlers:console/handler:console-raw)
#?(:clj handlers:file/handler:file))
#?(:clj
(enc/compile-when
(do (require '[taoensso.telemere.handlers.open-telemetry :as handlers:open-tel]) true)
(enc/defalias handlers:open-tel/handler:open-telemetry-logger)))
(defonce ^:no-doc __add-default-handlers
(do
(add-handler! :default/console (handler:console))
#?(:clj
(enc/compile-when handler:open-telemetry-logger
(when-let [handler (enc/catching (handler:open-telemetry-logger))]
(add-handler! :default/open-telemetry-logger handler))))
nil))
;;;; Flow benchmarks
(comment
@ -447,6 +414,16 @@
;;;;
(impl/on-init
(when impl/auto-handlers?
(add-handler! :default/console (handler:console)))
#?(:clj (enc/catching (require '[taoensso.telemere.tools-logging])))
#?(:clj (enc/catching (require '[taoensso.telemere.slf4j])))
#?(:clj (enc/catching (require '[taoensso.telemere.handlers.open-telemetry]))))
;;;;
(comment
(with-handler :hid1 (handlers/console-handler) {} (log! "Message"))
@ -461,5 +438,3 @@
(do (let [hf (handlers/file-handler)] (hf sig) (hf)))
(do (let [hf (handlers/console-handler)] (hf sig) (hf)))
#?(:cljs (let [hf (handlers/raw-console-handler)] (hf sig) (hf)))))
;;;;

View file

@ -1,6 +1,6 @@
(ns ^:no-doc taoensso.telemere.handlers.open-telemetry
"Private ns, implementation detail.
Core OpenTelemetry handlers.
(ns taoensso.telemere.handlers.open-telemetry
"Core OpenTelemetry handler and utils.
Telemere will attempt to load this ns automatically when possible.
Needs `OpenTelemetry Java`,
Ref. <https://github.com/open-telemetry/opentelemetry-java>."
@ -8,7 +8,9 @@
(:require
[clojure.string :as str]
[taoensso.encore :as enc :refer [have have?]]
[taoensso.telemere.utils :as utils])
[taoensso.telemere.utils :as utils]
[taoensso.telemere.impl :as impl]
[taoensso.telemere :as tel])
(:import
[io.opentelemetry.api.logs LoggerProvider Severity]
@ -21,7 +23,7 @@
;;;; Implementation
(defn level->severity
(defn- level->severity
^Severity [level]
(case level
:trace Severity/TRACE
@ -33,7 +35,7 @@
:report Severity/INFO4
Severity/UNDEFINED_SEVERITY_NUMBER))
(def ^String attr-name
(def ^:private ^String attr-name
"Returns cached OpenTelemetry-style name: `:foo/bar-baz` -> \"foo_bar_baz\", etc.
Ref. <https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/>."
(enc/fmemoize
@ -49,7 +51,7 @@
(comment (enc/qb 1e6 (attr-name :x1.x2/x3-x4 :Foo/Bar-BAZ))) ; 63.6
;; AttributeTypes: String, Long, Double, Boolean, and arrays
(defprotocol IAttr+ (attr+ [_aval akey builder]))
(defprotocol IAttr+ (^:private attr+ [_aval akey builder]))
(extend-protocol IAttr+
nil (attr+ [v k ^AttributesBuilder b] (.put b (attr-name k) "nil")) ; Like pr-edn*
Boolean (attr+ [v k ^AttributesBuilder b] (.put b (attr-name k) v))
@ -78,7 +80,7 @@
Object (attr+ [v k ^AttributesBuilder b] (.put b (attr-name k) (enc/pr-edn* v))))
(defn as-attrs
(defn- as-attrs
"Returns `io.opentelemetry.api.common.Attributes` for given map."
^Attributes [m]
(if (empty? m)
@ -89,7 +91,7 @@
(comment (str (as-attrs {:s "s", :kw :foo/bar, :long 5, :double 5.0, :longs [5 5 5] :nil nil})))
(defn merge-prefix-map
(defn- merge-prefix-map
"Merges prefixed `from` into `to`."
[to prefix from]
(enc/cond
@ -103,7 +105,7 @@
(comment (merge-prefix-map {} "data" {:a/b1 "v1" :a/b2 "v2" :nil nil}))
(defn signal->attrs-map
(defn- signal->attrs-map
"Returns attributes map for given signal,
Ref. <https://opentelemetry.io/docs/specs/otel/logs/data-model/>."
[attrs-key signal]
@ -181,7 +183,7 @@
;;;; Handler
(defn ^:public handler:open-telemetry-logger
(defn handler:open-telemetry-logger
"Experimental, subject to change!! Feedback very welcome!
Returns a (fn handler [signal]) that:
@ -216,3 +218,10 @@
(.setSeverity severity)
(.setBody msg)
(.setAllAttributes attrs)))))))))
;;;;
(impl/on-init
(when impl/auto-handlers?
(when-let [handler (enc/catching (handler:open-telemetry-logger))]
(tel/add-handler! :default/open-telemetry-logger handler))))

View file

@ -21,8 +21,18 @@
;;;; Utils
(def auto-handlers? (enc/get-env {:as :bool, :default true} :taoensso.telemere/auto-handlers))
#?(:clj (defmacro threaded [& body] `(let [t# (Thread. (fn [] ~@body))] (.start t#) t#)))
#?(:clj
(defmacro on-init [& body]
(let [sym (with-meta '__on-init {:private true})
compiling? (if (:ns &env) false `*compile-files*)]
`(defonce ~sym (when-not ~compiling? ~@body nil)))))
(comment (macroexpand-1 '(on-init (println "foo"))))
;;;; Config
#?(:clj

View file

@ -1,23 +1,26 @@
(ns ^:no-doc taoensso.telemere.streams
"Private ns, implementation detail.
Intake support: standard stream/s -> Telemere."
(ns taoensso.telemere.streams
"Intake support for standard stream/s -> Telemere."
(:refer-clojure :exclude [binding])
(:require
[taoensso.encore :as enc :refer [binding have have?]]
[taoensso.telemere.impl :as impl]))
(enc/defonce orig-*out* "Original `*out*` on ns load" *out*)
(enc/defonce orig-*err* "Original `*err*` on ns load" *err*)
(enc/defonce ^:dynamic prev-*out* "Previous `*out*` (prior to any Telemere binds)" nil)
(enc/defonce ^:dynamic prev-*err* "Previous `*err*` (prior to any Telemere binds)" nil)
(enc/defonce ^:private orig-*out* "Original `*out*` on ns load" *out*)
(enc/defonce ^:private orig-*err* "Original `*err*` on ns load" *err*)
(enc/defonce ^:no-doc ^:dynamic prev-*out* "Previous `*out*` (prior to any Telemere binds)" nil)
(enc/defonce ^:no-doc ^:dynamic prev-*err* "Previous `*err*` (prior to any Telemere binds)" nil)
(def ^:private ^:const default-out-opts {:kind :system/out, :level :info})
(def ^:private ^:const default-err-opts {:kind :system/err, :level :error})
(defn osw ^java.io.OutputStreamWriter [x] (java.io.OutputStreamWriter. x))
(defn ^:no-doc osw
"Private, don't use."
^java.io.OutputStreamWriter [x]
(java.io.OutputStreamWriter. x))
(defn telemere-print-stream
"Returns a `java.io.PrintStream` that will flush to Telemere signals with given opts."
(defn ^:no-doc telemere-print-stream
"Private, don't use.
Returns a `java.io.PrintStream` that will flush to Telemere signals with given opts."
^java.io.PrintStream [{:as sig-opts :keys [kind level id]}]
(let [baos
(proxy [java.io.ByteArrayOutputStream] []
@ -42,6 +45,8 @@
(java.io.PrintStream. baos true ; Auto flush
java.nio.charset.StandardCharsets/UTF_8)))
;;;;
(defmacro ^:public with-out->telemere
"Executes form with `*out*` bound to flush to Telemere signals with given opts."
([ form] `(with-out->telemere nil ~form))
@ -143,14 +148,21 @@
(streams->telemere! {})
(streams->reset!))
(impl/add-intake-check! :system/out
(fn []
(let [sending? (boolean @orig-out_)
receiving? (and sending? (impl/test-intake! "`System/out` -> Telemere" #(.println System/out %)))]
{:sending->telemere? sending?, :telemere-receiving? receiving?})))
;;;;
(impl/add-intake-check! :system/err
(fn []
(let [sending? (boolean @orig-err_)
receiving? (and sending? (impl/test-intake! "`System/err` -> Telemere" #(.println System/err %)))]
{:sending->telemere? sending?, :telemere-receiving? receiving?})))
(defn check-out-intake
"Returns {:keys [sending->telemere? telemere-receiving?]}."
[]
(let [sending? (boolean @orig-out_)
receiving? (and sending? (impl/test-intake! "`System/out` -> Telemere" #(.println System/out %)))]
{:sending->telemere? sending?, :telemere-receiving? receiving?}))
(defn check-err-intake
"Returns {:keys [sending->telemere? telemere-receiving?]}."
[]
(let [sending? (boolean @orig-err_)
receiving? (and sending? (impl/test-intake! "`System/err` -> Telemere" #(.println System/err %)))]
{:sending->telemere? sending?, :telemere-receiving? receiving?}))
(impl/add-intake-check! :system/out check-out-intake)
(impl/add-intake-check! :system/err check-err-intake)

View file

@ -1,6 +1,6 @@
(ns ^:no-doc taoensso.telemere.tools-logging
"Private ns, implementation detail.
Intake support: `clojure.tools.logging` -> Telemere."
(ns taoensso.telemere.tools-logging
"Intake support for `clojure.tools.logging` -> Telemere.
Telemere will attempt to load this ns automatically when possible."
(:require
[taoensso.encore :as enc :refer [have have?]]
[taoensso.telemere.impl :as impl]
@ -36,7 +36,7 @@
(name [_ ] "taoensso.telemere")
(get-logger [_ logger-ns] (TelemereLogger. (str logger-ns))))
(defn ^:public tools-logging->telemere!
(defn tools-logging->telemere!
"Configures `clojure.tools.logging` to use Telemere as its logging implementation.
Called automatically if the following is true:
@ -53,19 +53,30 @@
(alter-var-root #'clojure.tools.logging/*logger-factory*
(fn [_] (TelemereLoggerFactory.))))
(defn tools-logging-factory [] (TelemereLoggerFactory.))
(defn tools-logging->telemere? []
(defn tools-logging->telemere?
"Returns true iff `clojure.tools.logging` is configured to use Telemere
as its logging implementation."
[]
(when-let [lf clojure.tools.logging/*logger-factory*]
(instance? TelemereLoggerFactory lf)))
(impl/add-intake-check! :tools-logging
(fn []
(let [sending? (tools-logging->telemere?)
receiving?
(and sending?
(impl/test-intake! "`clojure.tools.logging` -> Telemere"
#(clojure.tools.logging/info %)))]
;;;;
{:present? true
:sending->telemere? sending?
:telemere-receiving? receiving?})))
(defn check-intake
"Returns {:keys [present? sending->telemere? telemere-receiving?]}."
[]
(let [sending? (tools-logging->telemere?)
receiving?
(and sending?
(impl/test-intake! "`clojure.tools.logging` -> Telemere"
#(clojure.tools.logging/info %)))]
{:present? true
:sending->telemere? sending?
:telemere-receiving? receiving?}))
(impl/add-intake-check! :tools-logging check-intake)
(impl/on-init
(when (enc/get-env {:as :bool} :clojure.tools.logging-to-telemere?)
(tools-logging->telemere!)))

View file

@ -8,10 +8,12 @@
:refer [signal! with-signal with-signals]
:rename {signal! sig!, with-signal with-sig, with-signals with-sigs}]
[taoensso.telemere.utils :as utils]
[taoensso.telemere.timbre :as timbre]
#?(:clj [taoensso.telemere.slf4j :as slf4j])
#?(:clj [clojure.tools.logging :as ctl])
[taoensso.telemere.utils :as utils]
[taoensso.telemere.timbre :as timbre]
#_[taoensso.telemere.tools-logging :as tools-logging]
#_[taoensso.telemere.streams :as streams]
#?(:clj [taoensso.telemere.slf4j :as slf4j])
#?(:clj [clojure.tools.logging :as ctl])
#?(:default [taoensso.telemere.handlers.console :as handlers:console])
#?(:clj [taoensso.telemere.handlers.file :as handlers:file])
@ -577,9 +579,9 @@
(is (sm? (with-sig (-> (.atInfo sl) (.addKeyValue "k1" "v1") (.addKeyValue "k2" "v2") (.log))) {:data {:slf4j/kvs {"k1" "v1", "k2" "v2"}}}) "Fluent API: kvs")
(testing "Markers"
(let [m1 (slf4j/est-marker! "M1")
m2 (slf4j/est-marker! "M2")
cm (slf4j/est-marker! "Compound" "M1" "M2")]
(let [m1 (#'slf4j/est-marker! "M1")
m2 (#'slf4j/est-marker! "M2")
cm (#'slf4j/est-marker! "Compound" "M1" "M2")]
[(is (sm? (with-sig (.info sl cm "Hello")) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Legacy API: markers")
(is (sm? (with-sig (-> (.atInfo sl) (.addMarker m1) (.addMarker cm) (.log))) {:data #:slf4j{:marker-names #{"Compound" "M1" "M2"}}}) "Fluent API: markers")]))
@ -813,26 +815,26 @@
#?(:clj
(deftest _open-telemetry
[(testing "attr-name"
[(is (= (handlers:otel/attr-name :foo) "foo"))
(is (= (handlers:otel/attr-name :foo-bar-baz) "foo_bar_baz"))
(is (= (handlers:otel/attr-name :foo/bar-baz) "foo.bar_baz"))
(is (= (handlers:otel/attr-name :Foo/Bar-BAZ) "foo.bar_baz"))
(is (= (handlers:otel/attr-name "Foo Bar-Baz") "foo_bar_baz"))
(is (= (handlers:otel/attr-name :x1.x2/x3-x4 :foo/bar-baz)
[(is (= (#'handlers:otel/attr-name :foo) "foo"))
(is (= (#'handlers:otel/attr-name :foo-bar-baz) "foo_bar_baz"))
(is (= (#'handlers:otel/attr-name :foo/bar-baz) "foo.bar_baz"))
(is (= (#'handlers:otel/attr-name :Foo/Bar-BAZ) "foo.bar_baz"))
(is (= (#'handlers:otel/attr-name "Foo Bar-Baz") "foo_bar_baz"))
(is (= (#'handlers:otel/attr-name :x1.x2/x3-x4 :foo/bar-baz)
"x1.x2.x3_x4.foo.bar_baz"))])
(testing "merge-prefix-map"
[(is (= (handlers:otel/merge-prefix-map nil "pf" nil) nil))
(is (= (handlers:otel/merge-prefix-map nil "pf" {}) nil))
(is (= (handlers:otel/merge-prefix-map {"a" "A"} "pf" {:a :A}) {"a" "A", "pf.a" :A}))
(is (= (handlers:otel/merge-prefix-map {} "pf"
[(is (= (#'handlers:otel/merge-prefix-map nil "pf" nil) nil))
(is (= (#'handlers:otel/merge-prefix-map nil "pf" {}) nil))
(is (= (#'handlers:otel/merge-prefix-map {"a" "A"} "pf" {:a :A}) {"a" "A", "pf.a" :A}))
(is (= (#'handlers:otel/merge-prefix-map {} "pf"
{:a/b1 "v1" :a/b2 "v2" :nil nil, :map {:k1 "v1"}})
{"pf.a.b1" "v1", "pf.a.b2" "v2", "pf.nil" nil, "pf.map" {:k1 "v1"}}))])
(testing "as-attrs"
(is (= (str
(handlers:otel/as-attrs
(#'handlers:otel/as-attrs
{:string "s", :keyword :foo/bar, :long 5, :double 5.0, :nil nil,
:longs [5 5.0 5.0],
:doubles [5.0 5 5],
@ -844,7 +846,7 @@
"{bools=[true, false, false], double=5.0, doubles=[5.0, 5.0, 5.0], keyword=\":foo/bar\", long=5, longs=[5, 5, 5], map=[[:k1 \"v1\"]], mixed=[5, \"5\", nil], nil=\"nil\", string=\"s\", strings=[\"a\", \"b\", \"c\"]}")))
(testing "signal->attrs-map"
(let [attrs-map handlers:otel/signal->attrs-map]
(let [attrs-map #'handlers:otel/signal->attrs-map]
[(is (= (attrs-map nil { }) {"error" false}))
(is (= (attrs-map :attrs {:attrs {:a1 :A1}}) {"error" false, :a1 :A1}))
(is

View file

@ -95,21 +95,21 @@ See section [3-Config](./3-Config) for customization.
> Signal handlers process created signals to *do something with them* (analyse them, write them to console/file/queue/db, etc.)
| Platform | Condition | Handler |
| -------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Clj | Always | [Console handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) that prints signals to `*out*` or `*err*`. |
| Cljs | Always | [Console handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) that prints signals to the **browser console**. |
| Clj | [OpenTelemetry API](https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-api) present | [OpenTelemetry handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:open-telemetry-logger) that emits signals as log records to a configured [`LoggerProvider`](https://opentelemetry.io/docs/specs/otel/logs/sdk/#loggerprovider). |
| Platform | Condition | Handler |
| -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Clj | Always | [Console handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) that prints signals to `*out*` or `*err*`. |
| Cljs | Always | [Console handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) that prints signals to the **browser console**. |
| Clj      | [OpenTelemetry API](https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-api) present | [OpenTelemetry handler](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:open-telemetry-logger) that emits signals as log records to a configured [`LoggerProvider`](https://opentelemetry.io/docs/specs/otel/logs/sdk/#loggerprovider). |
**Default signal intakes**:
> Telemere can create signals from relevant **external API calls**, etc.
| Platform | Condition | Signals from |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| Clj | [SLF4J API](https://mvnrepository.com/artifact/org.slf4j/slf4j-api) and [Telemere SLF4J backend](https://clojars.org/com.taoensso/slf4j-telemere) present | [SLF4J](https://www.slf4j.org/) logging calls. |
| Clj | [clojure.tools.logging](https://mvnrepository.com/artifact/org.clojure/tools.logging) present and [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#tools-logging-%3Etelemere!) called | [clojure.tools.logging](https://github.com/clojure/tools.logging) logging calls. |
| Clj | [`streams->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#streams-%3Etelemere!) called | Output to `System/out` and `System/err` streams. |
| Platform | Condition | Signals from |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Clj | [SLF4J API](https://mvnrepository.com/artifact/org.slf4j/slf4j-api) and [Telemere SLF4J backend](https://clojars.org/com.taoensso/slf4j-telemere) present | [SLF4J](https://www.slf4j.org/) logging calls. |
| Clj | [clojure.tools.logging](https://mvnrepository.com/artifact/org.clojure/tools.logging) present and [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.tools-logging#tools-logging-%3Etelemere!) called | [clojure.tools.logging](https://github.com/clojure/tools.logging) logging calls. |
| Clj | [`streams->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#streams-%3Etelemere!) called | Output to `System/out` and `System/err` streams. |
Run [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes) to help verify/debug:

View file

@ -20,12 +20,12 @@ This flow is described by [`help:signal-flow`](https://cljdoc.org/d/com.taoensso
For more info see:
| Var | Help with |
| :-- | :-- |
| [`help:signal-creators`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-creators) | List of signal creators
| [`help:signal-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) | Options for signal creators
| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal map content
| [`help:signal-flow`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-flow) | Ordered flow from signal creation to handling
| [`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
| [`help:signal-formatters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-formatters) | Signal formatters for use by handlers
| Var | Help with |
| :-------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------- |
| [`help:signal-creators`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-creators) | List of signal creators |
| [`help:signal-options`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-options) | Options for signal creators |
| [`help:signal-content`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-content) | Signal map content |
| [`help:signal-flow`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-flow) | Ordered flow from signal creation to handling |
| [`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 |
| [`help:signal-formatters`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#help:signal-formatters) | Signal formatters for use by handlers |

View file

@ -29,9 +29,7 @@ See section [4-Handlers](./4-Handlers).
To do this:
1. Ensure that you have the `clojure.tools.logging` dependency, and
2. Call [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#tools-logging-%3Etelemere!), or set the relevant system config as described in its docstring.
Note that the `tools-logging->telemere!` var will be present **only if** the `clojure.tools.logging` dependency is present.
2. Call [`tools-logging->telemere!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.tools-logging#tools-logging-%3Etelemere!), or set the relevant system config as described in its docstring.
Verify successful intake with [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes):
@ -90,9 +88,7 @@ Telemere can send signals as [`LogRecords`](https://opentelemetry.io/docs/specs/
To do this:
1. Ensure that you have the [OpenTelemetry Java](https://github.com/open-telemetry/opentelemetry-java) dependency.
2. Use [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:open-telemetry-logger) to create an appropriately configured handler, and register it with [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!).
Note that the `handler:open-telemetry-logger` var will be present **only if** the OpenTelemetry Java dependency is present.
2. Use [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.open-telemetry#handler:open-telemetry-logger) to create an appropriately configured handler, and register it with [`add-handler!`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#add-handler!).
## Tufte

View file

@ -4,13 +4,13 @@ Signal handlers process created signals to *do something with them* (analyse the
The following handlers are included out-the-box:
| Name | Platform | Writes signals to | Writes signals as |
| :---------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Clj | `*out*` or `*err*` | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw data (for [cljs-devtools](https://github.com/binaryage/cljs-devtools), etc.) |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#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/) |
| Name | Platform | Writes signals to | Writes signals as |
| :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Clj | `*out*` or `*err*` | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:console`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console) | Cljs | Browser console | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:console-raw`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:console-raw) | Cljs | Browser console | Raw data (for [cljs-devtools](https://github.com/binaryage/cljs-devtools), etc.) |
| [`handler:file`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#handler:file) | Clj | File/s on disk | String ([edn](https://github.com/edn-format/edn), JSON, formatted, etc.) |
| [`handler:open-telemetry-logger`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere.open-telemetry#handler:open-telemetry-logger) | Clj | [OpenTelemetry](https://opentelemetry.io/) [Java client](https://github.com/open-telemetry/opentelemetry-java) | [LogRecord](https://opentelemetry.io/docs/specs/otel/logs/data-model/) |
- See relevant docstrings (links above) for more info.
- See section [8-Community](8-Community.md) for additional handlers.