2010-02-26 5 views
19

Ich baue gerade eine Anwendung mit Tomcat, Spring und JAVA. Ich verwende Log4J als meine Protokollierungsbibliothek. Ich protokolliere derzeit alles in eine Textdatei. Eines der Probleme, die ich habe, ist, dass RuntimeExceptions nicht in Dateien protokolliert werden. Ich habe mich gefragt, ob es eine Möglichkeit gibt, alle RuntimeExceptions zu protokollieren, die möglicherweise in meine Anwendungsprotokolldatei geworfen werden. Wenn nicht, ist es möglich, dass es in einer anderen Protokolldatei protokolliert wird? Gibt es einen Standard Weg dies zu tun? Wenn dies der Fall ist, gibt es dafür eine Standardmethode, wenn Sie Ihre Anwendung in Tomcat ausführen.Protokolllaufzeit Ausnahmen in Java mit log4j

Vielen Dank im Voraus für Ihre Hilfe!

+2

Meinten Sie „abgefangene“ Runtime? –

+0

Ja ich meine "uncaught" RuntimeExceptions – DkS

Antwort

21

Ich bin mir nicht sicher, ob das ist, was Sie suchen, aber es gibt einen Handler für Ausnahmen, die Threads beenden. Es ist ein Handler für jede Ausnahme, die nicht explizit vom Ziel des Threads abgefangen wird.

Der Standard "abgefangene Exception-Handler", ruft einfach printStackTrace() auf den Throwable den Stack-Trace zu System.err zu drucken. Sie könnten jedoch replace dies mit Ihrem eigenen UncaughtExceptionHandler, der die Ausnahme statt log4j protokolliert:

class Log4jBackstop implements Thread.UncaughtExceptionHandler { 

    private static Logger log = Logger.getLogger(Log4jBackstop.class); 

    public void uncaughtException(Thread t, Throwable ex) { 
    log.error("Uncaught exception in thread: " + t.getName(), ex); 
    } 

} 

Wenn Sie einen Testamentsvollstrecker Framework verwenden, an die übergeben Sie ein Runnable Objekt, dessen Fäden wahrscheinlich ihre eigenen catch Block haben, die verhindern Ausnahmen vom Erreichen des nicht abgefangenen Ausnahmebehandlers. Wenn Sie Runtime Ausnahmen dort fangen wollen, einen Weg, es zu tun ist, jede Aufgabe in einer Logging-Wrapper zu wickeln, wie folgt aus:

class Log4jWrapper { 

    private final Logger log; 

    private final Runnable target; 

    Log4jWrapper(Logger log, Runnable target) { 
    this.log = Objects.requireNonNull(log); 
    this.target = Objects.requireNonNull(target); 
    } 

    public void run() { 
    try { 
     target.run(); 
    } catch(RuntimeException ex) { 
     log.error("Uncaught exception.", ex); 
     throw ex; 
    } 
    } 

} 

... 

Runnable realTask = ...; 
executor.submit(new Log4jWrapper(Logger.getLogger(Whatever.class), realTask)); 
+0

Ist dies normalerweise wie in Anwendungen behandelt RuntimeExceptions? Ich nehme an, ich frage mich, ob das ein normaler Weg ist, damit umzugehen. – DkS

+0

Auch ich benutze ThreadPoolTaskExecutor von der Spring API, ist dies noch etwas, das mit dieser Klasse getan werden kann? – DkS

+0

Das funktioniert gut, wenn es eine RuntimeException auf der Runnable gibt, aber was ist, wenn es eine Ausnahme mit dem ThreadPoolTaskExecutor gibt? Angenommen, es wird eine RunTimeException ausgelöst, weil der Pool korrekt konfiguriert wurde. Dies wird weiterhin auf der Konsole ausgegeben und nicht protokolliert .... Vorschläge? – DkS

1

Sie können versuchen, die StdErr zur Verwendung Ihres Loggers umzuleiten. Dies sollte das Ergebnis von allem, was auf Ihrem std err (was unbehandelt Ausnahmen enthalten) ausgegeben werden sollte

Dieser Blog-Post gibt eine gute Übersicht über die Umleitung in einen FileHandler, der Teil Ihres Loggers ist.

https://blogs.oracle.com/nickstephen/entry/java_redirecting_system_out_and

12

Eine Möglichkeit abgefangene Runtime (oder jegliche abgefangene Throwables was das betrifft) loggt ist, eine Klasse zu erstellen, die Thread.UncaughtExceptionHandler implementiert. Die Klasse uncaughtException() dieser Klasse würde einfach die Ausnahmedetails in das Protokoll schreiben. Sie können die JVM Aufruf dieser Exception-Handler machen, wenn ein nicht erfasster Runtime durch Hinzufügen der Zeile

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler()); 

, um Ihren Code ein Thread beendet wird.