如何让 kotlin-logging (MicroUtils) 打印到 subclass 名称而不是抽象 class 名称?

How do I get kotlin-logging (MicroUtils) to print to subclass name instead of abstract class name?

我正在使用 kotlin-logging (https://github.com/MicroUtils/kotlin-logging),我希望我的记录器打印到 subclass 名称而不是抽象 class 名称。例如我有这些 class

// in A.kt file:

import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

abstract class A<T> {
    fun someMethod(item: T?) {
        logger.info("testing")
    }
}



fun main() {
    val b: A<String> = B()
    b.someMethod("123")
}




// in B.kt file

import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

class B : A<String>() {
}

它打印:[main] INFO A - testing

但我希望它打印:[main] INFO B - testing(其中 B 是 subclass 名称)

您可能希望将记录器发送到摘要 class。

// in A.kt file:

import mu.KotlinLogging

abstract class A<T>(private val logger: KLogger) {
    fun someMethod(item: T?) {
        logger.info("testing")
    }
}



fun main() {
    val b: A<String> = B()
    b.someMethod("123")
}




// in B.kt file

import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

class B : A<String>(logger) {
}

结果: [main] INFO B - testing

如果记录器在您的抽象 Class A 中,您可以使用 logger(name: String) 方法而不是 logger(func: () -> Unit) 方法,如下所示:

// in A.kt file

import mu.KotlinLogging

abstract class A<T> {
    private val logger = KotlinLogging.logger("${this::class.java.name}")

    fun someMethod(item: T?) {
        logger.info("testing")
    }
}

fun main() {
    val b: A<String> = B()
    b.someMethod("123")
}

// in B.kt file

class B : A<String>() {
}

以便任何扩展 A 的 class 都将根据其自己的 class 名称进行记录。

结果:INFO B - testing

为什么? KotlinLogging 有两种方法,一种使用 logger(name: String),另一种使用 logger(func: () -> Unit),在此处找到: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/KotlinLogging.kt#L14-L16

logger(func: () -> Unit) 使用函数的 class 名称在内部调用 logger(name: String)https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerFactory.kt#L29-L30

在你的例子中,A.kt 中的函数调用是 private val logger = KotlinLogging.logger {} 来自 A.kt 内部,从不在该文件之外,因此它将始终来自 A。 所以它在此名称解析器中找到 Ahttps://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerNameResolver.kt#L15-L23

如果我们在这里使用这段代码:

import mu.KotlinLogging

private val funcJavaClass: String = {}.javaClass.name

abstract class A<T> {
    private val logger = KotlinLogging.logger("${this::class.java.name}")

    fun someMethod(item: T?) {
        logger.info("$funcJavaClass")
        logger.info("testing")
    }
}

结果是 AKt$funcJavaClass 所以当我们在这里切分名称时: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerNameResolver.kt#L18 结果只是 A

还值得注意的是,原始示例使用 A 是因为文件名为 A,而不是因为 class.

// in R.kt

import mu.KotlinLogging

private val funcJavaClass: String = {}.javaClass.name

abstract class A<T> {
    private val logger = KotlinLogging.logger("${this::class.java.name}")

    fun someMethod(item: T?) {
        logger.info("$funcJavaClass")
        logger.info("testing")
    }
}

结果:RKt$funcJavaClass

而如果函数是从 class

内部调用的
// in R.kt

import mu.KotlinLogging

abstract class A<T> {
    private val logger = KotlinLogging.logger("${this::class.java.name}")
    private val funcJavaClass: String = {}.javaClass.name

    fun someMethod(item: T?) {
        logger.info("$funcJavaClass")
        logger.info("testing")
    }
}

结果:A$funcJavaClass