Karsten Schmidt avatar Karsten Schmidt committed 1bbd1dd

setting version: 0.1.0, bug fix rotate-logs fn, renaming config keys, updating readme

Comments (0)

Files changed (3)

 # rotor
 
-A simple rotating generic log file appender with (optional) support for [Timbre](https://github.com/ptaoussanis/timbre), a new Clojure logging library.
+A simple rotating log file appender for Clojure. Has no dependencies, but is designed to work with [Timbre](https://github.com/ptaoussanis/timbre), a new Clojure logging library.
 
 ## Leiningen coordinates
 
     
     (t/set-config!
       [:appenders :rotor]
-      {:doc "Writes to to (:filename (:rotor :shared-appender-config)) file
+      {:doc "Writes to to (:path (:rotor :shared-appender-config)) file
              and creates optional backups."
        :min-level :info
        :enabled? true
     :::clojure
     (t/set-config!
       [:shared-appender-config :rotor]
-      {:filename "logs/app.log" :max-size (* 512 1024) :history 5})
+      {:path "logs/app.log" :max-size (* 512 1024) :backlog 5})
 
-Only the `:filename` arg is mandatory and can be a relative or absolute path. `:max-size` and `:history` default to the values shown...
+Only the `:path` arg is mandatory and can be a relative or absolute path (any parent dirs must be existing & writable). The `:max-size` and `:backlog` args default to the values shown above: 512KB limit and backlog of 5 files...
 
-Once the log file's size limit has been reached, log rotation is triggered up to a backlog of `:history` files. These backups are suffixed with a 3-digit index, with larger numbers indicating age, e.g.
+Once the log file's size limit has been reached, log rotation is triggered up to `:backlog` files. These backups are suffixed with a 3-digit index, with larger numbers indicating older age, e.g.
 
+    :::text
     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.
 
+Any IOExceptions occuring during logging will be silently ignored.
+
 ## License
 
 Copyright © 2012 Karsten Schmidt // PostSpectacular Ltd.
-(defproject com.postspectacular/rotor "0.1.0-SNAPSHOT"
+(defproject com.postspectacular/rotor "0.1.0"
   :description "A simple rotating log file appender, e.g. for Timbre."
   :url "http://hg.postspectacular.com/rotor/"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.4.0"]
-                 [com.taoensso/timbre "1.1.0"]])
+  :dependencies [[org.clojure/clojure "1.4.0"]]
+  :profiles {:test {:dependencies [[com.taoensso/timbre "1.1.0"]]}})

src/com/postspectacular/rotor.clj

 
 (defn file-filter
   "Returns a Java FilenameFilter instance which only matches
-  files with the given `base-name`."
-  [base-name]
+  files with the given `basename`."
+  [basename]
   (reify FilenameFilter
     (accept [_ _ name]
-      (.startsWith name base-name))))
+      (.startsWith name basename))))
 
 (defn matching-files
-  "Returns a seq of files with the given base `name` in the
+  "Returns a seq of files with the given `basepath` in the
   same directory."
-  [name]
-  (let [f (-> name io/file (.getAbsoluteFile))]
+  [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 `base-path`
+  "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.
 
   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."
-  [base-path max-count]
-  (let [abs-path (-> base-path io/file (.getAbsolutePath))
-        [oldest :as logs] (->> base-path
-                             matching-files
-                             (take max-count)
-                             (map #(.getAbsolutePath %))
-                             sort
-                             reverse)
-        num-logs (count logs)]
-    (when (>= num-logs max-count)
-      (io/delete-file oldest))
-    (loop [[l & more] logs n num-logs]
-      (when l
-        (.renameTo (io/file l)
-                   (io/file (format "%s.%03d" abs-path n)))
+  [basepath max-count]
+  (let [abs-path (-> basepath io/file (.getAbsolutePath))
+        logs (->> basepath
+                  matching-files
+                  (take max-count)
+                  (map #(.getAbsolutePath %))
+                  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 append
 
       (timbre/set-config!
         [:shared-appender-config :rotor]
-        {:filename \"logs/app.log\"
+        {:path \"logs/app.log\"
          :max-size (* 512 1024)
-         :history 5})
+         :backlog 5})
 
   The above settings will write to a file `logs/app.log` in the project folder,
   with a max file size of 512KB and a backlog of 5 files.
 
-  Use the following config as template to use this fn as appender for Timbre:
+  Use the following config as template to create a new appender for Timbre:
 
       (timbre/set-config!
         {:doc \"Writes to (:filename (:rotor :shared-appender-config)) file and
                 creates optional backups.\"
-         :min-level nil
+         :min-level :info
          :enabled? true
          :async? false ; should be always false for rotor
          :max-message-per-msecs nil
          :fn rotor/appender})"
   [{:keys [ap-config prefix message more]}]
-  (let [{:keys [filename max-size history]
+  (let [{:keys [path max-size backlog]
          :or   {max-size (* 1024 1024)
-                history 5}} (:rotor ap-config)]
-    (when filename
+                backlog 5}} (:rotor ap-config)]
+    (when path
       (try
-        (when (> (.length (io/file filename)) max-size)
-          (rotate-logs filename history))
-        (spit filename
+        (when (> (.length (io/file path)) max-size)
+          (rotate-logs path backlog))
+        (spit path
               (with-out-str
                 (apply str-println prefix "-" message more))
               :append true)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.