package er.extensions.logging; import java.io.PrintWriter; import java.io.StringWriter; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Layout; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; import er.extensions.foundation.ERXExceptionUtilities; import er.extensions.foundation.ERXThreadStorage; /** * ERXConsoleAppender is just like ConsoleAppender except that it display stack * traces using ERXExceptionUtilities. Additionally, it will not log the same * exception twice in a row, preventing the annoying problem where you may log * from multiple places in your code and produce multiple copies of the same * exception trace. * * @author mschrag */ public class ERXConsoleAppender extends ConsoleAppender { private static final String LAST_THROWABLE_KEY = "er.extensions.logging.ERXConsoleAppender.lastThrowable"; public ERXConsoleAppender() { super(); } @SuppressWarnings("hiding") public ERXConsoleAppender(Layout layout) { super(layout); } @SuppressWarnings("hiding") public ERXConsoleAppender(Layout layout, String target) { super(layout, target); } @Override protected void subAppend(LoggingEvent event) { qw.write(super.layout.format(event)); if (super.layout.ignoresThrowable()) { ThrowableInformation throwableInfo = event.getThrowableInformation(); if (throwableInfo != null) { Throwable throwable = throwableInfo.getThrowable(); Throwable lastThrowable = (Throwable) ERXThreadStorage.valueForKey(ERXConsoleAppender.LAST_THROWABLE_KEY); if (throwable != null) { if (lastThrowable != throwable) { StringWriter exceptionStringWriter = new StringWriter(); ERXExceptionUtilities.printStackTrace(throwable, new PrintWriter(exceptionStringWriter, true)); String exceptionStr = exceptionStringWriter.toString(); if (exceptionStr.length() > 0) { for (String line : exceptionStr.split("[\r\n]+")) { qw.write(line); qw.write(Layout.LINE_SEP); } } ERXThreadStorage.takeValueForKey(throwable, ERXConsoleAppender.LAST_THROWABLE_KEY); } } } } if (immediateFlush) { qw.flush(); } } }