Logging in Kotlin Applications: Best Practices and Tools

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Logging in Kotlin Applications: Best Practices



Logging is not just about writing messages to the console. In modern Kotlin applications (from Android to backend on Ktor or Spring Boot), logs become the primary source of information for debugging, monitoring, and auditing. Improperly configured logging can lead to loss of critical data or, conversely, to disk overflow. In this article, we will analyze best practices for logging in Kotlin, review popular libraries, and show code examples.



1. Choosing a Logging Library for Kotlin



Kotlin is fully compatible with the Java ecosystem, so you can use any Java logging library. However, there are also Kotlin-specific wrappers that make the code more idiomatic.



  • SLF4J (Simple Logging Facade for Java) — a facade that allows you to plug in different implementations (Logback, Log4j2, java.util.logging). This is the de facto standard in the Java world.
  • Logback — the most popular SLF4J implementation. Fast, flexible, with support for asynchronous logging.
  • kotlin-logging — a lightweight wrapper over SLF4J, using Kotlin features (inline functions, lambdas). Allows you to write code in the style of logger.debug { "Message" }.


Recommended stack for a new project: SLF4J + Logback + kotlin-logging. Example of adding dependencies in build.gradle.kts:



dependencies {    implementation("ch.qos.logback:logback-classic:1.4.14")    implementation("io.github.microutils:kotlin-logging-jvm:3.0.5")}


2. Correct Logging Levels



Using the correct level is the foundation of good logging. SLF4J has 5 levels (in increasing order of severity): TRACE, DEBUG, INFO, WARN, ERROR.



  • TRACE — very detailed information for debugging (method entry/exit, variable values). Enable only in dev environment.
  • DEBUG — useful information for the developer (system state, intermediate calculations).
  • INFO — important application runtime events (startup, request processing, database connection).
  • WARN — potentially dangerous situations (non-critical errors, deprecated APIs).
  • ERROR — errors requiring intervention (exceptions, business logic failures).


Example of usage with kotlin-logging:



import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

fun processOrder(orderId: String) { logger.info { "Starting processing of order $orderId" } try { // business logic logger.debug { "Order $orderId: amount = $amount" } } catch (e: Exception) { logger.error(e) { "Error processing order $orderId" } }}


Important: Avoid using logger.info("String " + variable) — this creates a string even if the level is not enabled. Use lambdas: logger.info { "String $variable" }.



3. Structured Logging



Text logs are difficult to parse. It is better to use structured formats (JSON, Logstash) that allow machines to easily analyze data. This is especially important for microservice architecture and centralized log collection systems (ELK, Grafana Loki).



In Logback, the logstash-logback-encoder library is used for JSON format:



// build.gradle.ktsimplementation("net.logstash.logback:logstash-logback-encoder:7.4")


logback.xml configuration:



<configuration>    <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>    </appender>

<root leve

Blogs

Book Recommendations