mirror of https://github.com/status-im/timbre.git
Merge pull request #34 from mopemope/rotor
Add Simple Rotating File Appender (mopemope)
This commit is contained in:
commit
afd8a87b11
|
@ -0,0 +1,80 @@
|
||||||
|
(ns taoensso.timbre.appenders.rotor
|
||||||
|
(:import
|
||||||
|
[java.io File FilenameFilter])
|
||||||
|
(:require
|
||||||
|
[clj-stacktrace.repl :as stacktrace]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[taoensso.timbre :as t]))
|
||||||
|
|
||||||
|
(defn- ^FilenameFilter file-filter
|
||||||
|
"Returns a Java FilenameFilter instance which only matches
|
||||||
|
files with the given `basename`."
|
||||||
|
[basename]
|
||||||
|
(reify FilenameFilter
|
||||||
|
(accept [_ _ name]
|
||||||
|
(.startsWith name basename))))
|
||||||
|
|
||||||
|
(defn- matching-files
|
||||||
|
"Returns a seq of files with the given `basepath` in the
|
||||||
|
same directory."
|
||||||
|
[basepath]
|
||||||
|
(let [f (-> basepath io/file (.getAbsoluteFile))]
|
||||||
|
(-> (.getParentFile f)
|
||||||
|
(.listFiles (file-filter (.getName f)))
|
||||||
|
seq)))
|
||||||
|
|
||||||
|
(defn- rotate-logs
|
||||||
|
"Performs log file rotation for the given files matching `basepath`
|
||||||
|
and up to a maximum of `max-count`. Historical versions are suffixed
|
||||||
|
with a 3-digit index, e.g.
|
||||||
|
|
||||||
|
logs/app.log ; current log file
|
||||||
|
logs/app.log.001 ; most recent log file
|
||||||
|
logs/app.log.002 ; second most recent log file etc.
|
||||||
|
|
||||||
|
If the max number of files has been reached, the oldest one
|
||||||
|
will be deleted. In future, there will be a suffix fn to customize
|
||||||
|
the naming of archived logs."
|
||||||
|
[basepath max-count]
|
||||||
|
(let [abs-path (-> basepath io/file (.getAbsolutePath))
|
||||||
|
logs (->> basepath
|
||||||
|
matching-files
|
||||||
|
(take max-count)
|
||||||
|
(map (fn [^File x] (.getAbsolutePath x)))
|
||||||
|
sort
|
||||||
|
reverse)
|
||||||
|
num-logs (count logs)
|
||||||
|
overflow? (> num-logs max-count)]
|
||||||
|
(when overflow?
|
||||||
|
(io/delete-file (first logs)))
|
||||||
|
(loop [[log & more] (if overflow? (rest logs) logs) n num-logs]
|
||||||
|
(when log
|
||||||
|
(.renameTo (io/file log) (io/file (format "%s.%03d" abs-path n)))
|
||||||
|
(recur more (dec n))))))
|
||||||
|
|
||||||
|
(defn appender-fn [{:keys [ap-config prefix throwable message]}]
|
||||||
|
(let [{:keys [path max-size backlog]
|
||||||
|
:or {max-size (* 1024 1024)
|
||||||
|
backlog 5}} (:rotor ap-config)]
|
||||||
|
(when path
|
||||||
|
(try
|
||||||
|
(when (> (.length (io/file path)) max-size)
|
||||||
|
(rotate-logs path backlog))
|
||||||
|
(spit path
|
||||||
|
(with-out-str
|
||||||
|
(t/str-println prefix "-" message
|
||||||
|
(t/stacktrace throwable)))
|
||||||
|
:append true)
|
||||||
|
(catch java.io.IOException _)))))
|
||||||
|
|
||||||
|
(def rotor-appender
|
||||||
|
{:doc (str "Simple Rotating File Appender.\n"
|
||||||
|
"Needs :rotor config map in :shared-appender-config, e.g.:
|
||||||
|
{:path \"logs/app.log\"
|
||||||
|
:max-size (* 512 1024)
|
||||||
|
:backlog 5}")
|
||||||
|
:min-level nil
|
||||||
|
:enabled? true
|
||||||
|
:async? false
|
||||||
|
:limit-per-msecs nil
|
||||||
|
:fn appender-fn})
|
Loading…
Reference in New Issue