forked from fzakaria/slf4j-timbre
-
Notifications
You must be signed in to change notification settings - Fork 0
/
configure.clj
176 lines (161 loc) · 5.43 KB
/
configure.clj
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
(ns slf4j-timbre.configure
"Timbre configuration.
Put `logging_filters.edn` file in your resources. The file should
contain a map of namespace prefixes (strings) to log levels."
(:require [taoensso.timbre :as timbre]
[clojure.string :as str]
[clojure.edn :as edn]
[clojure.java.io :as io]))
(defn filter-middleware
([levels data]
(let [ns-str (:?ns-str data "")
results (filter (fn [[k level]]
(and (.startsWith ns-str k)
(not (timbre/level>= (:level data) level))))
levels)]
(if (first results)
nil
data))))
(defn add-thread-name-middleware
"Addds :thread-name entry"
[data]
(assoc data :thread-name (.getName (Thread/currentThread))))
(defn output-context
[context]
(when (not-empty context)
(str
" ["
(->> context
(map (fn [[k v]]
(str (name k) ":" v)))
(interpose " ")
(apply str))
"]")))
(defn color-output-fn
"Default (fn [data]) -> string output fn.
Use`(partial color-output-fn <opts-map>)` to modify default opts."
([ data] (color-output-fn nil data))
([opts data] ; For partials
(let [{:keys [no-stacktrace? stacktrace-fonts]} opts
{:keys [level ?err #_vargs msg_ ?ns-str hostname_
timestamp_ ?line context]} data
color {:info :green :warn :yellow :error :red}]
(str
(force timestamp_) " "
(timbre/color-str (get color level :white) (format "%-5s"(str/upper-case (name level)))) " "
(timbre/color-str :cyan "[" (or ?ns-str "?") ":" (or ?line "?") "]") " "
(if-let [tn (:thread-name data)]
(format "[%s]" tn)
"[?]")
(output-context context)
" - "
(force msg_)
(when-not no-stacktrace?
(when-let [err ?err]
(str "\n" (timbre/stacktrace err opts))))))))
(defn plain-output-fn
"Default (fn [data]) -> string output fn.
Use`(partial default-output-fn <opts-map>)` to modify default opts."
([ data] (color-output-fn nil data))
([opts data] ; For partials
(let [{:keys [no-stacktrace? stacktrace-fonts]} opts
{:keys [level ?err #_vargs msg_ ?ns-str hostname_
timestamp_ ?line context]} data
color {:info :green :warn :yellow :error :red}]
(str
(force timestamp_) " "
(format "%-5s"(str/upper-case (name level))) " "
"[" (or ?ns-str "?") ":" (or ?line "?") "] "
(if-let [tn (:thread-name data)]
(format "[%s]" tn)
"[?]")
(output-context context)
" - "
(force msg_)
(when-not no-stacktrace?
(when-let [err ?err]
(str "\n" (timbre/stacktrace err opts))))))))
(defn assoc-output-fn
"put one of the predefinedd output-fns into the :println appender"
[timbre-config opts]
(assoc-in timbre-config
[:appenders :println :output-fn]
(if (:no-colors-in-logs? opts)
plain-output-fn
color-output-fn)))
(defn read-logging-filters
"minimum levels for different namespaces"
([] (read-logging-filters "logging_filters.edn"))
([f]
(if-let [r (io/resource
f
;; there's a bug in io/resource which NPEs
;; when the context ClassLoader is null
(or
(.getContextClassLoader (Thread/currentThread))
(ClassLoader/getSystemClassLoader)))]
(do
(timbre/info "found log filters in: " r)
(some-> r slurp edn/read-string))
(do
(timbre/warn "no logging_filters.edn resource found")
{}))))
(defn prepare-logging-config
[opts]
(let [logging-filters (->
(or (:logging-filters opts)
(some-> opts
:logging-filters-file
read-logging-filters))
(dissoc :root))
filters (partial filter-middleware logging-filters)
base-config timbre/example-config
base-config (if-not (:short-timestamp-in-logs? opts)
base-config
(assoc-in base-config
[:timestamp-opts :pattern]
"HH:mm:ss"))]
(-> base-config
(update :middleware into [filters add-thread-name-middleware])
(assoc-output-fn opts))))
(defn configure-timbre*
([]
(let [lfs (read-logging-filters)]
(configure-timbre*
{:logging-filters lfs})))
([{:keys [opts
level
environment
logging-filters]}]
(try
(let [l (or level
(:root logging-filters)
(condp = (some-> environment name)
"test" :warn
"production" :info
:debug))]
(timbre/info "applying timbre config: " l)
(timbre/set-level! l)
(timbre/set-config!
(prepare-logging-config opts))
;; set-config! overwrites the level
(timbre/set-level! l))
(catch Exception ex
(timbre/error "Failed to configure logging: " (.getMessage ex))
(throw ex)))))
(def ^:private configured (atom false))
(defn configure-timbre
[& args]
(swap!
configured
(fn [done?]
(apply configure-timbre* args)
true)))
(defn configure-timbre-once
[& args]
(swap!
configured
(fn [done?]
(when-not done?
(apply configure-timbre* args))
true)))