#

Live HTML Logging mit Log4J

Kürztlich habe ich eine JSP-Seite geschrieben, mit der man manuell Prozesse antriggern konnte. Um den Prozessverlauf jedoch genau nachzuhalten, musste ich stets in der Konsole die Logdatei auf haben, um die Logmeldungen zu verfolgen. Also habe ich mir die Log4J-API genauer angeschaut und mit ein paar Handgriffen das Logging parallel auf die JSP-Seite umleiten lassen.

Log4J arbeitet beim Loggen mit sogenannten Appendern, die festlegen, wie und wohin etwas geloggt werden soll. Also habe ich meinen eigenen Appender auf der JSP-Seite eingebunden und nach dem Prozess wieder entfernt.
Dazu braucht man lediglich der WriterAppender Implementierung in der API einen entsprechenden Writer zu übergeben. Mein erster versuch, direkt den JSPWriter zu übergeben wurde am Ende des Loggens mit einer Exception quittiert, da der JSPWriter geschlossen wurde (entweder von Log4J oder von der JSP selber). Also habe ich einen Robusten Writer-Wrapper gebastelt, der Fehler einfach schluckt:

package narcanti.jsplogging;
 
import java.io.IOException;
import java.io.Writer;
 
/**
 * @author M. Serhat Cinar
 */
public class ErrorImuneWriter extends Writer {
  private Writer delegate;
 
  public ErrorImuneWriter(Writer delegate){
    this.delegate = delegate;
  }
 
  /* (non-Javadoc)
    * @see java.io.Writer#close()
    */
  public void close() throws IOException {}
 
  /* (non-Javadoc)
   * @see java.io.Writer#flush()
   */
  public void flush() throws IOException {
    try{
      delegate.flush();
    }
    catch(Exception e){}
  }
 
  /* (non-Javadoc)
    * @see java.io.Writer#write(char[], int, int)
    */
  public void write(char[] cbuf, int off, int len) throws IOException {
    try{
      delegate.write(cbuf, off, len);
    }
    catch(Exception e){}
  }
}

Und nun konnte ich meinen Appender in der JSP dynamisch hinzufügen (mit meinem HTMLEscapeWriter dekoriert):

WriterAppender jspLogAppender = new WriterAppender(
  new PatternLayout("%d{dd.MM.yy HH:mm:ss} %-5p %m%n"), 
  new ErrorImuneWriter(new HTMLEscapeWriter(out))
  );
jspLogAppender.setEncoding("UTF-8");
jspLogAppender.setImmediateFlush(true);
jspLogAppender.setThreshold(Priority.INFO);
Logger rootLogger = Logger.getRootLogger();
rootLogger.addAppender(jspLogAppender);

Nach getaner Arbeit (am Ende der JSP, nachdem der Prozess abgearbeitet war):

rootLogger.removeAppender(jspLogAppender);

So einfach. Sieht spitze aus.
Erwähnt sei, dass Log4J out-of-the-box einen HtmlWriterAppender anbietet, der die Logs als Tabellen generiert. Aber ich wollte Plaintext…

Tags:

Leave a Reply »»

Note: All comments are manually approved to avoid spam. So if your comment doesn't appear immediately, that's ok. Have patience, it can take some days until I have the time to approve my comments.