Función de logging de extensión Kotlin con logback (slf4j)
He creado una function de extensión para el logging:
import org.slf4j.LoggerFactory fun Any.log(msg: String) { LoggerFactory.getLogger(javaClass.name).debug(msg) }
Pero no estoy seguro de si será init en cualquier momento cuando se lo llame o no, porque el método LoggerFactory.getLogger
invoca getILoggerFactory
.
- ¿Cuáles son las mejores prácticas para "recortar" una stack de exception antes de iniciar session con SLF4J?
- slf4j simple, ¿es posible filtrar posts dentro del mismo nivel?
Mb alguien ya hizo algo así y me puede asegurar que no habrá ninguna pérdida de memory :)?
Por ahora estoy usando el enfoque de la vieja moda (de declarar campo de logging en una class):
companion object { private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name) }
pero una testing de unit
simple como esta:
@Test fun testLogger() { val start = System.currentTimeMillis() for (i in 0..999) { log("i=" + i) } val end = System.currentTimeMillis() val time = end - start println("*** TIME=" + time.toDouble() / 1000 + " sec") }
muestra el mismo resultado que con la opción de moda antigua:
@Test fun testLogger() { val start = System.currentTimeMillis() for (i in 0..999) { logger.debug("i=" + i) } val end = System.currentTimeMillis() val time = end - start println("*** TIME=" + time.toDouble() / 1000 + " sec") } companion object { private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name) }
~ *** TIME=0.02 sec
Estoy usando:
org.slf4j - 1.7.25 ch.qos.logback - 1.2.3
Para el logging, podría recomendar otra solución.
Primero, agregue la interfaz ILogging y la class LoggingImpl:
interface ILogging { val log: Logger } class LoggingImp(loggerImpl: Logger) : ILogging { override val log: Logger = loggerImpl companion object { operator inline fun <reified T> invoke(): LoggingImp { return LoggingImp(LoggerFactory.getLogger(T::class.java)) } } }
Y ahora puedes agregar logger a cualquier class usando la delegación de Kotlin:
class TestClass : ILogging by LoggingImp<TestClass>() { fun test() { log.info("test") } }
El registrador se creará cuando se cree un object padre. Ejemplo de uso:
fun main(args: Array<String>) { val testClass = TestClass() testClass.test() }
Espero que esto te ayudará.
Una solución aún más simple es usar una interfaz con un método pnetworkingeterminado.
interface ILogger { @get:JsonIgnore val logger: Logger get() = LoggerFactory.getLogger(this) }
Y luego úsalo así:
class TestClass : ILogging { fun test() { logger.info("test") } }