slf4j: cómo registrar mensajes formateados, matriz de objetos, excepción

275

¿Cuál es el enfoque correcto para registrar tanto un mensaje poblado como un seguimiento de pila de la excepción?

logger.error(
    "\ncontext info one two three: {} {} {}\n",
    new Object[] {"1", "2", "3"},
    new Exception("something went wrong"));

Me gustaría producir una salida similar a esta:

context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...

slf4j versión 1.6.1

rowe
fuente
3
No entiendo por qué slf4j usa su propia sintaxis de cadena de formato en lugar del estilo estándar% s. Molesto.
Keith Tyler
@KeithTyler Me gusta {}más, la cuestión del gusto ...
Betlista
@KeithTyler El toString()método de los argumentos puede ser costoso. Con esta sintaxis, solo se pasa una referencia a cada objeto y toString()solo se llama al método si el mensaje en particular se está registrando. Los objetos a los que se hace referencia en una info()llamada de registro no tendrán su toString()método llamado si el nivel de registro es WARNo superior. La {}sintaxis es un recordatorio para los usuarios de que esta no es una String.format()operación similar, es decir, deben pasar objetos en lugar de representaciones de cadenas de los mismos.
user149408

Respuestas:

427

A partir de SLF4J 1.6.0, en presencia de múltiples parámetros y si el último argumento en una declaración de registro es una excepción, SLF4J supondrá que el usuario desea que el último argumento sea tratado como una excepción y no como un parámetro simple. Consulte también la entrada relevante de preguntas frecuentes .

Entonces, escribir (en SLF4J versión 1.7.xy posterior)

 logger.error("one two three: {} {} {}", "a", "b", 
              "c", new Exception("something went wrong"));

o escribiendo (en SLF4J versión 1.6.x)

 logger.error("one two three: {} {} {}", new Object[] {"a", "b", 
              "c", new Exception("something went wrong")});

rendirá

one two three: a b c
java.lang.Exception: something went wrong
    at Example.main(Example.java:13)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ...

El resultado exacto dependerá del marco subyacente (por ejemplo, logback, log4j, etc.) y de cómo se configura el marco subyacente. Sin embargo, si el último parámetro es una excepción, se interpretará como tal independientemente del marco subyacente.

Ceki
fuente
44
¿Qué marco de registro subyacente está utilizando? Como se mencionó en mi respuesta anterior, si el último parámetro es una excepción, se interpretará como tal independientemente del marco subyacente. (Probado con logback, slf4j-log4j12, slf4j-jdk14 y slf4j-simple.)
Ceki
3
Lo sentimos, no reconocí que en su ejemplo usó n = 3 marcadores de posición en la cadena de formato yn + 1 = 4 elementos en la matriz de objetos. Tenía n marcadores de posición en la cadena de formato y también n elementos en la matriz de objetos más una excepción como tercer parámetro. Esperaba que la excepción se imprimiera con stacktrace, pero esto nunca sucedió. ¿Funciona como está diseñado? Además, si tengo n marcadores de posición y n elementos en la matriz de objetos, con la excepción del último elemento, no veo ningún seguimiento de pila. Quizás los n marcadores de posición con n + 1 objetos en una matriz deberían estar un poco más enfatizados.
rowe
77
Iba a molestar a @Ceki por no estar en los Javadocs pero está en la parte superior de la Loggerclase javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
He creado solicitud de mejora , puede votar por ella si le gusta.
Betlista el
8

Además de la respuesta de @Ceki, si está utilizando el inicio de sesión y configura un archivo de configuración en su proyecto (generalmente logback.xml), también puede definir el registro para trazar el seguimiento de la pila utilizando

<encoder>
    <pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern> 
</encoder>

el% ex en el patrón es lo que hace la diferencia

Yaniv
fuente