Come inviare uno stacktrace a log4j?

Supponiamo di prendere un’eccezione e ottenere quanto segue sullo standard output (come, ad esempio, sulla console) se si esegue e.printStackTrace () :

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

Ora voglio inviare questo ad un logger come, ad esempio, log4j per ottenere quanto segue:

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

Come posso fare questo?

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

Si passa l’eccezione direttamente al logger, ad es

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

È compito di log4j eseguire il rendering della traccia dello stack.

Se vuoi registrare uno stacktrace senza coinvolgere un’eccezione, fai questo:

 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); 

È anche ansible ottenere la traccia dello stack come stringa tramite ExceptionUtils.getStackTrace .

Vedi: ExceptionUtils.java

Lo uso solo per log.debug , per mantenere log.error semplice.

Questa risposta potrebbe non essere correlata alla domanda posta ma correlata al titolo della domanda.

 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()); } 

La risposta di skaffman è sicuramente la risposta corretta. Tutti i metodi di registrazione come error() , warn() , info() , debug() prendono Throwable come secondo parametro:

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

Tuttavia, puoi anche estrarre lo stacktrace come stringa. A volte può essere utile se si desidera sfruttare la funzione di formattazione usando il segnaposto “{}” – vedi il metodo void info(String var1, Object... var2); In questo caso, diciamo che hai uno stacktrace come String, quindi puoi effettivamente fare qualcosa del genere:

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

Questo stamperà il messaggio parametrizzato e lo stacktrace alla fine nello stesso modo in cui lo fa per il metodo: logger.error("error: ", e);

In realtà ho scritto una libreria open source che ha un’utilità per l’estrazione di uno stacktrace come una stringa con un’opzione per filtrare in modo intelligente il rumore fuori dallo stacktrace. Cioè se si specifica il prefisso del pacchetto che ti interessa, il tuo stacktrace estratto verrà filtrato da alcune parti irrilevanti e ti lascerà informazioni molto dettagliate. Ecco il link all’articolo che spiega quali utilità ha la libreria e dove trovarla (sia come artefatti di Maven che come sorgenti di git) e come usarla. Libreria Java open source con filtraggio traccia stack, parsing Silent String convertitore Unicode e confronto versione Vedi il paragrafo ” Filtro rumore Stacktrace

Solo perché è successo a me e può essere utile. Se lo fai

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

otterrete l’intestazione dell’eccezione e non l’intero stacktrace. Perché il logger penserà che stai passando una stringa. Fallo senza {} come ha detto lo skaffman

questo sarebbe un buon log4j errore / registrazione delle eccezioni – leggibile da splunk / altri logging / monitoraggio s / w. tutto è una forma di coppia chiave-valore. log4j otterrebbe la traccia dello stack da Exception obj e

  try { --- --- } catch (Exception e) { log.error("api_name={} method={} _message=\"error description.\" msg={}", new Object[]{"api_name", "method_name", e.getMessage(), e}); } 
 Try this: catch (Throwable t) { logger.error("any message" + t); StackTraceElement[] s = t.getStackTrace(); for(StackTraceElement e : s){ logger.error("\tat " + e); } } 

Puoi usare il codice qui sotto:

 import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class LogWriterUtility { Logger log; public LogWriterUtility(Class clazz) { log = LogManager.getLogger(clazz); } public void errorWithAnalysis( Exception exception) { String message="No Message on error"; StackTraceElement[] stackTrace = exception.getStackTrace(); if(stackTrace!=null && stackTrace.length>0) { message=""; for (StackTraceElement e : stackTrace) { message += "\n" + e.toString(); } } log.error(message); } } 

Qui puoi solo chiamare: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

Stampa stackTrace nel registro.

Crea questa 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); } }; } } 

Chiama questo nel tuo codice

 StdOutErrLog.tieSystemOutAndErrToLog();