Как мне заставить kotlin-logging (MicroUtils) печатать имя подкласса вместо имени абстрактного класса?

Я использую kotlin-logging (https://github.com/MicroUtils/kotlin-logging), я хочу, чтобы мой регистратор печатал имя подкласса вместо имени абстрактного класса. Пример у меня есть эти классы

// 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>() {
}

Он печатает: [основная] ИНФОРМАЦИЯ A - тестирование

Но я хочу напечатать: [main] INFO B - тестирование (где B - имя подкласса)

2 ответа

Решение

Вы можете отправить регистратор в абстрактный класс.

// 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

Если регистратор находился внутри вашего абстрактного класса 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, будет регистрироваться в соответствии с его собственным именем класса.

Результат: INFO B - testing

Почему? KotlinLogging имеет два метода, один из которых используетlogger(name: String) и один использует logger(func: () -> Unit)найдено здесь: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/KotlinLogging.kt

В logger(func: () -> Unit) называет logger(name: String)внутренне используя имя класса функции: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerFactory.kt

В вашем случае вызов функции в A.kt равен private val logger = KotlinLogging.logger {} находится внутри A.kt, а не вне этого файла, поэтому он всегда будет из A., поэтому он находит Aв этом преобразователе имен: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerNameResolver.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")
    }
}

результат AKt$funcJavaClass$1поэтому, когда мы разрезаем имя здесь: https://github.com/MicroUtils/kotlin-logging/blob/master/src/jvmMain/kotlin/mu/internal/KLoggerNameResolver.kt, результат будет простоA

Также стоит отметить, что в исходном примере используется A потому что имя файла A, а не из-за класса.

// 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$1

тогда как если функция вызывается изнутри класса

// 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$1

Другие вопросы по тегам