ведение журнала kotlin с лямбда-параметрами
В log4j2 у нас есть удобная функция, которая описывается как
// Java-8 style optimization: no need to explicitly check the log level:
// the lambda expression is not evaluated if the TRACE level is not enabled
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
моя попытка использовать это в Котлин
log.debug("random {}", { UUID.randomUUID() })
которая будет печатать
random Function0<java.util.UUID>
как мы используем лямбда-логирование аргументов с помощью kotlin? Или как мы явно скажем Котлину, какой метод вызывать?
3 ответов
проблема в том, что debug()
перегружен и имеет другой метод, принимающий объект vararg в качестве аргумента. Котлин выбирает эту перегрузку, а не ту, которая принимает Supplier<?>
как аргумент, потому что он не знает, что лямбда-выражение должно быть поставщиком.
просто укажите его в качестве поставщика:
log.debug("random {}", Supplier { UUID.randomUUID() })
я написал класс, который делает это весело, чтобы использовать... Чтобы мы могли писать такие вещи, как
log.debug { "some $thing is $that" }
что эквивалентно ленивому журналированию лямбда, как
log.debug("some {} is {}", ()->thing, ()->that)
вы даже не нужны эти {}
для параметризации строки, и у вас есть все исходные методы регистратора, поскольку это делегат...
вот класс для тех, кто хотел бы его использовать...
import org.apache.logging.log4j.util.Supplier
class Logger(private val logger: org.apache.logging.log4j.Logger) : org.apache.logging.log4j.Logger by logger {
fun info(supplier: () -> String) {
logger.info(Supplier { supplier.invoke() })
}
fun debug(supplier: () -> String) {
logger.debug(Supplier { supplier.invoke() })
}
fun warn(supplier: () -> String) {
logger.warn(Supplier { supplier.invoke() })
}
fun error(supplier: () -> String) {
logger.error(Supplier { supplier.invoke() })
}
fun trace(supplier: () -> String) {
logger.trace(Supplier { supplier.invoke() })
}
}
или если вы хотите воспользоваться удивительными ссылками на источник в логах вы можете сделать
import org.apache.logging.log4j.util.Supplier
class Logger(val logger: org.apache.logging.log4j.Logger) : org.apache.logging.log4j.Logger by logger {
inline fun info(crossinline supplier: () -> String) {
logger.info(Supplier { supplier.invoke() })
}
inline fun debug(crossinline supplier: () -> String) {
logger.debug(Supplier { supplier.invoke() })
}
inline fun warn(crossinline supplier: () -> String) {
logger.warn(Supplier { supplier.invoke() })
}
inline fun error(crossinline supplier: () -> String) {
logger.error(Supplier { supplier.invoke() })
}
inline fun trace(crossinline supplier: () -> String) {
logger.trace(Supplier { supplier.invoke() })
}
}
проверить https://github.com/MicroUtils/kotlin-logging . Он также предоставляет эти функции:
удобная и исполнительная библиотека журналов, обертывающая slf4j с расширениями Kotlin.
методы журнала вызовов, не проверяя, включен ли соответствующий уровень журнала:
logger.debug { "Some $expensive message!" }
за кулисами дорогое сообщение не оценивается, если отладка не включена:
if (logger.isDebugEnabled) logger.debug("Some $expensive message!")
определите регистратор, без явного указание имени класса:
// Place definition above class declaration to make field static
private val logger = KotlinLogging.logger {}