diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java index 17b0d764e9..aa1fb6ef8c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java @@ -38,6 +38,7 @@ public class ThrowableProxyConverter extends ThrowableHandlingConverter { int lengthOption; List> evaluatorList = null; + List ignoredStackTraceLines = null; int errorCount = 0; @@ -69,12 +70,16 @@ public void start() { if (optionList != null && optionList.size() > 1) { final int optionListSize = optionList.size(); for (int i = 1; i < optionListSize; i++) { - String evaluatorStr = (String) optionList.get(i); + String evaluatorOrIgnoredStackTraceLine = (String) optionList.get(i); Context context = getContext(); Map evaluatorMap = (Map) context.getObject(CoreConstants.EVALUATOR_MAP); EventEvaluator ee = (EventEvaluator) evaluatorMap - .get(evaluatorStr); - addEvaluator(ee); + .get(evaluatorOrIgnoredStackTraceLine); + if (ee != null) { + addEvaluator(ee); + } else { + addIgnoreStackTraceLine(evaluatorOrIgnoredStackTraceLine); + } } } super.start(); @@ -87,6 +92,13 @@ private void addEvaluator(EventEvaluator ee) { evaluatorList.add(ee); } + private void addIgnoreStackTraceLine(String ignoredStackTraceLine) { + if (ignoredStackTraceLines == null) { + ignoredStackTraceLines = new ArrayList(); + } + ignoredStackTraceLines.add(ignoredStackTraceLine); + } + public void stop() { evaluatorList = null; super.stop(); @@ -185,10 +197,23 @@ protected void subjoinSTEPArray(StringBuilder buf, int indent, IThrowableProxy t maxIndex -= commonFrames; } + int ignoredCount = 0; for (int i = 0; i < maxIndex; i++) { - ThrowableProxyUtil.indent(buf, indent); - buf.append(stepArray[i]); - extraData(buf, stepArray[i]); // allow other data to be added + StackTraceElementProxy element = stepArray[i]; + if (!isIgnoredStackTraceLine(element.toString())) { + ThrowableProxyUtil.indent(buf, indent); + printStackLine(buf, ignoredCount, element); + ignoredCount = 0; + buf.append(CoreConstants.LINE_SEPARATOR); + } else { + ++ignoredCount; + if (maxIndex < stepArray.length) { + ++maxIndex; + } + } + } + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); buf.append(CoreConstants.LINE_SEPARATOR); } @@ -198,4 +223,28 @@ protected void subjoinSTEPArray(StringBuilder buf, int indent, IThrowableProxy t " common frames omitted").append(CoreConstants.LINE_SEPARATOR); } } + + private void printStackLine(StringBuilder buf, int ignoredCount, StackTraceElementProxy element) { + buf.append(element); + extraData(buf, element); // allow other data to be added + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); + } + } + + private void printIgnoredCount(StringBuilder buf, int ignoredCount) { + buf.append(" [").append(ignoredCount).append(" skipped]"); + } + + private boolean isIgnoredStackTraceLine(String line) { + if (ignoredStackTraceLines != null) { + for (String ignoredStackTraceLine : ignoredStackTraceLines) { + if (line.contains(ignoredStackTraceLine)) { + return true; + } + } + } + return false; + } + } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java index 74b1155f33..a4f459d018 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; +import ch.qos.logback.core.CoreConstants; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -33,6 +34,7 @@ import ch.qos.logback.classic.util.TeztHelper; import static ch.qos.logback.classic.util.TeztHelper.addSuppressed; +import static org.fest.assertions.Assertions.assertThat; import static org.junit.Assert.*; import static org.junit.Assume.assumeTrue; @@ -158,6 +160,57 @@ public void withShortArgument() throws Exception { assertNull("Unexpected line in stack trace", reader.readLine()); } + @Test + public void skipSelectedLine() throws Exception { + //given + final Throwable t = TeztHelper.makeNestedException(0); + t.printStackTrace(pw); + final ILoggingEvent le = createLoggingEvent(t); + tpc.setOptionList(Arrays.asList("full", "skipSelectedLines")); + tpc.start(); + + //when + final String result = tpc.convert(le); + + //then + assertThat(result).excludes("skipSelectedLines"); + } + + @Test + public void skipMultipleLines() throws Exception { + //given + final Throwable t = TeztHelper.makeNestedException(0); + t.printStackTrace(pw); + final ILoggingEvent le = createLoggingEvent(t); + tpc.setOptionList(Arrays.asList("full", "skipMultipleLines", "junit")); + tpc.start(); + + //when + final String result = tpc.convert(le); + + //then + assertThat(result) + .excludes("skipSelectedLines") + .excludes("junit"); + } + + @Test + public void shouldLimitTotalLinesExcludingSkipped() throws Exception { + //given + final Throwable t = TeztHelper.makeNestedException(0); + t.printStackTrace(pw); + final ILoggingEvent le = createLoggingEvent(t); + tpc.setOptionList(Arrays.asList("3", "shouldLimitTotalLinesExcludingSkipped")); + tpc.start(); + + //when + final String result = tpc.convert(le); + + //then + String[] lines = result.split(CoreConstants.LINE_SEPARATOR); + assertThat(lines).hasSize(3 + 1); + } + void someMethod() throws Exception { throw new Exception("someMethod"); }