Update 3rd-party appenders (rough)

This commit is contained in:
Peter Taoussanis 2015-05-26 01:28:32 +07:00
parent 014faa7bab
commit 3c824d31da
7 changed files with 185 additions and 167 deletions

View File

@ -1,41 +1,44 @@
(ns taoensso.timbre.appenders.android
"Android LogCat appender. Depends on the android runtime. This is a
configuration for the timbre logging library"
(ns taoensso.timbre.appenders.3rd-party.android
"Android LogCat appender. Requires Android runtime."
{:author "Adam Clements"}
(:require [taoensso.timbre :as timbre]
clojure.string))
(:require [clojure.string :as str]
[taoensso.timbre :as timbre]))
(defn make-logcat-appender
(defn make-appender
"Returns an appender that writes to Android LogCat. Obviously only works if
running within the Android runtime (device or emulator). You may want to
disable std-out to prevent printing nested timestamps, etc."
[& [appender-opts make-opts]]
(let [default-appender-opts {:enabled? true
:min-level :debug}]
(merge default-appender-opts appender-opts
{:fn (fn [{:keys [level ns throwable message]}]
(let [output (format "%s %s - %s" timestamp
(-> level name clojure.string/upper-case)
(or message ""))]
(if throwable
(case level
:trace (android.util.Log/d ns output throwable)
:debug (android.util.Log/d ns output throwable)
:info (android.util.Log/i ns output throwable)
:warn (android.util.Log/w ns output throwable)
:error (android.util.Log/e ns output throwable)
:fatal (android.util.Log/e ns output throwable)
:report (android.util.Log/i ns output throwable))
[& [appender-config make-config]]
(let [default-appender-config
{:enabled? true
:min-level :debug}]
(case level
:trace (android.util.Log/d ns output)
:debug (android.util.Log/d ns output)
:info (android.util.Log/i ns output)
:warn (android.util.Log/w ns output)
:error (android.util.Log/e ns output)
:fatal (android.util.Log/e ns output)
:report (android.util.Log/i ns output)))))})))
(merge default-appender-config appender-config
{:fn
(fn [data]
(let [{:keys [level ?ns-str ?err_ msg_ timestamp_]} data
msg (or (force msg_) "")
timestamp (force timestamp_)
ns (or ?ns-str "")
output (format "%s %s - %s" timestamp
(-> level name str/upper-case)
msg)]
(def logcat-appender
"DEPRECATED: Use `make-logcat-appender` instead."
(make-logcat-appender))
(if-let [throwable (force ?err_)]
(case level
:trace (android.util.Log/d ns output throwable)
:debug (android.util.Log/d ns output throwable)
:info (android.util.Log/i ns output throwable)
:warn (android.util.Log/w ns output throwable)
:error (android.util.Log/e ns output throwable)
:fatal (android.util.Log/e ns output throwable)
:report (android.util.Log/i ns output throwable))
(case level
:trace (android.util.Log/d ns output)
:debug (android.util.Log/d ns output)
:info (android.util.Log/i ns output)
:warn (android.util.Log/w ns output)
:error (android.util.Log/e ns output)
:fatal (android.util.Log/e ns output)
:report (android.util.Log/i ns output)))))})))

View File

@ -1,18 +1,20 @@
(ns taoensso.timbre.appenders.irc
"IRC appender. Depends on https://github.com/flatland/irclj."
(ns taoensso.timbre.appenders.3rd-party.irc
"IRC appender. Requires https://github.com/flatland/irclj."
{:author "Emlyn Corrin"}
(:require [clojure.string :as str]
[irclj.core :as irc]
[taoensso.timbre :as timbre]))
(defn default-fmt-output-fn
[{:keys [level throwable message]}]
[{:keys [level ?err_ msg_]}]
(format "[%s] %s%s"
(-> level name (str/upper-case))
(or message "")
(or (timbre/stacktrace throwable "\n") "")))
(-> level name (str/upper-case))
(or (force msg_) "")
(if-let [err (force ?err_)]
(str "\n" (timbre/stacktrace err))
"")))
(def default-appender-opts
(def default-appender-config
{:async? true
:enabled? true
:min-level :info})
@ -38,38 +40,36 @@
(irc/message conn chan ">" line))))
(defn- make-appender-fn [irc-config conn]
(fn [{:keys [ap-config] :as args}]
(when-let [irc-config (or irc-config (:irc ap-config))]
(ensure-conn conn irc-config)
(let [fmt-fn (or (:fmt-output-fn irc-config)
default-fmt-output-fn)]
(send-message conn (:chan irc-config) (fmt-fn args))))))
(fn [data]
(let [{:keys [appender-opts]} data]
(when-let [irc-config (or irc-config appender-opts)]
(ensure-conn conn irc-config)
(let [fmt-fn (or (:fmt-output-fn irc-config)
default-fmt-output-fn)]
(send-message conn (:chan irc-config) (fmt-fn data)))))))
;;; Public
(defn make-irc-appender
(defn make-appender
"Sends IRC messages using irc.
Needs :irc config map in :shared-appender-config, e.g.:
{:host \"irc.example.org\" :port 6667 :nick \"logger\"
:name \"My Logger\" :chan \"#logs\"}"
[& [appender-opts {:keys [irc-config]}]]
Needs :opts map in appender, e.g.:
{:host \"irc.example.org\" :port 6667 :nick \"logger\"
:name \"My Logger\" :chan \"#logs\"}"
[& [appender-config {:keys [irc-config]}]]
(let [conn (atom nil)]
(merge default-appender-opts
appender-opts
{:conn conn
:doc (:doc (meta #'make-irc-appender))
:fn (make-appender-fn irc-config conn)})))
(def irc-appender "DEPRECATED: Use `make-irc-appender` instead."
(make-irc-appender))
(merge default-appender-config appender-config
{:conn conn
:fn (make-appender-fn irc-config conn)})))
(comment
(timbre/set-config!
[:shared-appender-config :irc]
{:host "127.0.0.1"
:nick "lazylog"
:user "lazare"
:name "Lazylus Logus"
:chan "bob"})
(timbre/set-config! [:appenders :irc] (make-irc-appender))
(timbre/log :error "A multiple\nline message\nfor you"))
(timbre/merge-config! {:appenders {:irc (make-appender)}})
(timbre/merge-config!
{:appenders
{:irc
{:opts
{:host "127.0.0.1"
:nick "lazylog"
:user "lazare"
:name "Lazylus Logus"
:chan "bob"}}}})
(timbre/error "A multiple\nline message\nfor you"))

View File

@ -1,7 +1,9 @@
(ns taoensso.timbre.appenders.mongo
"MongoDB appender. Depends on https://github.com/aboekhoff/congomongo."
(ns taoensso.timbre.appenders.3rd-party.mongo
"MongoDB appender. Requires on https://github.com/aboekhoff/congomongo."
{:author "Emlyn Corrin"}
(:require [somnium.congomongo :as mongo]))
(:require [somnium.congomongo :as mongo]
[taoensso.timbre :as timbre]
[taoensso.encore :as encore]))
(def conn (atom nil))
@ -21,26 +23,28 @@
:as config}]
(let [selected-params (if logged-keys
(select-keys params logged-keys)
(dissoc params :ap-config))
logged-params (if-let [t (:throwable selected-params)]
(assoc selected-params :throwable (str t))
selected-params)]
(dissoc params :config :appender :appender-opts))
logged-params (encore/map-vals #(str (force %)) selected-params)]
(mongo/with-mongo (ensure-conn config)
(mongo/insert! collection logged-params))))
(defn appender-fn [{:keys [ap-config] :as params}]
(when-let [mongo-config (:mongo ap-config)]
(log-message params mongo-config)))
(defn- make-appender-fn [make-config]
(fn [data]
(let [{:keys [appender-opts]} data]
(when-let [mongo-config appender-opts]
(log-message data mongo-config)))))
(def mongo-appender
{:doc (str "Logs to MongoDB using congomongo.\n"
"Needs :mongo config map in :shared-appender-config, e.g.:
{:db \"logs\"
:collection \"myapp\"
:logged-keys [:instant :level :message]
:write-concern :acknowledged
:server {:host \"127.0.0.1\"
:port 27017}}")
:min-level :warn :enabled? true :async? true
:rate-limit [1 1000] ; 1 entry / sec
:fn appender-fn})
(defn make-appender
"Logs to MongoDB using congomongo. Needs :opts map in appender, e.g.:
{:db \"logs\"
:collection \"myapp\"
:logged-keys [:instant :level :msg_]
:write-concern :acknowledged
:server {:host \"127.0.0.1\"
:port 27017}}"
[& [appender-config make-config]]
(let [default-appender-config
{:min-level :warn :enabled? true :async? true
:rate-limit [[1 1000]]}]
(merge default-appender-config appender-config
{:fn (make-appender-fn make-config)})))

View File

@ -1,8 +1,10 @@
(ns taoensso.timbre.appenders.rolling "Rolling file appender."
(ns taoensso.timbre.appenders.3rd-party.rolling
"Rolling file appender."
{:author "Unknown - please let me know?"}
(:require [clojure.java.io :as io]
[taoensso.timbre :as timbre])
(:import [java.text SimpleDateFormat]
[java.util Calendar]))
(:import [java.text SimpleDateFormat]
[java.util Calendar]))
(defn- rename-old-create-new-log [log old-log]
(.renameTo log old-log)
@ -41,9 +43,11 @@
cal))
(defn- make-appender-fn [path pattern]
(fn [{:keys [ap-config output instant]}]
(let [path (or path (-> ap-config :rolling :path))
pattern (or pattern (-> ap-config :rolling :pattern) :daily)
(fn [data]
(let [{:keys [instant appender-opts output-fn]} data
output (output-fn data)
path (or path (-> appender-opts :path))
pattern (or pattern (-> appender-opts :pattern) :daily)
prev-cal (prev-period-end-cal instant pattern)
log (io/file path)]
(when log
@ -52,20 +56,20 @@
(if (<= (.lastModified log) (.getTimeInMillis prev-cal))
(shift-log-period log path prev-cal))
(.createNewFile log))
(spit path (with-out-str (timbre/str-println output)) :append true)
(spit path (with-out-str (println output)) :append true)
(catch java.io.IOException _))))))
(defn make-rolling-appender
(defn make-appender
"Returns a Rolling file appender.
A rolling config map can be provided here as a second argument, or provided at
:rolling in :shared-appender-config.
A rolling config map can be provided here as a second argument, or provided in
appender's :opts map.
(make-rolling-appender {:enabled? true}
{:path \"log/app.log\"
:pattern :daily})
path: logfile path
pattern: frequency of rotation, available values: :daily (default), :weekly, :monthly"
[& [appender-opts {:keys [path pattern]}]]
(let [default-appender-opts {:enabled? true :min-level nil}]
(merge default-appender-opts appender-opts
[& [appender-config {:keys [path pattern]}]]
(let [default-appender-config {:enabled? true :min-level nil}]
(merge default-appender-config appender-config
{:fn (make-appender-fn path pattern)})))

View File

@ -1,10 +1,8 @@
(ns taoensso.timbre.appenders.rotor
(ns taoensso.timbre.appenders.3rd-party.rotor
{:author "Yutaka Matsubara"}
(:import
[java.io File FilenameFilter])
(:require
[clojure.java.io :as io]
[taoensso.timbre :as t]))
(:require [clojure.java.io :as io]
[taoensso.timbre :as timbre])
(:import [java.io File FilenameFilter]))
(defn- ^FilenameFilter file-filter
"Returns a Java FilenameFilter instance which only matches
@ -45,25 +43,27 @@
(reverse (map vector logs-to-rotate (iterate inc 1)))]
(.renameTo log-file (io/file (format "%s.%03d" abs-path n))))))
(defn appender-fn [{:keys [ap-config output]}]
(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
(str output "\n")
:append true)
(catch java.io.IOException _)))))
(defn make-appender-fn [make-config]
(fn [data]
(let [{:keys [appender-opts output-fn]} data
{:keys [path max-size backlog]
:or {max-size (* 1024 1024)
backlog 5}} appender-opts]
(when path
(try
(when (> (.length (io/file path)) max-size)
(rotate-logs path backlog))
(spit path (str (output-fn data) "\n") :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
:fn appender-fn})
(defn make-appender
"Simple Rotating File Appender.
Needs :opts map in appender, e.g.:
{:path \"logs/app.log\"
:max-size (* 512 1024)
:backlog 5}"
[& [appender-config make-config]]
(let [default-appender-config
{:min-level :warn :enabled? true}]
(merge default-appender-config appender-config
{:fn (make-appender-fn make-config)})))

View File

@ -1,10 +1,10 @@
(ns taoensso.timbre.appenders.socket
"TCP Socket appender. Depends on https://github.com/technomancy/server-socket."
(ns taoensso.timbre.appenders.3rd-party.socket
"TCP socket appender. Requires https://github.com/technomancy/server-socket."
{:author "Emlyn Corrin"}
(:require [server.socket :refer [create-server]]
[taoensso.timbre :refer [stacktrace]])
(:import [java.net Socket InetAddress]
[java.io BufferedReader InputStreamReader PrintWriter]))
(:import [java.net Socket InetAddress]
[java.io BufferedReader InputStreamReader PrintWriter]))
(def conn (atom nil))
@ -30,19 +30,23 @@
(defn ensure-conn [socket-config]
(swap! conn #(or % (connect socket-config))))
(defn appender-fn [{:keys [ap-config prefix message throwable] :as params}]
(when-let [socket-config (:socket ap-config)]
(let [c (ensure-conn socket-config)]
(doseq [sock @(:connections c)]
(let [out (PrintWriter. (.getOutputStream ^Socket sock))]
(binding [*out* out]
(println prefix message
(stacktrace throwable))))))))
(defn make-appender-fn [make-config]
(fn [data]
(let [{:keys [appender-opts output-fn ?err_]} data]
(when-let [socket-config appender-opts]
(let [c (ensure-conn socket-config)]
(doseq [sock @(:connections c)]
(let [out (PrintWriter. (.getOutputStream ^Socket sock))]
(binding [*out* out]
(println (output-fn data))))))))))
(def socket-appender
{:doc (str "Logs to a listening socket.\n"
"Needs :socket config map in :shared-appender-config, e.g.:
{:listen-addr :all
:port 9000}")
:min-level :trace :enabled? true
:fn appender-fn})
(defn make-appender
"Logs to a listening socket.
Needs :opts map in appender, e.g.:
{:listen-addr :all
:port 9000}"
[& [appender-config make-config]]
(let [default-appender-config
{:min-level :trace :enabled? true}]
(merge default-appender-config appender-config
{:fn (make-appender-fn make-config)})))

View File

@ -1,34 +1,37 @@
(ns taoensso.timbre.appenders.zmq
(ns taoensso.timbre.appenders.3rd-party.zmq
"ØMQ appender. Requires https://github.com/zeromq/cljzmq"
{:author "Angus Fletcher"}
(:require [zeromq.zmq :as zmq]
(:require [zeromq.zmq :as zmq]
[taoensso.timbre :as timbre]))
(defn make-zmq-socket [context transport address port]
(doto (zmq/socket context :push)
(zmq/connect (format "%s://%s:%d" transport address port))))
(defn appender-fn [socket poller {:keys [ap-config output]}]
(loop []
(zmq/poll poller 500)
(cond
(zmq/check-poller poller 0 :pollout) (zmq/send-str socket output)
(zmq/check-poller poller 0 :pollerr) (System/exit 1)
:else (recur))))
(defn make-appender-fn [socket poller]
(fn [data]
(let [{:keys [appender-opts output-fn]} data
output (output-fn data)]
(loop []
(zmq/poll poller 500)
(cond
(zmq/check-poller poller 0 :pollout) (zmq/send-str socket output)
(zmq/check-poller poller 0 :pollerr) (System/exit 1)
:else (recur))))))
(defn make-zmq-appender
(defn make-appender
"Returns a ØMQ appender. Takes appender options and a map consisting of:
transport: a string representing transport type: tcp, ipc, inproc, pgm/epgm
address: a string containing an address to connect to.
port: a number representing the port to connect to."
[& [appender-opts {:keys [transport address port]}]]
(let [default-appender-opts {:enabled? true
:min-level :error
:async? true}
[& [appender-config {:keys [transport address port]}]]
(let [default-appender-config
{:enabled? true
:min-level :error
:async? true}
context (zmq/zcontext)
socket (make-zmq-socket context transport address port)
poller (doto (zmq/poller context)
(zmq/register socket :pollout :pollerr))]
(merge default-appender-opts
appender-opts
{:fn (partial appender-fn socket poller)})))
(merge default-appender-config appender-config
{:fn (make-appender-fn socket poller)})))