Lazily Initializing Implicit Logger in Every Class in Kotlin
Tags: kotlin, jvm, logging, java
Published: 2023-03-15 07:17:26

---
title: Lazily Initializing Implicit Logger in Every Class in Kotlin
published: true
date: 2023-01-30 00:12:00 UTC
tags: kotlin,jvm,logging,java
canonical_url: https://blog.dripto.xyz/lazily-initializing-implicit-logger-in-every-class-in-kotlin
cover_image: https://cdn.hashnode.com/res/hashnode/image/upload/v1675034932530/7a586102-a340-4a1f-9264-9c063b55082f.png?w=1600&h=840&fit=crop&crop=entropy&auto=compress,format&format=webp
---

## How Kotlin(JVM) logger declaration works

If you're familiar with the Kotlin programming language on the JVM platform, you may have encountered the need for logging in your projects. Typically, this requires declaring a logger for each class in your code, using a library such as slf4j. While this approach is functional, it can become tedious and repetitive, especially as the number of classes in your project increases. In this blog, we'll explore an alternative method for class-level logging in Kotlin JVM that leverages implicit loggers, streamlining the process and reducing the boilerplate code you need to write.

A typical logger declaration using slf4j in Kotlin JVM may look like the following code sample:

```kotlin
import org.slf4j.LoggerFactory

class Test {
    val log = LoggerFactory.getLogger(Test::class.java)

    fun doSomething() {
        log.info("doing things")
    }
}

```

It's worth noting that if you choose to use a different logging framework, such as log4j2 or kotlin-logging, the code for declaring a logger may look different. For instance, here's a code sample for declaring a logger using kotlin-logging:

```kotlin
private val logger = KotlinLogging.logger {}

```

The syntax may vary based on the specific logging framework you choose, but the overall process of declaring a logger for each class remains the same.

## How Lombok does this with less boilerplate in Java

If you're familiar with Java, you may have encountered Lombok, a library that reduces boilerplate code in your Java projects. One aspect of Lombok that can be particularly useful for logging is its ability to simplify the declaration of class-level loggers. With Lombok, a logger declaration can be reduced to just a single annotation, as demonstrated in this code sample:

```java
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ExampleClass {
  public static void main(String... args) {
    log.error("Something is wrong here");
  }
}

```

In this example, the `@Slf4j` annotation generates a logger for the class using the slf4j framework. This greatly reduces the amount of code you need to write for logging, making it a convenient and efficient solution for logging in Java projects. While Kotlin does not have a direct equivalent to Lombok, there is another approache to streamlining logging that we'll explore in this blog.

## Can we do something better in Kotlin?

As it turned out, we can.

Fortunately, Kotlin provides features that allow us to improve upon the standard method of declaring loggers for each class. One such feature is reified type parameters, which enables the creation of inline extension variables with preserved type information. With this in mind, we can create an inline extension variable that acts as an implicit logger for a class. The reified generics allow us to fetch class details to pass to the logger creation, and by storing the created loggers in a hashmap, we can avoid redundant recreations and ensure constant lookup times.

```kotlin
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import kotlin.reflect.KClass

val loggerMap = hashMapOf<KClass<*>, Logger>()
inline val <reified T> T.log: Logger
    get() = loggerMap.getOrPut(T::class) {
        LoggerFactory.getLogger(
            if (T::class.isCompanion) T::class.java.enclosingClass else T::class.java)
    }

```

Once this code is in classpath, declaring a logger for a class becomes incredibly simple. That is, you don't have to declare anything at all, just go ahead and use the `log` variable and Kotlin compiler will create one for you the first time it is used.

```kotlin
class Test {
    fun doSomething() {
        log.info("doing things")
    }
}

```

This reduces the amount of code required and makes the logging process more efficient and less prone to error. You can even put it in a library and use it for multiple applications.

Whether you're a seasoned developer or just starting out with Kotlin, implementing an implicit logger is a great way to streamline your logging process and save time in your development workflow. So, give it a try and see how it can simplify your projects.