diff --git a/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java index 9733b34..7b3a7f8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java @@ -23,10 +23,10 @@ import ch.qos.logback.core.status.WarnStatus; /** * Sets a skeleton implementation for appenders. - * + * *

For more information about this appender, please refer to the online * manual at http://logback.qos.ch/manual/appenders.html#AppenderBase - * + * * @author Ceki Gülcü */ abstract public class AppenderBase extends ContextAwareBase implements @@ -41,6 +41,12 @@ abstract public class AppenderBase extends ContextAwareBase implements private boolean guard = false; /** + * Normally exceptions are internally logged and then ignored. Setting this to + * false will cause the exception to percolate to the application. + */ + protected boolean exceptionMask = true; + + /** * Appenders are named. */ protected String name; @@ -88,6 +94,9 @@ abstract public class AppenderBase extends ContextAwareBase implements if (exceptionCount++ < ALLOWED_REPEATS) { addError("Appender [" + name + "] failed to append.", e); } + if (!exceptionMask) { + throw new LogbackException("Exception detected in " + this.getClass().getName(), e); + } } finally { guard = false; } @@ -95,6 +104,14 @@ abstract public class AppenderBase extends ContextAwareBase implements abstract protected void append(E eventObject); + public void setExceptionMask(boolean mask) { + exceptionMask = mask; + } + + public boolean isExceptionMask() { + return exceptionMask; + } + /** * Set the name of this appender. */ diff --git a/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java index 64a0d20..600d1f3 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java @@ -22,9 +22,9 @@ import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.status.WarnStatus; /** - * Similar to AppenderBase except that derived appenders need to handle + * Similar to AppenderBase except that derived appenders need to handle * thread synchronization on their own. - * + * * @author Ceki Gülcü * @author Ralph Goers */ @@ -33,6 +33,12 @@ abstract public class UnsynchronizedAppenderBase extends ContextAwareBase imp protected boolean started = false; + /** + * Normally exceptions are internally logged and then ignored. Setting this to + * false will cause the exception to percolate to the application. + */ + protected boolean exceptionMask = true; + // using a ThreadLocal instead of a boolean add 75 nanoseconds per // doAppend invocation. This is tolerable as doAppend takes at least a few microseconds // on a real appender @@ -94,6 +100,9 @@ abstract public class UnsynchronizedAppenderBase extends ContextAwareBase imp if (exceptionCount++ < ALLOWED_REPEATS) { addError("Appender [" + name + "] failed to append.", e); } + if (!exceptionMask) { + throw new LogbackException("Exception detected in " + this.getClass().getName(), e); + } } finally { guard.set(false); } @@ -101,6 +110,14 @@ abstract public class UnsynchronizedAppenderBase extends ContextAwareBase imp abstract protected void append(E eventObject); + public void setExceptionMask(boolean mask) { + exceptionMask = mask; + } + + public boolean isExceptionMask() { + return exceptionMask; + } + /** * Set the name of this appender. */ @@ -136,7 +153,7 @@ abstract public class UnsynchronizedAppenderBase extends ContextAwareBase imp return fai.getCopyOfAttachedFiltersList(); } - + public FilterReply getFilterChainDecision(E event) { return fai.getFilterChainDecision(event); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/appender/AppenderExceptionTest.java b/logback-core/src/test/java/ch/qos/logback/core/appender/AppenderExceptionTest.java index 696d18d..63928fa 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/appender/AppenderExceptionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/appender/AppenderExceptionTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.fail; import ch.qos.logback.core.Appender; import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.UnsynchronizedAppenderBase; import org.junit.Test; /** @@ -32,33 +33,37 @@ public class AppenderExceptionTest { @Test public void testAppenderBaseException() { MockAppender a = new MockAppender(); + a.start(); try { a.doAppend("Test"); } catch (Exception ex) { fail("Unexpected exception caught"); } - a.setExceptionMask(true); + a.setExceptionMask(false); try { a.doAppend("Test"); fail("Expected exception not thrown"); } catch (Exception ex) { } + a.stop(); } @Test public void testUnsynchronizedAppenderBaseException() { - MockAppender a = new MockAppender(); + MockUnsynchronizedAppender a = new MockUnsynchronizedAppender(); + a.start(); try { a.doAppend("Test"); } catch (Exception ex) { fail("Unexpected exception caught"); } - a.setExceptionMask(true); + a.setExceptionMask(false); try { a.doAppend("Test"); fail("Expected exception not thrown"); } catch (Exception ex) { } + a.stop(); } public class MockAppender extends AppenderBase { @@ -68,10 +73,10 @@ public class AppenderExceptionTest { } } - public class MockAppender extends AppenderBase { + public class MockUnsynchronizedAppender extends UnsynchronizedAppenderBase { @Override protected void append(Object eventObject) { throw new RuntimeException("Test"); } - } + } }