Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 775
user2870934 Avatar asked Oct 18 '22 03:10

user2870934


1 Answers

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.

like image 96
kurt Avatar answered Oct 21 '22 00:10

kurt