Welcome! Please see the About page for a little more info on how this works.

+1 vote
in tools.logging by

I am calling into some code that uses clojure.tools.logging and happens to produce a large number of INFO level log messages.

  • Is it possible to programatically (that is, not from some configuration file), and from the outside, suppress these messages for the duration of my call into this code?

If possible, I'd rather not need to know what logging factory is in play, etc...

In other projects, using taoensso.timbre, I have profitably used the with-level macro to accomplish similar things.

Thanks in advance for your time and consideration!

1 Answer

+3 votes
by
selected by
 
Best answer

If you simply want to disable all logging that happens in a certain call, you can tell tools.logging to use the provided disabled-logger-factory.

(require '[clojure.tools.logging :as log]
         '[clojure.tools.logging.impl :as log-impl])

(binding [log/*logger-factory* log-impl/disabled-logger-factory]
  (call-to-noisy-lib))

If you are looking to drop messages based on the originating namespace,
you can create your own LoggerFactory.

(def default-factory (log-impl/find-factory))

(def custom-factory
  (reify log-impl/LoggerFactory
    (name [_factory]
      "some.arbitrary.name.for.this.factory")
    (get-logger [factory logger-ns]
      (if (= "namespace.you.want.to.silence" (str logger-ns))
        log-impl/disabled-logger
        (log-impl/get-logger default-factory logger-ns)))))

(binding [log/*logger-factory* custom-factory]
  (call-to-noisy-lib))

If you addtionally want to filter based on the level of the message,
you'll need to implement a custom logger as well.

(defn logger-with-levels [wrapped-logger allowed-levels]
  (reify log-impl/logger
    (enabled? [logger level]
      (when (contains? allowed-levels level)
        (log-impl/enabled? wrapped-logger level)))
    (write! [logger level throwable message]
      (when (contains? allowed-levels level)
        (log-impl/write! wrapped-logger level throwable message)))))

(def custom-factory
  (reify log-impl/LoggerFactory
    (name [_factory]
      "some.arbitrary.name.for.this.factory")
    (get-logger [factory logger-ns]
      (if (= "namespace.you.want.to.silence" (str logger-ns))
        (logger-with-levels (log-impl/get-logger default-factory logger-ns) #{:warn})
        (log-impl/get-logger default-factory logger-ns)))))

There's room for improvement, polish, and optimization here, but it looks like all the necessary pieces are available to implement the desired functionality.

Personally, I'd lean towards putting this sort of thing in backend-specific configuration files, but that's explicitly not what you wanted. :)

by
I appreciate these helpful thoughts - reifying overrides in this way hadn't occurred to me. Thank you.
by
Just had this problem again, came back to this answer, and remembered how good it was. I wish I could give you another upvote. Thanks again!
...