[mod] [#39] Remove shell API

This commit is contained in:
Peter Taoussanis 2024-12-20 16:22:15 +01:00
parent 706a8b6d37
commit 096c432eff
7 changed files with 5 additions and 297 deletions

View file

@ -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"]

View file

@ -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

View file

@ -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

View file

@ -1,15 +0,0 @@
pom.xml*
.lein*
.nrepl-port
*.jar
*.class
.env
.DS_Store
/lib/
/classes/
/target/
/checkouts/
/logs/
/.clj-kondo/.cache
.idea/
*.iml

View file

@ -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"]]})

View file

@ -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})))

View file

@ -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.