androidloggingkotlinslf4jslf4j-api

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?


Solution

  • 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)
      }
    
    }