¿Cómo registrar un mensaje formateado, una matriz de objetos, una excepción?

4 minutos de lectura

avatar de usuario
Rowe

¿Cuál es el enfoque correcto para registrar tanto un mensaje completo 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 ...

Mi versión SLF4J es 1.6.1.

  • No entiendo por qué slf4j usa su propia sintaxis de cadena de formato en lugar del estilo estándar %s. Irritante.

    –Keith Tyler

    31 de julio de 2019 a las 17:36

  • @KeithTyler Me gusta {} más, cuestión de gustos…

    – Betlista

    23 de enero de 2020 a las 4:48


  • @KeithTyler El toString() método de los argumentos puede ser costoso. Con esta sintaxis, solo se pasa una referencia a cada objeto y el toString() El método solo se llama si el mensaje en particular realmente se está registrando. Objetos a los que se hace referencia en un info() la llamada de registro no tendrá su toString() método llamado si el nivel de registro es WARN o mas alto. los {} sintaxis es un recordatorio para los usuarios de que esto no es un String.format()-como operación, es decir, deben pasar objetos en lugar de cadenas de representación de los mismos.

    – usuario149408

    28 de abril de 2020 a las 13:25

avatar de usuario
cekí

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, entonces SLF4J supondrá que el usuario desea que el último argumento sea tratado como una excepción y no como un simple parámetro. Véase también el entrada de preguntas frecuentes relevante.

Entonces, escribiendo (en SLF4J versión 1.7.x y posteriores)

 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 (p. ej., logback, log4j, etc.), así como de cómo esté configurado el marco subyacente. Sin embargo, si el último parámetro es una excepción, se interpretará como tal independientemente del marco subyacente.

  • ¿Qué marco de registro subyacente está utilizando? Como 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

    20 de junio de 2011 a las 10:37


  • Lo siento, no reconocí que en su ejemplo usó n = 3 marcadores de posición en la cadena de formato y n + 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. Mi expectativa era que la excepción se imprimiría con stacktrace, pero esto nunca sucedió. ¿Funciona como se diseñó? 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 rastro de pila. Tal vez los n marcadores de posición con n+1 objetos en una matriz deberían enfatizarse un poco más.

    – Rowe

    22 de junio de 2011 a las 13:19

  • Le iba a hacer pasar un mal rato a @Ceki por no estar en los Javadocs, pero está en la parte superior de la lista. Logger clase javadoc: slf4j.org/apidocs/org/slf4j/Logger.html

    – Adam Gent

    20 de abril de 2013 a las 20:43


  • yo creé solicitud de mejorapuedes votar por él si te gusta.

    – Betlista

    23 de enero de 2020 a las 5:18

  • ¿Sabes cómo hacer que Intellij IDEA 2020.2.3 no se queje de esto? me da un aviso The formatted log message expects N arguments, passed N-1 así que me veo obligado a usar String.format()

    – dfche

    7 julio 2021 a las 14:41


avatar de usuario
Yaniv

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 usando

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

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

La respuesta aceptada es genial. Solo estoy agregando aquí mi caso que ahora está funcionando, gracias por la respuesta. Esto puede ayudar a alguien más.

Estoy usando SLF4J y logback con un codificador JSON. Además, uso marker y arguments para enriquecer mi producción.

    logger.error(getMarker("errorEvent"),
                 "An error occurred",
                 entries(mapOf("someKey" to "someValue")),
                 new Exception())

La salida:

  {
   "level": "ERROR",
   "event": "errorEvent",
   "eventData": {
      "someKey": "someValue"
   },
   "stacktrace": "...omitted...",
   "message": "An error occurred"
}

Por supuesto, hay mucha configuración de logstash detrás de escena, pero solo quería mostrar que el arguments pasó como entries se muestran en el configurado eventData etiqueta.

¿Ha sido útil esta solución?