-
-
Notifications
You must be signed in to change notification settings - Fork 137
/
logging.cljc
116 lines (97 loc) · 5.12 KB
/
logging.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
(ns fulcro.logging
"Utilities for logging on the client and server.
This namespace exists so that fulcro libraries have a mechanism to do logging that can be lightweight without
pull in any additional dependencies. You can use this logging support, but it is not designed to be great, just
lightweight and efficient.
It is highly recommended that you use a dedicated logging library in production apps, such as timbre. However, if
you're writing an add-on for Fulcro it is probably best to use this logging so you give our users a consistent
way to deal with Fulcro logging."
#?(:cljs (:require-macros fulcro.logging))
(:require
[clojure.string :as str]
[clojure.stacktrace :as strace]
#?@(:cljs ([goog.log :as glog]
[goog.object :as gobj]
[goog.debug.Logger.Level :as level])))
#?(:cljs (:import [goog.debug Console])))
(def logging-priority {:all 100 :trace 6 :debug 5 :info 4 :warn 3 :error 2 :fatal 1 :none 0})
(defn should-log?
"Returns true if the current logging level indicates that the message level is of interest."
[current-logging-level message-level]
(let [c (get logging-priority current-logging-level 4)
m (get logging-priority message-level 4)]
(<= m c)))
(defonce ^:private current-logging-level
(atom 0))
#?(:cljs
(def level-map
(let [levels [:all :trace :debug :info :error :warn :fatal]
glevels ["ALL" "FINE" "FINE" "INFO" "SEVERE" "WARNING" "SEVERE"]]
(zipmap levels (map #(level/getPredefinedLevel %) glevels)))))
(defonce ^:private logger
(do
#?(:cljs
(when ^boolean goog.DEBUG
(.setCapturing (Console.) true)))
(atom (fn built-in-logger [{:keys [file line]} level & args]
(when (should-log? @current-logging-level level)
(let [location (str (or file "?") ":" (or line "?"))]
#?(:cljs (let [logger (glog/getLogger file)
first-exception (first (filter #(instance? js/Error %) args))
message (str/join " " args)]
(when logger
(.log logger (get level-map level (:info level-map)) message first-exception)))
:clj (println (str (-> level name str/upper-case) " [" location "] : " (str/join " " args))))))))))
#?(:clj
(defmacro system-log-level
"Get the current runtime JVM system logging level from fulcro.logging. Works for clj and cljs."
[]
(some->
(System/getProperty "fulcro.logging")
keyword)))
(defn -log
"Private implementation for macro output. Use `log` instead."
[location level & things-to-print]
(when @logger
(apply @logger location level things-to-print)))
(defn- log* [])
(defn fline [and-form] (some-> and-form meta :line))
#?(:clj
(defmacro log
"Logs to the current global logging function, which can be set in the top-level logger atom.
If you set the JVM option to something like -Dfulcro.logging=error then this macro will not output
any code for logging below that level.
level - one of :trace, :debug, :info, :warn, :error, or :fatal.
things-to-include - Any number of additional things to log. The logging function may give special treatment
to certain types (e.g. exceptions).
See `set-logger!`."
[logging-level & things-to-include]
(let [l (system-log-level)
has-options? (map? logging-level)
level (if has-options? (:level logging-level) logging-level)
elide? (and l (not (should-log? l level)))]
(when-not elide?
(let [file (or (some-> &env :ns :name str) (some-> *ns* ns-name str) "?")
line (or (and has-options? (:line logging-level)) (fline &form) "?")
js? (some-> &env :ns :name)
location {:file file :line line}]
`(try
(fulcro.logging/-log ~location ~level ~@things-to-include)
(catch ~(if js? 'js/Error 'Exception) e#
(fulcro.logging/-log ~location ~level "Log statement failed (arguments did not evaluate)." e#))))))))
(defn set-level! [log-level]
"Takes a keyword (:all, :trace, :debug, :info, :warn, :error, :fatal, :none) and changes the runtime log level accordingly.
Note that the log levels are listed from least restrictive level to most restrictive.
The system property fulcro.logging can be set on the JVM to cause elision of logging statements from code."
(reset! current-logging-level (get logging-priority log-level 2)))
(defn set-logger!
"Set the fulcro logging function.
log-fn - A (fn [{:keys [file line] :as location} level & args] ...)"
[log-fn]
(reset! logger log-fn))
(defmacro trace [& args] `(log {:line ~(fline &form) :level :trace} ~@args))
(defmacro debug [& args] `(log {:line ~(fline &form) :level :debug} ~@args))
(defmacro info [& args] `(log {:line ~(fline &form) :level :info} ~@args))
(defmacro warn [& args] `(log {:line ~(fline &form) :level :warn} ~@args))
(defmacro error [& args] `(log {:line ~(fline &form) :level :error} ~@args))
(defmacro fatal [& args] `(log {:line ~(fline &form) :level :fatal} ~@args))