From ef678bcc36290979e7726bafbb44b300fa6d63b5 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Thu, 22 Aug 2024 14:25:48 +0200 Subject: [PATCH] [mod] Generalize "intake", rename -> "interop" Extending feature to cover general interop like OpenTelemetry tracing, etc. --- slf4j/src/taoensso/telemere/slf4j.clj | 19 ++++---- src/taoensso/telemere.cljc | 6 +-- src/taoensso/telemere/impl.cljc | 60 ++++++++++++++++--------- src/taoensso/telemere/streams.clj | 22 ++++----- src/taoensso/telemere/tools_logging.clj | 15 ++++--- test/taoensso/telemere_tests.cljc | 14 +++--- wiki/1-Getting-started.md | 6 +-- wiki/3-Config.md | 12 ++--- 8 files changed, 86 insertions(+), 68 deletions(-) diff --git a/slf4j/src/taoensso/telemere/slf4j.clj b/slf4j/src/taoensso/telemere/slf4j.clj index c79513fe..928dacc5 100644 --- a/slf4j/src/taoensso/telemere/slf4j.clj +++ b/slf4j/src/taoensso/telemere/slf4j.clj @@ -1,5 +1,5 @@ (ns taoensso.telemere.slf4j - "Intake support for SLF4J -> Telemere. + "Interop 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 @@ -97,7 +97,7 @@ (marker-names cm) (marker-names ms)))) -;;;; Intake fns (called by `TelemereLogger`) +;;;; Interop fns (called by `TelemereLogger`) (defn- allowed? "Private, don't use. @@ -176,25 +176,26 @@ ;;;; -(defn check-intake - "Returns {:keys [present? sending->telemere? telemere-receiving?]}." +(defn check-interop + "Returns interop debug info map." [] (let [^org.slf4j.Logger sl - (org.slf4j.LoggerFactory/getLogger "IntakeTestTelemereLogger") + (org.slf4j.LoggerFactory/getLogger "InteropTestTelemereLogger") sending? (instance? com.taoensso.telemere.slf4j.TelemereLogger sl) receiving? (and sending? - (impl/test-intake! "SLF4J -> Telemere" #(.info sl %)))] + (impl/test-interop! "SLF4J -> Telemere" #(.info sl %)))] - {:present? true + {:present? true + :telemere-provider-present? true :sending->telemere? sending? :telemere-receiving? receiving?})) -(impl/add-intake-check! :slf4j check-intake) +(impl/add-interop-check! :slf4j check-interop) (impl/on-init (impl/signal! {:kind :event :level :debug ; < :info since runs on init :id :taoensso.telemere/slf4j->telemere! - :msg "Enabling intake: SLF4J -> Telemere"})) + :msg "Enabling interop: SLF4J -> Telemere"})) diff --git a/src/taoensso/telemere.cljc b/src/taoensso/telemere.cljc index 686dc6d0..002f2bcf 100644 --- a/src/taoensso/telemere.cljc +++ b/src/taoensso/telemere.cljc @@ -263,18 +263,18 @@ (handler thread throwable)))) nil)) -;;;; Intake +;;;; Interop #?(:clj (enc/defaliases - impl/check-intakes + impl/check-interop streams/with-out->telemere streams/with-err->telemere streams/with-streams->telemere streams/streams->telemere! streams/streams->reset!)) -(comment (check-intakes)) +(comment (check-interop)) ;;;; Handlers diff --git a/src/taoensso/telemere/impl.cljc b/src/taoensso/telemere/impl.cljc index fd07fe7e..21f58c03 100644 --- a/src/taoensso/telemere/impl.cljc +++ b/src/taoensso/telemere/impl.cljc @@ -21,17 +21,18 @@ ^:dynamic taoensso.telemere/*middleware* ^:dynamic taoensso.telemere/*uid-fn*)) -;;;; Utils +;;;; Config #?(: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))))) + (do + (def present:tools-logging? (enc/have-resource? "clojure/tools/logging.clj")) + (def present:slf4j? (enc/compile-if org.slf4j.Logger true false)) + (def present:slf4j-telemere? (enc/compile-if com.taoensso.telemere.slf4j.TelemereLogger true false)) + (def present:otel? (enc/compile-if io.opentelemetry.context.Context true false)) -(comment (macroexpand-1 '(on-init (println "foo")))) - -;;;; Config + (def enabled:tools-logging? + "Documented at `taoensso.telemere.tools-logging/tools-logging->telemere!`." + (enc/get-env {:as :bool} :clojure.tools.logging/to-telemere)))) #?(:clj (let [base (enc/get-env {:as :edn} :taoensso.telemere/ct-filters<.platform><.edn>) @@ -64,6 +65,16 @@ (comment (enc/get-env {:as :edn, :return :explain} :taoensso.telemere/rt-filters<.platform><.edn>)) +;;;; Utils + +#?(: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")))) + ;;;; Messages (deftype MsgSkip []) @@ -657,7 +668,7 @@ #?(:clj (defmacro signal-allowed? - "Used only for intake (SLF4J, `tools.logging`, etc.)." + "Used only for interop (SLF4J, `tools.logging`, etc.)." {:arglists (signal-arglists :signal!)} [opts] (let [{:keys [#_expansion-id #_location elide? allow?]} @@ -671,30 +682,35 @@ (and (not elide?) allow?)))) -;;;; Intakes +;;;; Interop #?(:clj (do - (enc/defonce ^:private intake-checks_ + (enc/defonce ^:private interop-checks_ "{ (fn check [])}" (atom - {:tools-logging (fn [] {:present? (enc/have-resource? "clojure/tools/logging.clj")}) - :slf4j (fn [] {:present? (enc/compile-when org.slf4j.Logger true false)})})) + {:tools-logging (fn [] {:present? present:tools-logging?, :enabled-by-env? enabled:tools-logging?}) + :slf4j (fn [] {:present? present:slf4j?, :telemere-provider-present? present:slf4j-telemere?}) + :open-telemetry (fn [] {:present? present:otel?})})) - (defn add-intake-check! [source-id check-fn] (swap! intake-checks_ assoc source-id check-fn)) + (defn add-interop-check! [source-id check-fn] (swap! interop-checks_ assoc source-id check-fn)) - (defn ^:public check-intakes + (defn ^:public check-interop "Experimental, subject to change. - Runs Telemere's registered intake checks and returns - { {:keys [sending->telemere? telemere-receiving? ...]}}. - - Useful for tests/debugging." + Runs Telemere's registered interop checks and returns info useful + for tests/debugging, e.g.: + + {:tools-logging {:present? false} + :slf4j {:present? true + :sending->telemere? true + :telemere-receiving? true} + ...}" [] (enc/map-vals (fn [check-fn] (check-fn)) - @intake-checks_)) + @interop-checks_)) - (defn test-intake! [msg test-fn] - (let [msg (str "Intake test: " msg " (" (enc/uuid-str) ")") + (defn test-interop! [msg test-fn] + (let [msg (str "Interop test: " msg " (" (enc/uuid-str) ")") signal (binding [*rt-sig-filter* nil] ; Without runtime filters (with-signal :raw :trap (test-fn msg)))] diff --git a/src/taoensso/telemere/streams.clj b/src/taoensso/telemere/streams.clj index eaeb0dc2..11fab1ff 100644 --- a/src/taoensso/telemere/streams.clj +++ b/src/taoensso/telemere/streams.clj @@ -1,5 +1,5 @@ (ns taoensso.telemere.streams - "Intake support for standard stream/s -> Telemere." + "Interop support for standard stream/s -> Telemere." (:refer-clojure :exclude [binding]) (:require [taoensso.encore :as enc :refer [binding have have?]] @@ -96,7 +96,7 @@ {:kind :event :level :info :id :taoensso.telemere/streams->telemere! - :msg "Disabling intake: standard stream/s -> Telemere" + :msg "Disabling interop: standard stream/s -> Telemere" :data {:system/out? (boolean orig-out) :system/err? (boolean orig-err)}}) @@ -133,7 +133,7 @@ {:kind :event :level :info :id :taoensso.telemere/streams->telemere! - :msg "Enabling intake: standard stream/s -> Telemere" + :msg "Enabling interop: standard stream/s -> Telemere" :data {:system/out? (boolean out) :system/err? (boolean err)}}) @@ -150,19 +150,19 @@ ;;;; -(defn check-out-intake - "Returns {:keys [sending->telemere? telemere-receiving?]}." +(defn check-out-interop + "Returns interop debug info map." [] (let [sending? (boolean @orig-out_) - receiving? (and sending? (impl/test-intake! "`System/out` -> Telemere" #(.println System/out %)))] + receiving? (and sending? (impl/test-interop! "`System/out` -> Telemere" #(.println System/out %)))] {:sending->telemere? sending?, :telemere-receiving? receiving?})) -(defn check-err-intake - "Returns {:keys [sending->telemere? telemere-receiving?]}." +(defn check-err-interop + "Returns interop debug info map." [] (let [sending? (boolean @orig-err_) - receiving? (and sending? (impl/test-intake! "`System/err` -> Telemere" #(.println System/err %)))] + receiving? (and sending? (impl/test-interop! "`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) +(impl/add-interop-check! :system/out check-out-interop) +(impl/add-interop-check! :system/err check-err-interop) diff --git a/src/taoensso/telemere/tools_logging.clj b/src/taoensso/telemere/tools_logging.clj index 0c4ca181..c68c095e 100644 --- a/src/taoensso/telemere/tools_logging.clj +++ b/src/taoensso/telemere/tools_logging.clj @@ -1,5 +1,5 @@ (ns taoensso.telemere.tools-logging - "Intake support for `tools.logging` -> Telemere. + "Interop support for `tools.logging` -> Telemere. Telemere will attempt to load this ns automatically when possible. Naming conventions: @@ -53,7 +53,7 @@ {:kind :event :level :debug ; < :info since runs on init :id :taoensso.telemere/tools-logging->telemere! - :msg "Enabling intake: `tools.logging` -> Telemere"}) + :msg "Enabling interop: `tools.logging` -> Telemere"}) (alter-var-root #'clojure.tools.logging/*logger-factory* (fn [_] (TelemereLoggerFactory.)))) @@ -67,21 +67,22 @@ ;;;; -(defn check-intake - "Returns {:keys [present? sending->telemere? telemere-receiving?]}." +(defn check-interop + "Returns interop debug info map." [] (let [sending? (tools-logging->telemere?) receiving? (and sending? - (impl/test-intake! "`tools.logging` -> Telemere" + (impl/test-interop! "`tools.logging` -> Telemere" #(clojure.tools.logging/info %)))] {:present? true + :enabled-by-env? impl/enabled:tools-logging? :sending->telemere? sending? :telemere-receiving? receiving?})) -(impl/add-intake-check! :tools-logging check-intake) +(impl/add-interop-check! :tools-logging check-interop) (impl/on-init - (when (enc/get-env {:as :bool} :clojure.tools.logging/to-telemere) + (when impl/enabled:tools-logging? (tools-logging->telemere!))) diff --git a/test/taoensso/telemere_tests.cljc b/test/taoensso/telemere_tests.cljc index 05ada349..c63dad3f 100644 --- a/test/taoensso/telemere_tests.cljc +++ b/test/taoensso/telemere_tests.cljc @@ -626,35 +626,35 @@ ;; (do (enc/set-var-root! impl/*sig-handlers* nil) :unset-handler)])))]) -;;;; Intake +;;;; Interop (comment (def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class"))) #?(:clj - (deftest _intake + (deftest _interop [(testing "`tools.logging` -> Telemere" - [(is (sm? (tel/check-intakes) {:tools-logging {:present? true, :sending->telemere? true, :telemere-receiving? true}})) + [(is (sm? (tel/check-interop) {:tools-logging {:present? true, :sending->telemere? true, :telemere-receiving? true}})) (is (sm? (with-sig (ctl/info "Hello" "x" "y")) {:level :info, :ns "taoensso.telemere-tests", :kind :tools-logging, :msg_ "Hello x y", :inst pinst?})) (is (sm? (with-sig (ctl/warn "Hello" "x" "y")) {:level :warn, :ns "taoensso.telemere-tests", :kind :tools-logging, :msg_ "Hello x y", :inst pinst?})) (is (sm? (with-sig (ctl/error ex1 "An error")) {:level :error, :error pex1?, :inst pinst?}) "Errors")]) (testing "Standard out/err streams -> Telemere" - [(is (sm? (tel/check-intakes) {:system/out {:sending->telemere? false, :telemere-receiving? false}, + [(is (sm? (tel/check-interop) {:system/out {:sending->telemere? false, :telemere-receiving? false}, :system/err {:sending->telemere? false, :telemere-receiving? false}})) (is (true? (tel/streams->telemere!))) - (is (sm? (tel/check-intakes) {:system/out {:sending->telemere? true, :telemere-receiving? true}, + (is (sm? (tel/check-interop) {:system/out {:sending->telemere? true, :telemere-receiving? true}, :system/err {:sending->telemere? true, :telemere-receiving? true}})) (is (true? (tel/streams->reset!))) - (is (sm? (tel/check-intakes) {:system/out {:sending->telemere? false, :telemere-receiving? false}, + (is (sm? (tel/check-interop) {:system/out {:sending->telemere? false, :telemere-receiving? false}, :system/err {:sending->telemere? false, :telemere-receiving? false}})) (is (sm? (with-sig (tel/with-out->telemere (println "Hello" "x" "y"))) {:level :info, :location nil, :ns nil, :kind :system/out, :msg_ "Hello x y"}))]) (testing "SLF4J -> Telemere" - [(is (sm? (tel/check-intakes) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}})) + [(is (sm? (tel/check-interop) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}})) (let [^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class")] [(testing "Basics" [(is (sm? (with-sig (.info sl "Hello")) {:level :info, :ns "my.class", :kind :slf4j, :msg_ "Hello", :inst pinst?}) "Legacy API: info basics") diff --git a/wiki/1-Getting-started.md b/wiki/1-Getting-started.md index bb7658a4..620e2d3f 100644 --- a/wiki/1-Getting-started.md +++ b/wiki/1-Getting-started.md @@ -100,7 +100,7 @@ See section [3-Config](./3-Config) for customization. | 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**. | -**Default signal intakes**: +**Default interop**: > Telemere can create signals from relevant **external API calls**, etc. @@ -110,10 +110,10 @@ See section [3-Config](./3-Config) for customization. | Clj | [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 | [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: +Run [`check-interop`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-interop) to help verify/debug: ```clojure -(check-intakes) ; => +(check-interop) ; => {:tools-logging {:present? false} :slf4j {:sending->telemere? true, :telemere-receiving? true} :system/out {:sending->telemere? false, :telemere-receiving? false} diff --git a/wiki/3-Config.md b/wiki/3-Config.md index ce3112ee..420da71d 100644 --- a/wiki/3-Config.md +++ b/wiki/3-Config.md @@ -32,10 +32,10 @@ To do this: 1. Ensure that you have the `tools.logging` dependency, and 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 environmental 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): +Verify successful interop with [`check-interop`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-interop): ```clojure -(check-intakes) ; => +(check-interop) ; => {:tools-logging {:sending->telemere? true, :telemere-receiving? true}} ``` @@ -54,10 +54,10 @@ To do this, ensure that you have the following dependencies: When `com.taoensso/slf4j-telemere` is on your classpath AND no other SLF4J backends are, SLF4J will direct all its logging calls to Telemere. -Verify successful intake with [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes): +Verify successful interop with [`check-interop`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-interop): ```clojure -(check-intakes) ; => +(check-interop) ; => {:slf4j {:sending->telemere? true, :telemere-receiving? true}} ``` @@ -76,10 +76,10 @@ To do this, call [`streams->telemere!`](https://cljdoc.org/d/com.taoensso/teleme Note that Clojure's `*out*`, `*err*` are **not** necessarily automatically affected. -Verify successful intake with [`check-intakes`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-intakes): +Verify successful interop with [`check-interop`](https://cljdoc.org/d/com.taoensso/telemere/CURRENT/api/taoensso.telemere#check-interop): ```clojure -(check-intakes) ; => +(check-interop) ; => {:system/out {:sending->telemere? true, :telemere-receiving? true} :system/err {:sending->telemere? true, :telemere-receiving? true}} ```