diff --git a/project.clj b/project.clj index 82623e8..26a52c0 100644 --- a/project.clj +++ b/project.clj @@ -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 diff --git a/slf4j/src/taoensso/telemere/slf4j.clj b/slf4j/src/taoensso/telemere/slf4j.clj index 4aff376..b69a69f 100644 --- a/slf4j/src/taoensso/telemere/slf4j.clj +++ b/slf4j/src/taoensso/telemere/slf4j.clj @@ -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 #{}. 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"})) diff --git a/src/taoensso/telemere.cljc b/src/taoensso/telemere.cljc index 6f3cff4..94fe2cc 100644 --- a/src/taoensso/telemere.cljc +++ b/src/taoensso/telemere.cljc @@ -375,25 +375,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 @@ -403,20 +384,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 @@ -450,6 +417,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")) @@ -464,5 +441,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))))) - -;;;; diff --git a/src/taoensso/telemere/handlers/open_telemetry.clj b/src/taoensso/telemere/handlers/open_telemetry.clj index 72d6c7d..4c00da0 100644 --- a/src/taoensso/telemere/handlers/open_telemetry.clj +++ b/src/taoensso/telemere/handlers/open_telemetry.clj @@ -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. ." @@ -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. ." (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. ." [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)))) diff --git a/src/taoensso/telemere/impl.cljc b/src/taoensso/telemere/impl.cljc index 0b59e24..aa0b074 100644 --- a/src/taoensso/telemere/impl.cljc +++ b/src/taoensso/telemere/impl.cljc @@ -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 diff --git a/src/taoensso/telemere/streams.clj b/src/taoensso/telemere/streams.clj index 192d447..c654ff9 100644 --- a/src/taoensso/telemere/streams.clj +++ b/src/taoensso/telemere/streams.clj @@ -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) diff --git a/src/taoensso/telemere/tools_logging.clj b/src/taoensso/telemere/tools_logging.clj index 9608f86..81c39c5 100644 --- a/src/taoensso/telemere/tools_logging.clj +++ b/src/taoensso/telemere/tools_logging.clj @@ -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!))) diff --git a/test/taoensso/telemere_tests.cljc b/test/taoensso/telemere_tests.cljc index 3af1c9d..7e1b3f7 100644 --- a/test/taoensso/telemere_tests.cljc +++ b/test/taoensso/telemere_tests.cljc @@ -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 diff --git a/wiki/1-Getting-started.md b/wiki/1-Getting-started.md index cdebdf6..6467888 100644 --- a/wiki/1-Getting-started.md +++ b/wiki/1-Getting-started.md @@ -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: diff --git a/wiki/2-Architecture.md b/wiki/2-Architecture.md index 0981e69..2b71207 100644 --- a/wiki/2-Architecture.md +++ b/wiki/2-Architecture.md @@ -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 \ No newline at end of file +| 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 | diff --git a/wiki/3-Config.md b/wiki/3-Config.md index ec45e9d..609372b 100644 --- a/wiki/3-Config.md +++ b/wiki/3-Config.md @@ -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 diff --git a/wiki/4-Handlers.md b/wiki/4-Handlers.md index 4daa0a7..0a0dfc5 100644 --- a/wiki/4-Handlers.md +++ b/wiki/4-Handlers.md @@ -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.