2010-12-03 12 views
130

Digamos que capturar una excepción y obtener lo siguiente en la salida estándar (como, por ejemplo, la consola) si lo hace un e.printStackTrace():¿Cómo enviar una stacktrace a log4j?

java.io.FileNotFoundException: so.txt 
     at java.io.FileInputStream.<init>(FileInputStream.java) 
     at ExTest.readMyFile(ExTest.java:19) 
     at ExTest.main(ExTest.java:7) 

Ahora desea enviar este lugar a un registrador como, por ejemplo, log4j para obtener lo siguiente:

31947 [AWT-EventQueue-0] ERROR Java.io.FileNotFoundException: so.txt 
32204 [AWT-EventQueue-0] ERROR at java.io.FileInputStream.<init>(FileInputStream.java) 
32235 [AWT-EventQueue-0] ERROR at ExTest.readMyFile(ExTest.java:19) 
32370 [AWT-EventQueue-0] ERROR at ExTest.main(ExTest.java:7) 

¿Cómo puedo hacer esto?

try { 
    ... 
} catch (Exception e) { 
    final String s; 
    ... // <-- What goes here? 
    log.error(s); 
} 

Respuesta

218

Se pasa la excepción directamente al registrador, por ejemplo

try { 
    ... 
} catch (Exception e) { 
    log.error("failed!", e); 
} 

Corresponde a log4j procesar el seguimiento de la pila.

+24

El registrador toma un objeto por su primer argumento y la voluntad toString() de ella. Sin embargo, el segundo argumento debe ser Throwable y muestra el seguimiento de la pila. –

+1

Nunca sé qué meter en la primera Cadena, generalmente acabo haciendo 'log.error (e.getLocalizedMessage(), e)' que es totalmente redundante. ¿Maneja un nulo para el primer argumento? –

+4

@Mark: intente darle un mensaje que sea más pertinente para el contexto que el mensaje de la excepción, p. ¿Qué estaba tratando de hacer en ese momento? – skaffman

6

También puede obtener el seguimiento de la pila como cadena a través de ExceptionUtils.getStackTrace.

Ver: ExceptionUtils.java

lo uso sólo para log.debug, para mantener log.error sencilla.

+0

Viejo pero dorado. Gracias – kosgeinsky

-2

crear este class:

public class StdOutErrLog { 

private static final Logger logger = Logger.getLogger(StdOutErrLog.class); 

public static void tieSystemOutAndErrToLog() { 
    System.setOut(createLoggingProxy(System.out)); 
    System.setErr(createLoggingProxy(System.err)); 
} 

public static PrintStream createLoggingProxy(final PrintStream realPrintStream) { 
    return new PrintStream(realPrintStream) { 
     public void print(final String string) { 
      logger.info(string); 
     } 
     public void println(final String string) { 
      logger.info(string); 
     } 
    }; 
} 
} 

Call esto en su código

StdOutErrLog.tieSystemOutAndErrToLog(); 
2

Esta respuesta puede ser no relacionado a la pregunta formulada, pero relacionado con el título de la pregunta.

public class ThrowableTest { 

    public static void main(String[] args) { 

     Throwable createdBy = new Throwable("Created at main()"); 
     ByteArrayOutputStream os = new ByteArrayOutputStream(); 
     PrintWriter pw = new PrintWriter(os); 
     createdBy.printStackTrace(pw); 
     try { 
      pw.close(); 
      os.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     logger.debug(os.toString()); 
    } 
} 

O

public static String getStackTrace (Throwable t) 
{ 
    StringWriter stringWriter = new StringWriter(); 
    PrintWriter printWriter = new PrintWriter(stringWriter); 
    t.printStackTrace(printWriter); 
    printWriter.close(); //surprise no IO exception here 
    try { 
     stringWriter.close(); 
    } 
    catch (IOException e) { 
    } 
    return stringWriter.toString(); 
} 

O

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 
for(StackTraceElement stackTrace: stackTraceElements){ 
    logger.debug(stackTrace.getClassName()+ " "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber()); 
} 
1

El hecho de que me pasó a mí y puede ser útil. Si hace esto

try { 
    ... 
} catch (Exception e) { 
    log.error("failed! {}", e); 
} 

obtendrá la cabecera de la excepción y no todo el StackTrace. Porque el registrador pensará que estás pasando un String. hacerlo sin {} como skaffman dijo

+1

Seguramente obtendrá el rastro de la pila completa aquí, sin embargo el {} se imprimirá literalmente (sin ninguna sustitución)? – k1eran

+0

¡no estés tan seguro, amigo mío! No funcionó para mí, solo recibí el encabezado. Podría depender de la versión de log4j aunque – iberbeu

7

Si desea registrar un StackTrace sin que ello suponga una excepción simplemente hacer esto:

String message = ""; 

for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {       
    message = message + System.lineSeparator() + stackTraceElement.toString(); 
} 
log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message); 
+2

+1 para System.lineSeparator(), esto me ayudó a imprimir una stacktrace que obtuve como respuesta de un servicio remoto – Stephanie

+0

lo que he buscado, pero debería usar StringBuilder aquí – Xerus

+0

Exactamente lo que estaba buscando – tcardoso

0

La respuesta de skaffman es sin duda la respuesta correcta. Todos los métodos logger como error(), warn(), info(), debug() toman Throwable como segundo parámetro:

try { 
... 
} catch (Exception e) { 
logger.error("error: ", e); 
} 

Sin embargo, puede extraer StackTrace como una cadena también.A veces puede ser útil si usted desea tomar ventaja de función usando el formato "{}" marcador de posición - véase el método void info(String var1, Object... var2); En este caso, supongamos que tiene un StackTrace como secuencia, a continuación, en realidad se puede hacer algo como esto:

try { 
... 
} catch (Exception e) { 
String stacktrace = TextUtils.getStacktrace(e); 
logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace); 
} 

Esto imprimirá el mensaje parametrizada y el StackTrace al final de la misma forma que lo hace para el método: logger.error("error: ", e);

hecho, me escribió una biblioteca de código abierto que tiene una utilidad para la extracción de un StackTrace como una cadena con una opción para filtrar inteligentemente salir un poco de ruido de stacktrace. Es decir. si especifica el prefijo del paquete que le interesa, su stacktrace extraído se eliminará de algunas partes irrelevantes y le dejará información muy detallada. Aquí está el enlace al artículo que explica qué utilidades tiene la biblioteca y dónde obtenerla (tanto como artefactos convencionales como fuentes de git) y cómo usarla también. Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison Ver el párrafo "StackTrace filtro de ruido"

0

esto sería bueno log4j de error/excepción tala - legible por splunk/otro registro/monitoreo s/w. todo es una forma de par clave-valor. log4j conseguirían el seguimiento de pila de excepción obj e

try { 
      --- 
      --- 
    } catch (Exception e) { 
     log.error("api_name={} method={} _message=\"error description.\" msg={}", 
        new Object[]{"api_name", "method_name", e.getMessage(), e}); 
    } 
0
Try this: 

catch (Throwable t) { 
    logger.error("any message" + t); 
    StackTraceElement[] s = t.getStackTrace(); 
    for(StackTraceElement e : s){ 
     logger.error("\tat " + e); 
    } 
} 
Cuestiones relacionadas