Skip to content

Commit

Permalink
[mod] Generalize "intake", rename -> "interop"
Browse files Browse the repository at this point in the history
Extending feature to cover general interop like OpenTelemetry tracing, etc.
  • Loading branch information
ptaoussanis committed Aug 23, 2024
1 parent 88eb521 commit ef678bc
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 68 deletions.
19 changes: 10 additions & 9 deletions slf4j/src/taoensso/telemere/slf4j.clj
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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"}))
6 changes: 3 additions & 3 deletions src/taoensso/telemere.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
60 changes: 38 additions & 22 deletions src/taoensso/telemere/impl.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -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>)
Expand Down Expand Up @@ -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 [])
Expand Down Expand Up @@ -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?]}
Expand All @@ -671,30 +682,35 @@

(and (not elide?) allow?))))

;;;; Intakes
;;;; Interop

#?(:clj
(do
(enc/defonce ^:private intake-checks_
(enc/defonce ^:private interop-checks_
"{<source-id> (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
{<source-id> {: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)))]
Expand Down
22 changes: 11 additions & 11 deletions src/taoensso/telemere/streams.clj
Original file line number Diff line number Diff line change
@@ -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?]]
Expand Down Expand Up @@ -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)}})

Expand Down Expand Up @@ -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)}})

Expand All @@ -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)
15 changes: 8 additions & 7 deletions src/taoensso/telemere/tools_logging.clj
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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.))))
Expand All @@ -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!)))
14 changes: 7 additions & 7 deletions test/taoensso/telemere_tests.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 3 additions & 3 deletions wiki/1-Getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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}
Expand Down
12 changes: 6 additions & 6 deletions wiki/3-Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
```

Expand All @@ -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}}
```

Expand All @@ -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}}
```
Expand Down

0 comments on commit ef678bc

Please sign in to comment.