Configuring MongoDB Java driver logging from Clojure using timbre

I’ve mentioned in the past how you can configure the MongoDB Java driver output from Java. Most Clojure applications that use MongoDB use a database driver that wraps the official MongoDB Java driver. I personally use monger for a lot of my projects, but also occasionally created my own wrapper. The methods described in this post should be applicable to other Clojure MongoDB drivers as long as they wrap the official MongoDB Java driver. They should also work if your application directly wraps the MongoDB Java driver itself rather than using a more idiomatic driver.

The MongoDB Java driver helpfully logs a lot of information via slf4j under the assumption that your application configures its output to an appropriate place. That’s all very nice if you already use slf4j and have it configured it accordingly. However, if you use Clojure (or you’re me) that’s probably not the case. At least I didn’t set up slf4j in any of my Clojure code.

Enter timbre. Timbre is a logging library for Clojure that optionally interoperates with Java logging libraries like slf4j. You can use the interop for slf4j via the slf4j-timbre library and most importantly for me, control the slf4j logging output from Clojure directly.

The timbre configuration for timbre 5.1 that I use in some of my Clojure projects  that interact with MongoDB is as follows:

(timbre/merge-config! {:min-level `[[#{"org.mongodb.*"} :error]]})

This configuration sets a minimum log level of error for any log output from the org.mongodb namespace. This is the namespace the Java driver uses for logging. Normally you wouldn’t just configure the minimum log level for the MongoDB Java driver, but for several different tools. As a result the timbre configuration for my projets tends to look more like this:

(timbre/merge-config! {:min-level `[[#{"org.mongodb.*"} :error] [#{"clj-ssh.*"} :warn] [#{"*"} :debug]]})

The configuration above sets a default minimum log output level of :debug. It also sets two additional log levels specific to the org.mongodb and clj-ssh namespaces. Obviously if you use other tools or have other namespaces that require special handling, you would add those to the configuration settings as well.

Note that using timbre and slj4f-timbre requires the following dependencies in project.clj:

:dependencies [[org.clojure/clojure        "1.10.0"]
               [com.taoensso/timbre        "5.1.0"] 
               [com.fzakaria/slf4j-timbre  "0.3.14"] ;; Attempt to send all log output through timbre
               [org.slf4j/jul-to-slf4j     "1.7.14"]]

Installing leiningen on Manjaro Linux

I like Lispy languages. One I’ve been playing with – and occasionally been using for smaller projects – is Clojure. Clojure projects usually use Leiningen for their build system. There are generally two ways to install leiningen – just download the script as per the Leiningen web site, or use the OS package manager. I usually prefer using the OS package manager, but Manjaro doesn’t include leiningen as a package in its repositories. Installing leiningen is pretty easy via the package manager and I’ll show you how.

Read More

Uncle Bob Martin discovered Clojure

Uncle Bob Martin discovered Clojure fairly recently and really, really likes it. Having had the privilege to see him speak at various SD West conferences back when they still were a thing, I wasn’t surprised by this. Anyway, do yourself a favour and spend a few minutes reading the article. It’s worth your time.

I also strongly agree with him that reading Structure and Interpretation of Computer Programs is very much worth the effort. It is a very well written book, especially as computer science textbooks go. It’s not going to land you a new job with the latest hotness in technology, but it will help you improve your knowledge of computer science fundamentals. Those fundamentals are allow you to build a long term career and going from an “XX programmer” to a well rounded software engineer.

 

Lisp like filtered container views in C++

Lisp dialects like Clojure have a very rich set of algorithms that can present altered views on containers without modifying data in the underlying container. This is very important in functional languages as data is immutable and returning copies of containers is costly despite the containers being optimised for copy-on-write. Having these algorithms available prevents unnecessary data copies. While I am not going into mutating algorithms in this post, the tradition of non-modifying alghorithms that work on containers leads to an expressiveness that I often miss in multi-paradigm languages like C++. As an example I will show you how to use a filtered container view in C++ like you would in Clojure.

Read More

Running a single Clojure test using leiningen

I’ve recently been working in Clojure on some code that really benefits from parallelization but doesn’t need to squeeze the last available cycle out of the machine.

Of course, if you’re using Clojure, you’re also using Leiningen as the universal build and configuration system. Accept no substitute. Now if I could only remember the syntax to run a single test when I’m refactoring some code and need to reflect the changes in the test suite via the build system and not just from inside the REPL?

Ah, here it is:

lein test :only TestNS/function

This is of course self-explanatory if one’s brain is running in clojure mode and not only the editor.