Как мне заставить 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