mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-17 18:01:10 +00:00
[mod] Improve SLF4J, tools.logging interop signals
Incl.: 1. Logger names are now used as namespaces. - For SLF4J: these are typically class names. - For tools.logging: these are typically *ns* strings. 2. These now have dedicated :kind (:slf4j, :tools.logging) to make it easier for users to set kind-specific min levels.
This commit is contained in:
parent
8f1035ff97
commit
22c46afa04
5 changed files with 47 additions and 52 deletions
|
|
@ -6,7 +6,7 @@ Default signal keys:
|
|||
`:schema` ------ Int version of signal schema (current: 1)
|
||||
`:inst` -------- Platform instant [1] when signal was created
|
||||
`:level` ------- Signal level ∈ #{<int> :trace :debug :info :warn :error :fatal :report ...}
|
||||
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy <user-val> ...}
|
||||
`:kind` -------- Signal ?kind ∈ #{nil :event :error :log :trace :spy :slf4j :tools-logging <user-val> ...}
|
||||
`:id` ---------- ?id of signal (common to all signals created at callsite, contrast with `:uid`)
|
||||
`:uid` --------- ?id of signal instance (unique to each signal created at callsite, contrast with `:id`)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,30 +49,30 @@ public class TelemereLogger extends LegacyAbstractLogger implements LoggingEvent
|
|||
}
|
||||
|
||||
private static IFn logFn;
|
||||
private static IFn isLevelEnabledFn;
|
||||
private static IFn isAllowedFn;
|
||||
|
||||
static void init() {
|
||||
IFn requireFn = Clojure.var("clojure.core", "require");
|
||||
requireFn.invoke( Clojure.read("taoensso.telemere.slf4j"));
|
||||
logFn = Clojure.var("taoensso.telemere.slf4j", "log!");
|
||||
isLevelEnabledFn = Clojure.var("taoensso.telemere.slf4j", "allowed?");
|
||||
IFn requireFn = Clojure.var("clojure.core", "require");
|
||||
requireFn.invoke(Clojure.read("taoensso.telemere.slf4j"));
|
||||
isAllowedFn = Clojure.var("taoensso.telemere.slf4j", "allowed?");
|
||||
logFn = Clojure.var("taoensso.telemere.slf4j", "log!");
|
||||
}
|
||||
|
||||
protected TelemereLogger(String name) { this.name = name; }
|
||||
|
||||
protected boolean isLevelEnabled(Level level) { return (boolean) isLevelEnabledFn.invoke(level); }
|
||||
public boolean isTraceEnabled() { return (boolean) isLevelEnabledFn.invoke(Level.TRACE); }
|
||||
public boolean isDebugEnabled() { return (boolean) isLevelEnabledFn.invoke(Level.DEBUG); }
|
||||
public boolean isInfoEnabled() { return (boolean) isLevelEnabledFn.invoke(Level.INFO); }
|
||||
public boolean isWarnEnabled() { return (boolean) isLevelEnabledFn.invoke(Level.WARN); }
|
||||
public boolean isErrorEnabled() { return (boolean) isLevelEnabledFn.invoke(Level.ERROR); }
|
||||
protected boolean isLevelEnabled(Level level) { return (boolean) isAllowedFn.invoke(this.name, level); }
|
||||
public boolean isTraceEnabled() { return (boolean) isAllowedFn.invoke(this.name, Level.TRACE); }
|
||||
public boolean isDebugEnabled() { return (boolean) isAllowedFn.invoke(this.name, Level.DEBUG); }
|
||||
public boolean isInfoEnabled() { return (boolean) isAllowedFn.invoke(this.name, Level.INFO); }
|
||||
public boolean isWarnEnabled() { return (boolean) isAllowedFn.invoke(this.name, Level.WARN); }
|
||||
public boolean isErrorEnabled() { return (boolean) isAllowedFn.invoke(this.name, Level.ERROR); }
|
||||
|
||||
public void log(LoggingEvent event) { logFn.invoke(event); } // Fluent (modern) API, called after level check
|
||||
public void log(LoggingEvent event) { logFn.invoke(this.name, event); } // Fluent (modern) API, called after level check
|
||||
|
||||
@Override protected String getFullyQualifiedCallerName() { return null; }
|
||||
@Override
|
||||
protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, Throwable throwable) {
|
||||
logFn.invoke(level, throwable, messagePattern, arguments, marker); // Legacy API, called after level check
|
||||
logFn.invoke(this.name, level, throwable, messagePattern, arguments, marker); // Legacy API, called after level check
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,22 +102,20 @@
|
|||
(defn- allowed?
|
||||
"Private, don't use.
|
||||
Called by `com.taoensso.telemere.slf4j.TelemereLogger`."
|
||||
[^org.slf4j.event.Level level]
|
||||
(when-debug (println [:slf4j/allowed? (sig-level level)]))
|
||||
[logger-name level]
|
||||
(when-debug (println [:slf4j/allowed? (sig-level level) logger-name]))
|
||||
(impl/signal-allowed?
|
||||
{:location nil
|
||||
:kind :log
|
||||
:id :taoensso.telemere/slf4j
|
||||
{:location {:ns logger-name} ; Typically source class name
|
||||
:kind :slf4j
|
||||
:level (sig-level level)}))
|
||||
|
||||
(defn- normalized-log!
|
||||
[inst level error msg-pattern args marker-names kvs]
|
||||
(when-debug (println [:slf4j/normalized-log! (sig-level level)]))
|
||||
[logger-name level inst error msg-pattern args marker-names kvs]
|
||||
(when-debug (println [:slf4j/normalized-log! (sig-level level) logger-name]))
|
||||
(impl/signal!
|
||||
{:allow? true ; Pre-filtered by `allowed?` call
|
||||
:location nil
|
||||
:kind :log
|
||||
:id :taoensso.telemere/slf4j
|
||||
:location {:ns logger-name} ; Typically source class name
|
||||
:kind :slf4j
|
||||
:level (sig-level level)
|
||||
:inst inst
|
||||
:error error
|
||||
|
|
@ -143,7 +141,7 @@
|
|||
Called by `com.taoensso.telemere.slf4j.TelemereLogger`."
|
||||
|
||||
;; Modern "fluent" API calls
|
||||
([^org.slf4j.event.LoggingEvent event]
|
||||
([logger-name ^org.slf4j.event.LoggingEvent event]
|
||||
(let [inst (or (when-let [ts (.getTimeStamp event)] (java.time.Instant/ofEpochMilli ts)) (enc/now-inst*))
|
||||
level (.getLevel event)
|
||||
error (.getThrowable event)
|
||||
|
|
@ -156,17 +154,17 @@
|
|||
(assoc acc (.-key kvp) (.-value kvp)))
|
||||
nil kvps))]
|
||||
|
||||
(when-debug (println [:slf4j/fluent-log-call (sig-level level)]))
|
||||
(normalized-log! inst level error msg-pattern args markers kvs)))
|
||||
(when-debug (println [:slf4j/fluent-log-call (sig-level level) logger-name]))
|
||||
(normalized-log! logger-name level inst error msg-pattern args markers kvs)))
|
||||
|
||||
;; Legacy API calls
|
||||
([^org.slf4j.event.Level level error msg-pattern args marker]
|
||||
([logger-name ^org.slf4j.event.Level level error msg-pattern args marker]
|
||||
(let [marker-names (when marker (marker-names marker))]
|
||||
(when-debug (println [:slf4j/legacy-log-call (sig-level level)]))
|
||||
(normalized-log! (enc/now-inst*) level error msg-pattern args marker-names nil))))
|
||||
(when-debug (println [:slf4j/legacy-log-call (sig-level level) logger-name]))
|
||||
(normalized-log! logger-name level (enc/now-inst*) error msg-pattern args marker-names nil))))
|
||||
|
||||
(comment
|
||||
(def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "MySlfLogger"))
|
||||
(def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class"))
|
||||
(impl/with-signal (-> sl (.info "Hello {}" "x")))
|
||||
(impl/with-signal (-> (.atInfo sl) (.log "Hello {}" "x")))
|
||||
|
||||
|
|
@ -182,7 +180,7 @@
|
|||
"Returns {:keys [present? sending->telemere? telemere-receiving?]}."
|
||||
[]
|
||||
(let [^org.slf4j.Logger sl
|
||||
(org.slf4j.LoggerFactory/getLogger "IntakeTestTelemereLogger")
|
||||
(org.slf4j.LoggerFactory/getLogger "IntakeTestTelemereLogger")
|
||||
sending? (instance? com.taoensso.telemere.slf4j.TelemereLogger sl)
|
||||
receiving?
|
||||
(and sending?
|
||||
|
|
|
|||
|
|
@ -14,24 +14,22 @@
|
|||
|
||||
(defmacro ^:private when-debug [& body] (when #_true false `(do ~@body)))
|
||||
|
||||
(deftype TelemereLogger [logger-ns]
|
||||
(deftype TelemereLogger [logger-name]
|
||||
|
||||
clojure.tools.logging.impl/Logger
|
||||
(enabled? [_ level]
|
||||
(when-debug (println [:tools-logging/enabled? logger-ns level]))
|
||||
(when-debug (println [:tools-logging/enabled? level logger-name]))
|
||||
(impl/signal-allowed?
|
||||
{:location nil
|
||||
:kind :log
|
||||
:id :taoensso.telemere/tools-logging
|
||||
{:location {:ns logger-name} ; Typically *ns* string
|
||||
:kind :tools-logging
|
||||
:level level}))
|
||||
|
||||
(write! [_ level throwable message]
|
||||
(when-debug (println [:tools-logging/write! logger-ns level]))
|
||||
(when-debug (println [:tools-logging/write! level logger-name]))
|
||||
(impl/signal!
|
||||
{:allow? true ; Pre-filtered by `enabled?` call
|
||||
:location nil
|
||||
:kind :log
|
||||
:id :taoensso.telemere/tools-logging
|
||||
:location {:ns logger-name} ; Typically *ns* string
|
||||
:kind :tools-logging
|
||||
:level level
|
||||
:error throwable
|
||||
:msg message})
|
||||
|
|
@ -39,8 +37,8 @@
|
|||
|
||||
(deftype TelemereLoggerFactory []
|
||||
clojure.tools.logging.impl/LoggerFactory
|
||||
(name [_ ] "taoensso.telemere")
|
||||
(get-logger [_ logger-ns] (TelemereLogger. (str logger-ns))))
|
||||
(name [_ ] "taoensso.telemere")
|
||||
(get-logger [_ logger-name] (TelemereLogger. (str logger-name))))
|
||||
|
||||
(defn tools-logging->telemere!
|
||||
"Configures `tools.logging` to use Telemere as its logging
|
||||
|
|
|
|||
|
|
@ -576,15 +576,14 @@
|
|||
|
||||
;;;; Intake
|
||||
|
||||
(comment (def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "MyTelemereSLF4JLogger")))
|
||||
(comment (def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class")))
|
||||
|
||||
#?(:clj
|
||||
(deftest _intake
|
||||
[(testing "`tools.logging` -> Telemere"
|
||||
[(is (sm? (tel/check-intakes) {:tools-logging {:present? true, :sending->telemere? true, :telemere-receiving? true}}))
|
||||
|
||||
(is (sm? (with-sig (ctl/info "Hello" "x" "y")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y", :inst pinst?}))
|
||||
(is (sm? (with-sig (ctl/warn "Hello" "x" "y")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/tools-logging, :msg_ "Hello x y", :inst pinst?}))
|
||||
(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"
|
||||
|
|
@ -604,12 +603,12 @@
|
|||
|
||||
(testing "SLF4J -> Telemere"
|
||||
[(is (sm? (tel/check-intakes) {:slf4j {:present? true, :sending->telemere? true, :telemere-receiving? true}}))
|
||||
(let [^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "MyTelemereSLF4JLogger")]
|
||||
(let [^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class")]
|
||||
[(testing "Basics"
|
||||
[(is (sm? (with-sig (.info sl "Hello")) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello", :inst pinst?}) "Legacy API: info basics")
|
||||
(is (sm? (with-sig (.warn sl "Hello")) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello", :inst pinst?}) "Legacy API: warn basics")
|
||||
(is (sm? (with-sig (-> (.atInfo sl) (.log "Hello"))) {:level :info, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello", :inst pinst?}) "Fluent API: info basics")
|
||||
(is (sm? (with-sig (-> (.atWarn sl) (.log "Hello"))) {:level :warn, :location nil, :ns nil, :kind :log, :id :taoensso.telemere/slf4j, :msg_ "Hello", :inst pinst?}) "Fluent API: warn basics")])
|
||||
[(is (sm? (with-sig (.info sl "Hello")) {:level :info, :ns "my.class", :kind :slf4j, :msg_ "Hello", :inst pinst?}) "Legacy API: info basics")
|
||||
(is (sm? (with-sig (.warn sl "Hello")) {:level :warn, :ns "my.class", :kind :slf4j, :msg_ "Hello", :inst pinst?}) "Legacy API: warn basics")
|
||||
(is (sm? (with-sig (-> (.atInfo sl) (.log "Hello"))) {:level :info, :ns "my.class", :kind :slf4j, :msg_ "Hello", :inst pinst?}) "Fluent API: info basics")
|
||||
(is (sm? (with-sig (-> (.atWarn sl) (.log "Hello"))) {:level :warn, :ns "my.class", :kind :slf4j, :msg_ "Hello", :inst pinst?}) "Fluent API: warn basics")])
|
||||
|
||||
(testing "Message formatting"
|
||||
(let [msgp "X is {} and Y is {}", expected {:msg_ "X is x and Y is y", :data {:slf4j/args ["x" "y"]}}]
|
||||
|
|
|
|||
Loading…
Reference in a new issue