I'm quite a fan of the Clojure programming language. I recently needed to log things in a webserver project I'm writing. I figured, how hard could it be ? Turns out it was more complicated than I thought.
Clojure.tools.logging is not simple
Clojure usually has some notion of simplicity. The logging part is not from the
standard library but is part of org.clojure
. But its implementation is not
easy from an outsider in the Java ecosystem. It basically adds a nice API that
wraps the standard loggers in Java.
Dependencies
You need :
clojure.tools.logging
for the API wrappersorg.slf4j/slf4j-api
for the Java APIch.qos.logback/logback-classic
for a logger implementation (you can use others)
Then, you can configure your logger using logback.xml
file. To do that though,
you need this file to be in your classpath. So you need to add your
resources
folder to your sources so that it's included in your classpath.
Like the following :
{:paths ["src"
; We include resources here to make it part of the classpath so that
; logback.xml logging config file is present and loaded correctly.
"resources"]
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
;; Logging
org.slf4j/slf4j-api {:mvn/version "1.7.30"}
org.clojure/tools.logging {:mvn/version "1.1.0"}
; Logger
ch.qos.logback/logback-classic {:mvn/version "1.2.3"}}}
Logback.xml configuration
You can configure the logging like the following way (in my case). Note that this can be configured very differently, just that the following covers my main use cases.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
This is a simple logger that just prints to stdout (which is nice in
containers/CLI applications) and defaults to printing INFO
levels.
Conclusion
It's not very difficult to set logging up in Clojure and it is quite powerful! It's also standardized and easy to tap into the existing ecosystem, which is nice.