יום חמישי, 7 ביולי 2016

Logging in Kotlin

The post was moved to: https://medium.com/@OhadShai/logging-in-kotlin-95a4e76388f2#.oiwog6cyw

TL;DR - for logging in kotlin use https://github.com/MicroUtils/kotlin-logging

In this blog post I am going to discuss logging frameworks for Kotlin language and JVM environment. Actually, logging seems like a solved problem in the JVM world. The de-facto standard is slf4j and there are plenty of examples in the internet like that:

private static final Logger logger = LoggerFactory.getLogger(ThisClass.class);
...
logger.info("Hi, {}", name);

That works perfectly in Kotlin with the relevant syntax adjustment

val logger = LoggerFactory.getLogger(ThisClass::class)
...
logger.info("Hi, {}", name)

So why not use it as is???


Yes, that is a valid option. However, Kotlin tries to improve readability of the code by making it more concise and fluent. I addition removing boilerplates (ie: copy-paste code) also makes the code cleaner and less error prone.

Is it a real problem or did I just made it up for that blog post?


There are evidences it is a real problem, or at least people are talking about it:

In addition, other JVM languages also tackled that problem.
In Scala we have the StrictLogging trait that exposes a logger member, thus helps avoiding defining the logger name.
In addition, lazy evaluation of the message in Scala assists in avoiding the notorious isDebugEnabled() call before each debug logging to avoid expensive string concatenation and values evaluation.

Is there something similar in Kotlin?


Yes there is. I have created kotlin-logging.
To use it add maven dependency:
<dependency>
  <groupId>io.github.microutils</groupId>
  <artifactId>kotlin-logging</artifactId>
  <version>1.3.2</version>
</dependency>
Then it is possible to get all the benefits like in Scala, but in kotlin using a companion object (unlike Scala where you can define properties in an interface).
The usage is to have the Companion object extends KLogging() and using the logger member in the class like that:
companion object: KLogging()
Then using the logger:
logger.info("hello world")
For sequences that are expected to be frequently used prefer lazy evaluated messages:
logger.debug{"lazy evaluated $message"}
In the above example String is inside a method and gets evaluated only if debug log level is enabled at runtime.

So, what are the benefits over the slf4j original implementation:

  • Getting the logger without the class name itself (excellent for copy paste)
  • Much cleaner messages with String templates and lazy evaluation
  • That's it - it is a small lib!

Are there any other alternatives? Yes there are quite a few:
  • Using plain slf4j
  • Many libraries, with not much traction at the moment
  • Implement it yourself

Hope you enjoy and spread the word of kotlin.logging.
Getting involved and support: