Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding filter support to all appenders implementing UnsynchronizedAppenderBase #24

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion src/unilog/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ch.qos.logback.core.ConsoleAppender
ch.qos.logback.core.FileAppender
ch.qos.logback.core.OutputStreamAppender
ch.qos.logback.core.UnsynchronizedAppenderBase
ch.qos.logback.core.rolling.TimeBasedRollingPolicy
ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP
ch.qos.logback.core.rolling.FixedWindowRollingPolicy
Expand All @@ -34,7 +35,10 @@
ch.qos.logback.core.util.Duration
ch.qos.logback.core.util.FileSize
ch.qos.logback.core.net.SyslogOutputStream
net.logstash.logback.encoder.LogstashEncoder))
net.logstash.logback.encoder.LogstashEncoder
ch.qos.logback.classic.spi.ILoggingEvent
ch.qos.logback.core.filter.Filter
ch.qos.logback.core.spi.FilterReply))

;; Configuration constants
;; =======================
Expand Down Expand Up @@ -268,6 +272,33 @@
[val]
(throw (ex-info "invalid log appender configuration" {:config val})))

;;; build-filters
;;; =======================================
(def result-mapping {:accept FilterReply/ACCEPT
:deny FilterReply/DENY
:neutral FilterReply/NEUTRAL})

(defn make-log-property-filter
[field pred match no-match]
(let [match-enum (result-mapping match)
no-match-enum (result-mapping no-match)]
(proxy [Filter] []
(decide [^ILoggingEvent event]
(let [mdc (.getMDCPropertyMap event)
v (.get mdc (name field))]
(if (pred v)
match-enum
no-match-enum))))))

(defn build-filters
[config]
(let [{:keys [^Appender appender filters]} config]
(when (instance? UnsynchronizedAppenderBase appender)
(doseq [[field pred match no-match] filters]
(let [^Filter f (make-log-property-filter field pred match no-match)]
(.addFilter appender f))))
config))

;;; start-appender!
;;; =======================================
(defmulti start-appender!
Expand All @@ -291,11 +322,16 @@
(when (instance? ContextAware tp)
(.setContext ^ContextAware tp context))
(.start tp)))
(doseq [^Filter f (.getCopyOfAttachedFiltersList appender)]
(.start f))
(.start appender))

(defmethod start-appender! :default
[appender context]
(.setContext ^ContextAware appender ^LoggerContext context)
(when (instance? UnsynchronizedAppenderBase appender)
(doseq [^Filter f (.getCopyOfAttachedFiltersList ^UnsynchronizedAppenderBase appender)]
(.start f)))
(.start ^LifeCycle appender)
appender)

Expand Down Expand Up @@ -351,6 +387,7 @@ example:
(flatten)
(remove nil?)
(map build-appender)
(map build-filters)
(map build-encoder))]

(.detachAndStopAllAppenders root)
Expand Down
21 changes: 20 additions & 1 deletion test/unilog/config_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,23 @@
(is (= #{1} (reduce conj #{} (map get-version records))))
(is (= ["info" "warn" "error"] (map :message records)))
(is (= ["INFO" "WARN" "ERROR"] (map :level records)))
(is (= #{":bar"} (reduce conj #{} (map :foo records)))))))))
(is (= #{":bar"} (reduce conj #{} (map :foo records))))))))

(testing "JSON logging to file with filter"
(let [path (temp-file "unilog.config" "log")]
(start-logging! {:level :info :appenders [{:appender :file
:file (str path)
:encoder :json
:filters [[:foo #(= ":bar" %) :accept :deny]]}]})
(warn "warn")
(with-context {:foo :bar}
(info "info"))

(let [records (parse-lines path)]
(is (every? true? (map (comp check-interval get-timestamp) records)))
(is (= #{"unilog.config-test"} (reduce conj #{} (map :logger_name records))))
(is (= #{"main"} (reduce conj #{} (map :thread_name records))))
(is (= #{1} (reduce conj #{} (map get-version records))))
(is (= ["info"] (map :message records)))
(is (= ["INFO"] (map :level records)))
(is (= #{":bar"} (reduce conj #{} (map :foo records))))))))