Logging for Kotlin: Best Solutions
Logging is an integral part of developing any serious application. In the Kotlin ecosystem, thanks to full compatibility with Java and the availability of modern DSL approaches, there are several proven solutions. In this article, we will break down the best libraries for logging in Kotlin: from classic Java frameworks to specialized Kotlin wrappers. You will learn how to set up effective logging for server-side (Ktor, Spring Boot) and mobile (Android) projects.
1. SLF4J + Logback — The Classic Choice
SLF4J (Simple Logging Facade for Java) is a facade (abstraction) over various logging frameworks. Paired with Logback (an implementation created by the same author), this is the de facto standard for JVM projects, including Kotlin.
Features:
- Time-tested stability and performance.
- Flexible configuration via XML or Groovy/DSL.
- Support for asynchronous logging (AsyncAppender).
- Automatic log compression and rotation.
Configuration example in Kotlin:
// build.gradle.ktsdependencies { implementation("ch.qos.logback:logback-classic:1.4.14") implementation("org.slf4j:slf4j-api:2.0.9")}
// Main.ktimport org.slf4j.LoggerFactory
private val logger = LoggerFactory.getLogger("MyApp")
fun main() { logger.info("Application started") try { // business logic } catch (e: Exception) { logger.error("Execution error: {}", e.message, e) }}Logback automatically looks for the logback.xml file in the classpath. Example of a simple config:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender>
<root level="debug"> <appender-ref ref="STDOUT" /> </root></configuration>2. kotlin-logging — Lightweight Kotlin Wrapper
The kotlin-logging library (by author Marcin Zajączkowski) provides a minimalistic Kotlin interface on top of SLF4J. It adds support for lambda expressions and inline functions, which helps avoid the overhead of string formatting if the logging level is disabled.
Advantages:
- Lazy message evaluation:
logger.debug { "Complex ${expensive()}" }. - No need to declare
val loggermanually (via thelogger()delegate). - Full compatibility with any SLF4J implementation (Logback, Log4j2).
Usage example:
// build.gradle.ktsdependencies { implementation("io.github.microutils:kotlin-logging-jvm:3.0.5")}
// Main.ktimport mu.KotlinLogging
private val logger = KotlinLogging.logger {}
fun main() { val userId = 42 logger.info { "User $userId logged in" } logger.debug { "Detailed report: ${generateReport()}" } // won't execute if debug is disabled}
fun generateReport(): String = "very long report"3. Timber — For Android Development
Timber is a lightweight library by Jake Wharton, created specifically for Android. It extends the standard android.util.Log, adding automatic class detection, stack traces, and the ability to "plant" trees for different logging levels.
Key Features:
- Automatic tag (class name) — no need to write
Log.d(TAG, ...). - Ability to disable logs in release builds with a single line.
- Support for crash reports and custom trees (e.g., CrashlyticsTree).
Also in library
gRPC-Go for Go: Complete Guide with Examples
Working with Kafka in PHP: Libraries, Installation, and Code Examples
Working with S3 and Cloud Storage in C# (.NET): AWS SDK Library
GraphQL in C# (.NET): Complete Guide to the GraphQL.NET Library
Generating QR Codes in Java: ZXing Library (Detailed Guide)