mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-16 17:41:12 +00:00
[mod] [#39] Remove shell API
This commit is contained in:
parent
706a8b6d37
commit
096c432eff
7 changed files with 5 additions and 297 deletions
|
|
@ -50,7 +50,6 @@
|
|||
[org.clojure/test.check "1.1.1"]
|
||||
[org.clojure/tools.logging "1.3.0"]
|
||||
[org.slf4j/slf4j-api "2.0.16"]
|
||||
[com.taoensso/telemere-shell "1.0.0-RC1"]
|
||||
[com.taoensso/telemere-slf4j "1.0.0-RC1"]
|
||||
#_[org.slf4j/slf4j-simple "2.0.16"]
|
||||
#_[org.slf4j/slf4j-nop "2.0.16"]
|
||||
|
|
|
|||
|
|
@ -561,7 +561,7 @@
|
|||
:arglists (signal-arglists :signal!)}
|
||||
|
||||
;; TODO Maybe later, once we're sure we don't want additional arities?
|
||||
;; Remember to also update signal-arglists, shell, etc.
|
||||
;; Remember to also update signal-arglists, etc.
|
||||
;; ([arg1 & more] (enc/keep-callsite `(signal! ~(apply hash-map arg1 more))))
|
||||
([opts]
|
||||
(have? map? opts) ; We require const map keys, but vals may require eval
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
:refer [signal! with-signal with-signals]
|
||||
:rename {signal! sig!, with-signal with-sig, with-signals with-sigs}]
|
||||
|
||||
[taoensso.telemere.shell :as shell]
|
||||
[taoensso.telemere.utils :as utils]
|
||||
[taoensso.telemere.timbre :as timbre]
|
||||
#_[taoensso.telemere.tools-logging :as tools-logging]
|
||||
|
|
@ -286,12 +285,7 @@
|
|||
(update-in [:inst] enc/inst->udt)
|
||||
(update-in [:end-inst] enc/inst->udt))]
|
||||
|
||||
[(is (= sv1 (read-string (pr-str sv1))))])))
|
||||
|
||||
(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}))))])])
|
||||
[(is (= sv1 (read-string (pr-str sv1))))])))])
|
||||
|
||||
(deftest _handlers
|
||||
;; Basic handler tests are in Encore
|
||||
|
|
|
|||
15
projects/shell/.gitignore
vendored
15
projects/shell/.gitignore
vendored
|
|
@ -1,15 +0,0 @@
|
|||
pom.xml*
|
||||
.lein*
|
||||
.nrepl-port
|
||||
*.jar
|
||||
*.class
|
||||
.env
|
||||
.DS_Store
|
||||
/lib/
|
||||
/classes/
|
||||
/target/
|
||||
/checkouts/
|
||||
/logs/
|
||||
/.clj-kondo/.cache
|
||||
.idea/
|
||||
*.iml
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
(defproject com.taoensso/telemere-shell "1.0.0-RC1"
|
||||
:author "Peter Taoussanis <https://www.taoensso.com>"
|
||||
:description "Minimal Telemere shell API for library authors, etc."
|
||||
:url "https://www.taoensso.com/telemere"
|
||||
|
||||
:license
|
||||
{:name "Eclipse Public License - v 1.0"
|
||||
:url "https://www.eclipse.org/legal/epl-v10.html"}
|
||||
|
||||
:scm {:name "git" :url "https://github.com/taoensso/telemere"}
|
||||
|
||||
:dependencies []
|
||||
:profiles
|
||||
{:provided
|
||||
{:dependencies
|
||||
[[org.clojure/clojurescript "1.11.132"]
|
||||
[org.clojure/clojure "1.12.0"]
|
||||
[com.taoensso/telemere "1.0.0-RC1"]]}
|
||||
|
||||
:dev
|
||||
{:plugins
|
||||
[[lein-pprint "1.3.2"]
|
||||
[lein-ancient "0.7.0"]
|
||||
[lein-cljsbuild "1.1.8"]]}}
|
||||
|
||||
:cljsbuild
|
||||
{:test-commands {"node" ["node" "target/test.js"]}
|
||||
:builds
|
||||
[{:id :main
|
||||
:source-paths ["src"]
|
||||
:compiler
|
||||
{:output-to "target/main.js"
|
||||
:optimizations :advanced}}
|
||||
|
||||
{:id :test
|
||||
:source-paths ["src" "test"]
|
||||
:compiler
|
||||
{:output-to "target/test.js"
|
||||
:target :nodejs
|
||||
:optimizations :simple}}]}
|
||||
|
||||
:aliases
|
||||
{"build-once" ["do" ["clean"] ["cljsbuild" "once"]]
|
||||
"deploy-lib" ["do" ["build-once"] ["deploy" "clojars"] ["install"]]})
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
(ns taoensso.telemere.shell
|
||||
"Experimental, subject to change.
|
||||
Minimal Telemere shell API for library authors, etc.
|
||||
Allows library code to use Telemere if it's present, or fall back to
|
||||
something like tools.logging otherwise."
|
||||
{:author "Peter Taoussanis (@ptaoussanis)"}
|
||||
#?(:clj (:require [clojure.java.io :as jio])
|
||||
:cljs (:require-macros [taoensso.telemere.shell :refer [compile-if]])))
|
||||
|
||||
(comment
|
||||
(require '[taoensso.telemere :as t] '[taoensso.encore :as enc])
|
||||
(remove-ns (symbol (str *ns*)))
|
||||
(:api (enc/interns-overview)))
|
||||
|
||||
;;;; Private
|
||||
|
||||
#?(:clj
|
||||
(defmacro ^:private compile-if [test then else]
|
||||
(if (try (eval test) (catch Throwable _ false)) then else)))
|
||||
|
||||
#?(: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
|
||||
"Evaluates to `then` form if Telemere is present when expanding macro.
|
||||
Otherwise expands to `else` form."
|
||||
([then ] (if telemere-present? then nil))
|
||||
([then else] (if telemere-present? then else))))
|
||||
|
||||
#?(:clj
|
||||
(defmacro require-telemere-if-present
|
||||
"Experimental, subject to change.
|
||||
Requires Telemere if it's present, otherwise noops.
|
||||
Used in cooperation with `signal!`, etc.
|
||||
|
||||
For Cljs:
|
||||
- MUST be placed at top of file, just below `ns` form
|
||||
- Needs ClojureScript >= v1.9.293 (Oct 2016)"
|
||||
[] (if-telemere `(require 'taoensso.telemere))))
|
||||
|
||||
(comment (require-telemere-if-present))
|
||||
|
||||
#?(:clj
|
||||
(defmacro set-min-level!
|
||||
"Expands to `taoensso.telemere/set-min-level!` call iff Telemere is present.
|
||||
Otherwise expands to `nil` (noops)."
|
||||
([ min-level] (if-telemere `(taoensso.telemere/set-min-level! ~min-level)))
|
||||
([kind min-level] (if-telemere `(taoensso.telemere/set-min-level! ~kind ~min-level)))
|
||||
([kind ns-filter min-level] (if-telemere `(taoensso.telemere/set-min-level! ~kind ~ns-filter ~min-level)))))
|
||||
|
||||
(comment (set-min-level! nil "my-ns(.*)" :warn))
|
||||
|
||||
#?(:clj
|
||||
(defmacro signal!
|
||||
"Experimental, subject to change.
|
||||
Telemere shell API for library authors, etc.
|
||||
|
||||
Expands to `taoensso.telemere/signal!` call if Telemere is present.
|
||||
Otherwise expands to arbitrary `fallback` opt form.
|
||||
|
||||
Allows library code to use Telemere if it's present, or fall back to
|
||||
something like tools.logging otherwise.
|
||||
|
||||
MUST be used with `require-telemere-if-present`, example:
|
||||
|
||||
(ns my-lib
|
||||
(:require
|
||||
[taoensso.telemere.shell :as t] ; `com.taoensso/telemere-shell` dependency
|
||||
[clojure.tools.logging :as ctl] ; `org.clojure/tools.logging` dependency
|
||||
))
|
||||
|
||||
(t/require-telemere-if-present) ; Just below `ns` form!
|
||||
|
||||
(t/signal!
|
||||
{:kind :log, :id :my-id, :level :warn,
|
||||
:let [x :x]
|
||||
:msg [\"Hello\" \"world\" x]
|
||||
:data {:a :A :x x}
|
||||
:fallback (ctl/warn (str \"Hello world\" x))})
|
||||
|
||||
For more info, see:
|
||||
- Telemere `signal!`, Ref. <https://www.taoensso.com/telemere/signal!>
|
||||
- Telemere docs, Ref. <https://www.taoensso.com/telemere>"
|
||||
|
||||
{:arglists #_(taoensso.telemere.impl/signal-arglists :signal!) ; + fallback
|
||||
'([{:as opts
|
||||
:keys
|
||||
[fallback, ; Unique to shell
|
||||
#_defaults #_elide? #_allow? #_expansion-id, ; Undocumented
|
||||
elidable? location #_location* inst uid middleware middleware+,
|
||||
sample-rate kind ns id level when rate-limit rate-limit-by,
|
||||
ctx ctx+ parent root trace?, do let data msg error run & kvs]}])}
|
||||
|
||||
[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
|
||||
'(signal!
|
||||
{:kind :log, :id :my-id, :level :warn,
|
||||
:let [x :x]
|
||||
: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 #_middleware+,
|
||||
sample-rate kind ns id level when rate-limit rate-limit-by,
|
||||
#_ctx #_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})))
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
Are you a library author/maintainer that's considering **using Telemere in your library**?
|
||||
|
||||
You have **two options** below-
|
||||
|
||||
# Options
|
||||
## 1. Common logging facade (basic logging only)
|
||||
|
||||
|
|
@ -31,49 +33,4 @@ The most common thing users may want to do is **adjust the minimum level** of si
|
|||
(defonce ^:private __set-default-log-level (set-min-log-level! :warn))
|
||||
```
|
||||
|
||||
This way your users can easily disable, decrease, or increase signal output from your library without even needing to touch Telemere or to be aware of its existence.
|
||||
|
||||
## 3. Telemere as an optional dependency
|
||||
|
||||
Include the (super lightweight) [Telemere shell API](https://clojars.org/com.taoensso/telemere-shell) in your **library's dependencies**.
|
||||
|
||||
Your library will then be able to emit structured logs/telemetry **when Telemere is present**, or fall back to something like [tools.logging](https://github.com/clojure/tools.logging) otherwise.
|
||||
|
||||
The main trade-off is that your signal calls will be more verbose:
|
||||
|
||||
```clojure
|
||||
(ns my-lib
|
||||
(:require
|
||||
[taoensso.telemere.shell :as t] ; `com.taoensso/telemere-shell` dependency
|
||||
[clojure.tools.logging :as ctl] ; `org.clojure/tools.logging` dependency
|
||||
))
|
||||
|
||||
(t/require-telemere-if-present) ; Just below `ns` form
|
||||
|
||||
;; Optional convenience for library users
|
||||
(defn set-min-level!
|
||||
"If it's present, sets Telemere's minimum level for <my-lib> namespaces.
|
||||
This will affect all signals (logs) created by <my-lib>.
|
||||
|
||||
Possible minimum levels (from most->least verbose):
|
||||
#{:trace :debug :info :warn :error :fatal :report}.
|
||||
|
||||
The default minimum level is `:warn`."
|
||||
[min-level]
|
||||
(t/if-telemere
|
||||
(do (t/set-min-level! nil \"my-lib(.*)\" min-level) true)
|
||||
false))
|
||||
|
||||
(defonce ^:private __set-default-min-level (set-min-level! :warn))
|
||||
|
||||
;; Creates Telemere signal if Telemere is present,
|
||||
;; otherwise logs with tools.logging
|
||||
(signal!
|
||||
{:kind :log, :id :my-id, :level :warn,
|
||||
:let [x :x]
|
||||
:msg [\"Hello\" \"world\" x]
|
||||
:data {:a :A :x x}
|
||||
:fallback (ctl/warn (str \"Hello world\" x))})
|
||||
```
|
||||
|
||||
See [here](https://cljdoc.org/d/com.taoensso/telemere-shell/CURRENT/api/taoensso.telemere.shell) for more info.
|
||||
This way your users can easily disable, decrease, or increase signal output from your library without even needing to touch Telemere or to be aware of its existence.
|
||||
Loading…
Reference in a new issue