mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-16 17:41:12 +00:00
[new] Add signal-allowed? util
Useful for using Telemere's filtering features without generating any signals, etc.
This commit is contained in:
parent
a9005e7f1c
commit
d12b0b145b
4 changed files with 118 additions and 31 deletions
|
|
@ -68,6 +68,7 @@
|
|||
#?(:clj impl/with-signal)
|
||||
#?(:clj impl/with-signals)
|
||||
#?(:clj impl/signal!)
|
||||
#?(:clj impl/signal-allowed?)
|
||||
|
||||
;; Utils
|
||||
utils/format-signal-fn
|
||||
|
|
|
|||
|
|
@ -381,6 +381,13 @@
|
|||
sample-rate kind ns id level when rate-limit,
|
||||
ctx parent root trace?, do let data msg error run & kvs]}])
|
||||
|
||||
:signal-allowed?
|
||||
'([{:as opts :keys
|
||||
[#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented
|
||||
elidable? location #_location* #_inst #_uid #_middleware,
|
||||
sample-rate kind ns id level when rate-limit,
|
||||
#_ctx #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}])
|
||||
|
||||
:event! ; [id] [id level-or-opts] => allowed?
|
||||
'([id ]
|
||||
[id level]
|
||||
|
|
@ -762,11 +769,27 @@
|
|||
(signal! {:level :info, :run "run"}))))
|
||||
|
||||
#?(:clj
|
||||
(defmacro signal-allowed?
|
||||
"Used only for interop (tools.logging, SLF4J, etc.)."
|
||||
{:arglists (signal-arglists :signal!)}
|
||||
(defmacro ^:public signal-allowed?
|
||||
"Returns true iff signal with given opts would meet filtering conditions:
|
||||
(when (signal-allowed? {:level :warn, <...>}) (my-custom-code))
|
||||
|
||||
Allows you to use Telemere's rich filtering system for conditionally
|
||||
executing arbitrary code. Also handy for batching multiple signals
|
||||
under a single set of conditions (incl. rate-limiting, sampling, etc.):
|
||||
|
||||
;; Logs exactly 2 or 0 messages (never 1):
|
||||
(when (signal-allowed? {:level :info, :sample-rate 0.5})
|
||||
(log! {:allow? true} \"Message 1\")
|
||||
(log! {:allow? true} \"Message 2\"))"
|
||||
|
||||
;; Used also for interop (tools.logging, SLF4J), etc.
|
||||
{:arglists (signal-arglists :signal-allowed?)}
|
||||
[opts]
|
||||
(let [{:keys [#_expansion-id #_location elide? allow?]}
|
||||
(have? map? opts)
|
||||
(let [defaults (get opts :defaults)
|
||||
opts (merge defaults (dissoc opts :defaults))
|
||||
|
||||
{:keys [#_expansion-id #_location elide? allow?]}
|
||||
(sigs/filterable-expansion
|
||||
{:sf-arity 4
|
||||
:ct-sig-filter ct-sig-filter
|
||||
|
|
@ -774,7 +797,9 @@
|
|||
(assoc opts :location*
|
||||
(get opts :location* (enc/get-source &form &env))))]
|
||||
|
||||
(and (not elide?) allow?))))
|
||||
(if elide? false `(if ~allow? true false)))))
|
||||
|
||||
(comment (macroexpand '(signal-allowed? {:level :info})))
|
||||
|
||||
;;;; Interop
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,10 @@
|
|||
|
||||
[(is (= sv1 (read-string (pr-str sv1))))])))
|
||||
|
||||
(is (sm? (with-sig (shell/signal! {:level :info})) {:level :info, :ns "taoensso.telemere-tests", :line :submap/some}) "Shell API")])
|
||||
(testing "Shell API"
|
||||
[(is (sm? (with-sig (shell/signal! {:level :info})) {:level :info, :ns "taoensso.telemere-tests", :line :submap/some}))
|
||||
(is (true? (tel/with-min-level :debug (shell/signal-allowed? {:level :debug}))))
|
||||
(is (false? (tel/with-min-level :debug (shell/signal-allowed? {:level :trace}))))])])
|
||||
|
||||
(deftest _handlers
|
||||
;; Basic handler tests are in Encore
|
||||
|
|
|
|||
|
|
@ -12,13 +12,58 @@
|
|||
(remove-ns 'taoensso.telemere.shell)
|
||||
(:api (enc/interns-overview)))
|
||||
|
||||
;;;; Private
|
||||
|
||||
#?(:clj
|
||||
(defmacro ^:private compile-if [test then else]
|
||||
(if (try (eval test) (catch Throwable _ false)) then else)))
|
||||
|
||||
(def ^:private telemere-present?
|
||||
"Is Telemere present (not necessarily loaded)?"
|
||||
(compile-if (jio/resource "taoensso/telemere.cljc") true false))
|
||||
#?(:clj
|
||||
(def ^:private telemere-present?
|
||||
"Is Telemere present (not necessarily loaded)?"
|
||||
(compile-if (jio/resource "taoensso/telemere.cljc") true false)))
|
||||
|
||||
#?(:clj
|
||||
(defn- require-telemere! []
|
||||
(try
|
||||
(require 'taoensso.telemere) ; For macro expansion
|
||||
(catch Exception e
|
||||
(throw
|
||||
(ex-info "Failed to require `taoensso.telemere` - `(require-telemere-if-present)` call missing?"
|
||||
{} e))))))
|
||||
|
||||
#?(:clj
|
||||
(defn- get-source "From Encore" [macro-form macro-env]
|
||||
(let [{:keys [line column file]} (meta macro-form)
|
||||
file
|
||||
(if-not (:ns macro-env)
|
||||
*file* ; Compiling Clj
|
||||
(or ; Compiling Cljs
|
||||
(when-let [url (and file (try (jio/resource file) (catch Exception _)))]
|
||||
(try (.getPath (jio/file url)) (catch Exception _))
|
||||
(do (str url)))
|
||||
file))
|
||||
|
||||
file
|
||||
(when (string? file)
|
||||
(when-not (contains? #{"NO_SOURCE_PATH" "NO_SOURCE_FILE" ""} file)
|
||||
file))
|
||||
|
||||
m {:ns (str *ns*)}
|
||||
m (if line (assoc m :line line) m)
|
||||
m (if column (assoc m :column column) m)
|
||||
m (if file (assoc m :file file) m)]
|
||||
m)))
|
||||
|
||||
#?(:clj
|
||||
(defn- signal-opts [macro-form macro-env opts]
|
||||
(if (map? opts)
|
||||
(conj {:location* (get-source macro-form macro-env)} (dissoc opts :fallback))
|
||||
(throw
|
||||
(ex-info "Signal opts must be a map"
|
||||
{:given {:value opts, :type (type opts)}})))))
|
||||
|
||||
;;;; Public
|
||||
|
||||
#?(:clj
|
||||
(defmacro if-telemere
|
||||
|
|
@ -92,28 +137,12 @@
|
|||
ctx parent root trace?, do let data msg error run & kvs]}])}
|
||||
|
||||
[opts]
|
||||
(if (map? opts)
|
||||
(if telemere-present?
|
||||
(do
|
||||
(try
|
||||
(require 'taoensso.telemere) ; For macro expansion
|
||||
(catch Exception e
|
||||
(throw
|
||||
(ex-info "Failed to require `taoensso.telemere` - `(require-telemere-if-present)` call missing?"
|
||||
{} e))))
|
||||
|
||||
(with-meta ; Keep callsite
|
||||
`(taoensso.telemere/signal! ~(dissoc opts :fallback))
|
||||
(meta &form)))
|
||||
|
||||
(let [fb-form (get opts :fallback)]
|
||||
(if-let [run-form (get opts :run)]
|
||||
`(let [run-result# ~run-form] ~fb-form run-result#)
|
||||
(do fb-form))))
|
||||
|
||||
(throw
|
||||
(ex-info "`signal!` expects map opts"
|
||||
{:given {:value opts, :type (type opts)}})))))
|
||||
(if telemere-present?
|
||||
(do (require-telemere!) `(taoensso.telemere/signal! ~(signal-opts &form &env opts)))
|
||||
(let [fb-form (get opts :fallback)]
|
||||
(if-let [run-form (get opts :run)]
|
||||
`(let [run-result# ~run-form] ~fb-form run-result#)
|
||||
(do fb-form))))))
|
||||
|
||||
(comment
|
||||
(macroexpand
|
||||
|
|
@ -123,3 +152,32 @@
|
|||
:msg ["Hello" "world" x]
|
||||
:data {:a :A :x x}
|
||||
:fallback (println (str "Hello world " x))})))
|
||||
|
||||
#?(:clj
|
||||
(defmacro signal-allowed?
|
||||
"Experimental, subject to change.
|
||||
Returns true iff Telemere is present and signal with given opts would meet
|
||||
filtering conditions.
|
||||
|
||||
MUST be used with `require-telemere-if-present`, example:
|
||||
|
||||
(ns my-lib (:require [taoensso.telemere.shell :as t]))
|
||||
(t/require-telemere-if-present) ; Just below `ns` form!
|
||||
|
||||
(when (t/signal-allowed? {:level :warn, <...>})
|
||||
(my-custom-code))"
|
||||
|
||||
{:arglists
|
||||
'([{:as opts :keys
|
||||
[#_fallback, ; Unique to shell
|
||||
#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented
|
||||
elidable? location #_location* #_inst #_uid #_middleware,
|
||||
sample-rate kind ns id level when rate-limit,
|
||||
#_ctx #_parent #_root #_trace?, #_do #_let #_data #_msg #_error #_run #_& #_kvs]}])}
|
||||
|
||||
[opts]
|
||||
(if telemere-present?
|
||||
(do (require-telemere!) `(taoensso.telemere/signal-allowed? ~(signal-opts &form &env opts)))
|
||||
(get opts :fallback nil))))
|
||||
|
||||
(comment (macroexpand '(signal-allowed? {:level :warn, :sample-rate 0.5})))
|
||||
|
|
|
|||
Loading…
Reference in a new issue