1. 简介

日志记录是任何生产级应用中不可或缺的一部分。在 Java 项目中,常见的选择是使用 SLF4J 作为日志门面,底层通常搭配 LogbackLog4j 等实现。这些工具虽然成熟,但没有充分利用 Kotlin 提供的现代语言特性。

本文将介绍一个专为 Kotlin 设计的 SLF4J 封装库:kotlin-logging。它简化了日志的使用方式,更符合 Kotlin 的语法风格。

2. 快速上手

先来看一个简单的使用示例,快速搭建起 kotlin-logging 的环境。

2.1. 引入依赖

使用 Maven 添加依赖:

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

Gradle 项目则使用:

implementation 'io.github.oshai:kotlin-logging-jvm:7.0.3'

由于 kotlin-logging 基于 SLF4J,我们需要指定一个具体的日志实现。开发阶段可使用 slf4j-simple,生产环境推荐使用 Logback 或 Log4j2。

以 Logback 为例,Maven 配置如下:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.18</version>
</dependency>

Gradle 配置如下:

implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.5.18'

同时,我们还需要一个基础的 logback.xml 配置文件:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} MDC=%X{user} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

有关 Logback 的更多配置细节可参考 Logback 配置详解,但上面的配置已经足够我们开始使用。

2.2. 基本使用

导入 KotlinLogging:

import io.github.oshai.kotlinlogging.KotlinLogging

然后在类中声明一个 logger:

private val logger = KotlinLogging.logger {}

接下来就可以使用它进行日志输出:

fun main() {
    logger.trace { "This is trace log" }
    logger.debug { "This is debug log" }
    logger.info { "This is info log" }
    logger.warn { "This is warn log" }
    logger.error { "This is error log" }
}

输出结果如下:

16:29:20.390 [main] DEBUG com.baeldung.logging.BasicUsageMain MDC= - This is debug log
16:29:20.393 [main] INFO  com.baeldung.logging.BasicUsageMain MDC= - This is info log
16:29:20.394 [main] WARN  com.baeldung.logging.BasicUsageMain MDC= - This is warn log
16:29:20.394 [main] ERROR com.baeldung.logging.BasicUsageMain MDC= - This is error log

⚠️ 注意:trace 日志没有输出,是因为默认日志级别是 debug。如果你希望看到 trace 级别的日志,需要在 logback.xml 中将日志级别设为 trace

3. 深入使用

了解一些细节可以让我们更高效地使用 kotlin-logging。

3.1. 使用花括号 vs 圆括号

在 kotlin-logging 中,推荐使用花括号 {} 而不是圆括号 () 来包裹日志内容,这是为了实现延迟求值(lazy evaluation)

举个例子:

val bigEvaluationFunction: (String) -> String = {
    println("I am a VERY BIG evaluation: $it")
    "Big Evaluation"
}

使用圆括号:

logger.trace("Running big evaluation: ${bigEvaluationFunction("eagerly")}")

使用花括号:

logger.trace { "Running big evaluation: ${bigEvaluationFunction("lazily")}" }

假设当前日志级别为 debug,那么:

✅ 花括号写法:bigEvaluationFunction 不会被执行
❌ 圆括号写法:bigEvaluationFunction 会被执行(即使日志不会输出)

所以:始终使用花括号包裹日志内容,避免不必要的性能开销

3.2. Logger 命名

kotlin-logging 会自动根据当前类名生成 logger 名称,例如:

private val logger = KotlinLogging.logger {}

等价于 SLF4J 的:

private static final Logger logger = LoggerFactory.getLogger("package.ClassName");

如果你需要自定义 logger 名称,也可以手动指定:

private val logger = KotlinLogging.logger("The Name")

3.3. 获取底层 SLF4J Logger

虽然 kotlin-logging 提供了更 Kotlin 友好的 API,但有时我们仍需要直接使用 SLF4J:

val slf4j: org.slf4j.Logger = logger.underlyingLogger

这样就可以调用 SLF4J 的原生方法。

3.4. 创建 Logger 的方式

目前官方推荐的创建方式是使用顶层变量:

private val logger = KotlinLogging.logger {}

除此之外,还有两种历史方式(不推荐):

  1. 使用 companion object 扩展 KLogging
class ClassForImportantWork {
    companion object: KLogging()

    fun importantWork() {
        logger.debug { "I'm logging via companion object" }
    }
}
  1. 实现 KLoggable 接口
class ClassForImportantWork: KLoggable {
    override val logger: KLogger = logger()

    fun importantWork() {
        logger.debug { "I'm logging via non static member" }
    }
}

建议统一使用第一种方式,保持代码一致性。

3.5. 在 Android 中使用

kotlin-logging 同样适用于 Android 项目,只需添加:

implementation group: 'org.slf4j', name: 'slf4j-android', version: '1.7.32'

即可像普通 Kotlin/JVM 项目一样使用。

3.6. 支持 MDC(Mapped Diagnostic Context)

MDC 是日志上下文追踪的重要机制。kotlin-logging 完全支持 MDC,使用方式如下:

withLoggingContext("user" to "Baeldung") {
    logger.info { "Log with MDC" }
}

输出日志:

16:34:36.486 [main] INFO  com.baeldung.logging.LoggingContext MDC=Baeldung - Log with MDC

withLoggingContext 会自动将指定的键值对放入 MDC 上下文中,无需手动调用 MDC.put()

4. 总结

kotlin-logging 是一个专为 Kotlin 开发者打造的日志封装库,它简化了日志调用方式,支持延迟求值、MDC 等高级特性,同时兼容 SLF4J,使用门槛低。

✅ 优势总结:

  • ✅ 更 Kotlin 风格的 API
  • ✅ 支持懒加载日志内容,避免性能浪费
  • ✅ 完整支持 MDC
  • ✅ 可与 Logback、Log4j2、Android 等平台无缝集成

如果你正在使用 Kotlin 编写项目,强烈推荐使用 kotlin-logging 替代原生 SLF4J 的写法,提升代码可读性和开发效率。


原始标题:Guide to Kotlin-Logging