1. 简介
日志记录是任何生产级应用中不可或缺的一部分。在 Java 项目中,常见的选择是使用 SLF4J 作为日志门面,底层通常搭配 Logback 或 Log4j 等实现。这些工具虽然成熟,但没有充分利用 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 {}
除此之外,还有两种历史方式(不推荐):
- 使用
companion object
扩展KLogging
class ClassForImportantWork {
companion object: KLogging()
fun importantWork() {
logger.debug { "I'm logging via companion object" }
}
}
- 实现
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 的写法,提升代码可读性和开发效率。