Skip to content

日志标准 (kotlin-logging)

源:kotlin-logging

在 Kotlin 生态中,直接使用 android.util.Log 或后端的 System.out 并非最佳实践。kotlin-logging 是一个轻量级的日志门面(Facade),它支持 Kotlin Multiplatform (KMP),并能以极低的开销提供结构化、惰性求值的日志能力。

为什么需要它?

  1. 性能优化:支持 Lambda 惰性求值。如果日志级别低于当前配置(如在生产环境关闭 DEBUG),Lambda 内的字符串拼接完全不会执行。
  2. KMP 支持:一套代码同时运行在 Android (Logcat)、JVM (SLF4J)、JS 和 Native 上。
  3. 减少样板:无需手动输入 TAG,自动根据类名生成。

依赖配置

该库采用门面模式,因此通常需要引入“核心库”和“实现库”。

查看 Maven Central 最新版本

kotlin
dependencies {
    // 1. 引入 kotlin-logging 核心门面
    implementation("io.github.oshai:kotlin-logging-jvm:5.1.0")

    // 2. 引入具体的日志实现 (Android 推荐 slf4j-android)
    implementation("org.slf4j:slf4j-android:1.7.36")
}
kotlin
commonMain {
    dependencies {
        implementation("io.github.oshai:kotlin-logging:5.1.0")
    }
}

基础用法

最常见的方式是创建一个顶层或伴生对象的 Logger。

kotlin
import io.github.oshai.kotlinlogging.KotlinLogging

// 自动获取当前类名作为 TAG
private val logger = KotlinLogging.logger {}

class UserManager {
    fun login(userId: String) {
        // ⭐️ 惰性求值:如果 info 级别未开启,字符串模板不会被计算
        logger.info { "User $userId logged in at ${System.currentTimeMillis()}" }
        
        try {
            processLogin()
        } catch (e: Exception) {
            // 携带异常堆栈
            logger.error(e) { "Login failed for user $userId" }
        }
    }
}

Android 平台适配

在 Android 上,默认的 kotlin-logging 需要配合 SLF4J 实现才能输出到 Logcat。

推荐方案:slf4j-android

引入 org.slf4j:slf4j-android 后,日志会自动转发到 Logcat。

  • TAG 限制:旧版 Android 对 TAG 长度限制为 23 字符,slf4j-android 会自动截断。
  • 级别映射
    • logger.trace -> Log.v
    • logger.debug -> Log.d
    • logger.info -> Log.i
    • logger.warn -> Log.w
    • logger.error -> Log.e

核心工程准则

  1. 禁止直接使用 Log.d:在业务逻辑层(非 UI 层),严禁直接依赖 Android SDK 的 android.util.Log。这会破坏代码的可测试性(单元测试不依赖 Android 环境)和跨平台能力。
  2. 利用惰性求值:永远使用 { "Msg $param" } 的 Lambda 写法,而不是直接传入字符串。这在处理复杂对象 toString() 时能节省大量 CPU。
  3. 统一 TAG 规范:默认使用 KotlinLogging.logger {} 即可,不要手动硬编码 TAG 字符串,除非有特殊的过滤需求。