Logging in Kotlin Applications: Best Practices for Beginners

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 for Beginners

\n\n

Logging is not just about writing messages to a file. It is a system that helps a developer understand what is happening in the application in real time, quickly find errors, and analyze user behavior. In this article, we will look at how to properly organize logging in Kotlin applications, which libraries to use, and what mistakes to avoid.

\n\n

Why is logging needed?

\n

Logging solves several key tasks:

\n
    \n
  • Debugging: allows you to see the sequence of calls and variable values without using a debugger.
  • \n
  • Monitoring: helps track the application's state in a production environment.
  • \n
  • Auditing: records user actions and system events.
  • \n
  • Performance: logs can help identify bottlenecks and delays.
  • \n
\n\n

Popular libraries for logging in Kotlin

\n

In the Kotlin and JVM ecosystem, there are several proven solutions. Let's look at the main ones:

\n
    \n
  • SLF4J (Simple Logging Facade for Java) — a facade that does not implement logging itself but provides a unified API for various implementations (Logback, Log4j2, etc.).
  • \n
  • Logback — the most popular SLF4J implementation. Fast, flexible, with support for rolling files.
  • \n
  • Log4j 2 — a powerful library with support for asynchronous logging and filtering.
  • \n
  • Kotlin Logging — a convenient wrapper over SLF4J that uses inline functions to minimize overhead.
  • \n
\n\n

Configuring Logback in a Kotlin project

\n

Let's look at a step-by-step configuration of Logback, the most popular solution for Kotlin/JVM applications.

\n\n

Step 1. Adding dependencies

\n

In the build.gradle.kts file, add:

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

Step 2. Creating a configuration file

\n

Create a file src/main/resources/logback.xml:

\n
<configuration>\n    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">\n        <file>logs/app.log</file>\n        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">\n            <fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>\n            <maxHistory>30</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <root level="INFO">\n        <appender-ref ref="CONSOLE"/>\n        <appender-ref ref="FILE"/>\n    </root>\n</configuration>
\n

This configuration outputs logs to the console and to a file with daily rotation (logs are stored for 30 days).

\n\n

Step 3. Using in code

\n

Let's use the kotlin-logging library:

\n
import mu.KotlinLogging\n\nprivate val logger = KotlinLogging.logger {}\n\nfun main() {\n    logger.info("Application started")\n    logger.debug { "Variable value x = $x" }\n    try {\n        // some code\n    } catch (e: Exception) {\n        logger.error(e) { "Error during operation execution" }\n    }\n}
\n\n

Logging levels: when to use what

\n

Choosing the right level is the foundation of readable logs. Logback has the following levels

Blogs

Book Recommendations