Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convenient Kotlin LoggerFactory simplification

What is the most convenient way to use SLF4J or other logging approaches with kotlin?

Usually the developer is busy with boilerplate code like

private val logger: Logger = LoggerFactory.getLogger(this::class.java)

in each and every class to get a proper logger?

What are the most convenient ways to unify/simplify this with Kotlin?

like image 935
Martin Mlostek Avatar asked Jan 02 '18 10:01

Martin Mlostek


2 Answers

You can define an extension property on every type:

val <T : Any> T.logger: Logger
    get() = LoggerFactory.getLogger(this::class.java)

use it as follows:

class X {
    init {
        logger.debug("init")
    }
}
like image 97
s1m0nw1 Avatar answered Sep 17 '22 13:09

s1m0nw1


Here's a simple example which returns a lazily-initialized logger from a bound callable reference or a standard property. I prefer calling from a callable reference because the :: denotes reflection (related to logging).

The class which provides the Lazy<Logger>:

class LoggingProvider<T : Any>(val clazz: KClass<T>) {

  operator fun provideDelegate(inst: Any?, property: KProperty<*>) =
      lazy { LoggerFactory.getLogger(clazz.java) }
}

Inline functions to call them:

inline fun <reified T : Any> KCallable<T>.logger() = 
  LoggingProvider(T::class)

inline fun <reified T : Any> T.logger() = 
  LoggingProvider(T::class)

Here's an example of using them. The require assertion in the initializer shows that the loggers share a reference:

class Foo {

  val self: Foo = this

  val logger by this.logger()
  val callableLogger by this::self.logger()

  init {
    require(logger === callableLogger)
  }

}
like image 22
Preston Garno Avatar answered Sep 19 '22 13:09

Preston Garno