user2870934
user2870934

Reputation: 709

Kotlin extension log function with logback(slf4j)

I have create an extension function for logging:

import org.slf4j.LoggerFactory

fun Any.log(msg: String) {
    LoggerFactory.getLogger(javaClass.name).debug(msg)
}

But i'm not sure about will it be init any time when it will be called or not, because method LoggerFactory.getLogger invoking getILoggerFactory.

Mb someone already did something like that and can assure me that it's won't be any memory leaks :) ?

For now i using old fashion approach(of declaring logger field in a class):

companion object {
    private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name)
}

but a simple unit test like this:

@Test
fun testLogger() {
    val start = System.currentTimeMillis()
    for (i in 0..999) {
        log("i=" + i)
    }
    val end = System.currentTimeMillis()
    val time = end - start
    println("*** TIME=" + time.toDouble() / 1000 + " sec")
}

shows same result as with old fashion option:

@Test
fun testLogger() {
    val start = System.currentTimeMillis()
    for (i in 0..999) {
        logger.debug("i=" + i)
    }
    val end = System.currentTimeMillis()
    val time = end - start
    println("*** TIME=" + time.toDouble() / 1000 + " sec")
}

companion object {
    private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name)
}

~ *** TIME=0.02 sec

I'm using:

org.slf4j - 1.7.25
ch.qos.logback - 1.2.3

Upvotes: 5

Views: 2594

Answers (1)

kurt
kurt

Reputation: 1550

For logging, I could recommend another solution.

First, add interface ILogging and class LoggingImpl:

interface ILogging {
    val log: Logger
}

class LoggingImp(loggerImpl: Logger) : ILogging {
    override val log: Logger = loggerImpl

    companion object {
        operator inline fun <reified T> invoke(): LoggingImp {
            return LoggingImp(LoggerFactory.getLogger(T::class.java))
        }
    }
}

And now you could add logger to any class using Kotlin delegation:

class TestClass : ILogging by LoggingImp<TestClass>() {
    fun test() {
        log.info("test")
    }
}

Logger will be created when create parent object. Example of usage:

fun main(args: Array<String>) {
    val testClass = TestClass()

    testClass.test()
}

Hope, this will help you.

Upvotes: 3

Related Questions