Skip to content
Ohad Shai edited this page Jan 12, 2024 · 42 revisions

Welcome to the kotlin-logging wiki!

Javadocs can be found in: https://oshai.github.io/kotlin-logging/api/

kotlin-logging is a lightweight logging framework for Kotlin. A convenient and performant logging library wrapping slf4j with Kotlin extensions kotlin-logging provides both:

  • Idiomatic way to obtain a logger without the need to specify class name
  • Enhanced logging api that integrates fluently with Kotlin

Install

Important note: kotlin-logging is a facade so a backend dependency needs to be added. In JVM the recommended dependency is slf4j-api. At runtime, it is also required to depend on a logging implementation. More details here.

Maven

<dependency>
  <groupId>io.github.oshai</groupId>
  <artifactId>kotlin-logging-jvm</artifactId>
  <version>5.0.0</version>
</dependency>

See full example in kotlin-logging-example-maven.

Gradle

compile 'io.github.oshai:kotlin-logging-jvm:4.0.0'

Or alternatively, download jar from github or maven-central.

Usage

Obtaining a logger

The preferred way to obtain a logger is as follows:

import io.github.oshai.kotlinlogging.KotlinLogging

// Place definition above class declaration, below imports, 
// to make field static and accessible only within the file
private val logger = KotlinLogging.logger {}

Another option (less recommended) is to have the Companion object extends KLogging():

companion object: KLogging()

In cases the Companion object already extending other class it is recommended to implement the KLoggable interface:

companion object: Any(), KLoggable {
  override val logger = logger()
  ...
}

Other (less recommended) alternatives are:

companion object: Any(), KLoggable by NamedKLogging("com.MyClass")

Or implementing it as a non static member:

class ClassHasLogging: KLoggable {
    override val logger = logger()
}

all examples also available in tests.

Usage of logger

The most simple use is the same as with java logger:

logger.info("hello message")

For sequences that are expected to be frequently used or costly prefer lazily evaluated messages:

logger.debug { "lazy evaluated $hello message" }

(Message is in lambda and gets evaluated only if debug log level is enabled at runtime)

When logging exceptions, it is also possible to use a lambda expression to calculate the attached message:

logger.error(exception) { "a $fancy message about the $exception" }

The complete list of methods can be found in KLogger source code.

Mapped Diagnostic Context (MDC) Support

MDC allows adding implicit context data such as user id to all log messages base on the caller thread. More details can be found on https://www.slf4j.org/manual.html#mdc.

In kotlin-logging it is possible to set MDC properties to be used later in a lambda that way:

import io.github.oshai.kotlinlogging.withLoggingContext

...

withLoggingContext("userId" to userId) {
  doSomething()
}

Providing multiple values is also supported. See: KotlinLoggingMDC source code.

MDC and threads/coroutines

Under the hood, MDC uses ThreadLocal value to keep the content on the thread. When using thread pools or coroutines the data should be transported between the threads. Coroutines have support for it in the following way:

withLoggingContext("kotlin" to "the moon") {
  launch(MDCContext()) {
    logger.info { "..." }   // the MDC context will contain the mapping here
  }
}
  • In order to use it add the following additional dependency: compile "org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:<version>". More details in kotlinx-coroutines-slf4j.

Getting the actual Logger

In some cases, it is essential to get the actual Logger to use its specific features. In such cases use the underlyingLogger property like that:

logger.underlyingLogger

More details and examples here: https://github.com/oshai/kotlin-logging/issues/20

FAQ

Q: Is method line reporting supported?

A: Yes. More details here: https://github.com/oshai/kotlin-logging/issues/11

Q: Are colored logs supported?

A: As with other framework specific features it is supported and should be configured in the logging framework itself. More details here: https://github.com/oshai/kotlin-logging/issues/24

Q: What is the minimal Gradle dependency that I need in order for kotlin-logging to work and print my messages?

A: See below, versions might change:

implementation 'io.github.oshai:kotlin-logging-jvm:4.0.0'
implementation 'org.slf4j:slf4j-simple:2.0.3'

Q: Android R8 seems corrupting the logger name, what can I do?

A: In most cases the below setting for the logger should work:

companion object {
    private val logger = KotlinLogging.logger {}
}

See more details in #115.

Q: What happen if an exception is thrown when creating a log message?

A: By default it will log a message saying: Log message invocation failed: ...

In JVM, it is possible to change it to throw an exception by adding system property to jvm args -Dkotlin-logging.throwOnMessageError

More details on #160.

Q: How do I set the log level?

A: Setting log level globally is done (for jvm projects / android) in the underlying logging framework (log4j, logbck etc').

An example how to do that for logback:

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger

var slf4jLogger get() = (logger as DelegatingKLogger<org.slf4j.Logger>).underlyingLogger
var logbackLogger get() = (slf4jLogger.underlyingLogger) as ch.qos.logback.classic.Logger
var io.github.oshai.kotlinlogging.KLogger.level
    get() = logbackLogger.level
    set(value) { logbackLogger.level = value }

logger.level = Level.DEBUG
logger.level //=> Level.DEBUG

Something similar can be done for log4j, see answers here.

For other platforms it can be set like that:

KotlinLoggingConfiguration.LOG_LEVEL = KotlinLoggingLevel.ERROR;

See dedicated wiki for that.

And also more suggestions on stackoverflow.