You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/10/02 09:15:58 UTC
svn commit: r1392762 - in /logging/log4j/log4j2/trunk:
api/src/main/java/org/apache/logging/log4j/
core/src/main/java/org/apache/logging/log4j/core/appender/
core/src/main/java/org/apache/logging/log4j/core/impl/
core/src/main/java/org/apache/logging/l...
Author: rgoers
Date: Tue Oct 2 07:15:57 2012
New Revision: 1392762
URL: http://svn.apache.org/viewvc?rev=1392762&view=rev
Log:
Fix LOG-58 - Add support for filtering packages in stacktraces
Added:
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowableTest.java
- copied, changed from r1391705, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowableTest.java
logging/log4j/log4j2/trunk/core/src/test/resources/log4j-rootthrowablefilter.xml
logging/log4j/log4j2/trunk/core/src/test/resources/log4j-throwablefilter.xml
- copied, changed from r1391705, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml
Modified:
logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
logging/log4j/log4j2/trunk/src/changes/changes.xml
logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml
Modified: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java Tue Oct 2 07:15:57 2012
@@ -39,6 +39,10 @@ public final class ThreadContext {
*/
public static final Map<String, String> EMPTY_MAP = new ImmutableMap();
+ /**
+ * Empty, immutable ContextStack.
+ */
+ public static final ContextStack EMPTY_STACK = new ImmutableStack();
private static final String DISABLE_MAP = "disableThreadContextMap";
@@ -52,11 +56,6 @@ public final class ThreadContext {
private static boolean useStack = !(Boolean.getBoolean(DISABLE_STACK) || all);
- /**
- * Empty, immutable ContextStack.
- */
- public static final ContextStack EMPTY_STACK = new ImmutableStack();
-
private static ThreadLocal<Map<String, String>> localMap =
new InheritableThreadLocal<Map<String, String>>() {
@Override
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java Tue Oct 2 07:15:57 2012
@@ -27,8 +27,6 @@ import org.apache.logging.log4j.core.lay
import java.io.OutputStream;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
/**
* ConsoleAppender appends log events to <code>System.out</code> or
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java Tue Oct 2 07:15:57 2012
@@ -26,6 +26,7 @@ import java.lang.reflect.Modifier;
import java.net.URL;
import java.security.CodeSource;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Stack;
@@ -148,6 +149,15 @@ public class ThrowableProxy extends Thro
* @return The formatted Throwable that caused this Throwable.
*/
public String getRootCauseStackTrace() {
+ return getRootCauseStackTrace(null);
+ }
+
+ /**
+ * Format the Throwable that is the cause of this Throwable.
+ * @param packages The List of packages to be suppressed from the trace.
+ * @return The formatted Throwable that caused this Throwable.
+ */
+ public String getRootCauseStackTrace(List<String> packages) {
StringBuilder sb = new StringBuilder();
if (cause != null) {
formatWrapper(sb, cause);
@@ -155,7 +165,7 @@ public class ThrowableProxy extends Thro
}
sb.append(throwable.toString());
sb.append("\n");
- formatElements(sb, 0, throwable.getStackTrace(), callerPackageData);
+ formatElements(sb, 0, throwable.getStackTrace(), callerPackageData, packages);
return sb.toString();
}
@@ -165,13 +175,23 @@ public class ThrowableProxy extends Thro
* @param cause The Throwable to format.
*/
public void formatWrapper(StringBuilder sb, ThrowableProxy cause) {
+ formatWrapper(sb, cause, null);
+ }
+
+ /**
+ * Formats the specified Throwable.
+ * @param sb StringBuilder to contain the formatted Throwable.
+ * @param cause The Throwable to format.
+ * @param packages The List of packages to be suppressed from the trace.
+ */
+ public void formatWrapper(StringBuilder sb, ThrowableProxy cause, List<String> packages) {
Throwable caused = cause.getCause();
if (caused != null) {
formatWrapper(sb, cause.cause);
sb.append("Wrapped by: ");
}
sb.append(cause).append("\n");
- formatElements(sb, cause.commonElementCount, cause.getStackTrace(), cause.callerPackageData);
+ formatElements(sb, cause.commonElementCount, cause.getStackTrace(), cause.callerPackageData, packages);
}
/**
@@ -179,11 +199,20 @@ public class ThrowableProxy extends Thro
* @return The formatted stack trace including packaging information.
*/
public String getExtendedStackTrace() {
+ return getExtendedStackTrace(null);
+ }
+
+ /**
+ * Format the stack trace including packaging information.
+ * @param packages List of packages to be suppressed from the trace.
+ * @return The formatted stack trace including packaging information.
+ */
+ public String getExtendedStackTrace(List<String> packages) {
StringBuilder sb = new StringBuilder(throwable.toString());
sb.append("\n");
- formatElements(sb, 0, throwable.getStackTrace(), callerPackageData);
+ formatElements(sb, 0, throwable.getStackTrace(), callerPackageData, packages);
if (cause != null) {
- formatCause(sb, cause);
+ formatCause(sb, cause, packages);
}
return sb.toString();
}
@@ -204,28 +233,68 @@ public class ThrowableProxy extends Thro
return sb.toString();
}
- private void formatCause(StringBuilder sb, ThrowableProxy cause) {
+ private void formatCause(StringBuilder sb, ThrowableProxy cause, List<String> packages) {
sb.append("Caused by: ").append(cause).append("\n");
- formatElements(sb, cause.commonElementCount, cause.getStackTrace(), cause.callerPackageData);
+ formatElements(sb, cause.commonElementCount, cause.getStackTrace(), cause.callerPackageData, packages);
if (cause.getCause() != null) {
- formatCause(sb, cause.cause);
+ formatCause(sb, cause.cause, packages);
}
}
private void formatElements(StringBuilder sb, int commonCount, StackTraceElement[] causedTrace,
- StackTracePackageElement[] packageData) {
- for (int i = 0; i < packageData.length; ++i) {
- sb.append("\tat ");
- sb.append(causedTrace[i]);
- sb.append(" ");
- sb.append(packageData[i]);
- sb.append("\n");
+ StackTracePackageElement[] packageData, List<String> packages) {
+ if (packages == null || packages.size() == 0) {
+ for (int i = 0; i < packageData.length; ++i) {
+ formatEntry(causedTrace[i], packageData[i], sb);
+ }
+ } else {
+ int count = 0;
+ for (int i = 0; i < packageData.length; ++i) {
+ if (!isSuppressed(causedTrace[i], packages)) {
+ if (count > 0) {
+ if (count == 1) {
+ sb.append("\t....\n");
+ } else {
+ sb.append("\t... suppressed ").append(count).append(" lines\n");
+ }
+ count = 0;
+ }
+ formatEntry(causedTrace[i], packageData[i], sb);
+ } else {
+ ++count;
+ }
+ }
+ if (count > 0) {
+ if (count == 1) {
+ sb.append("\t...\n");
+ } else {
+ sb.append("\t... suppressed ").append(count).append(" lines\n");
+ }
+ }
}
if (commonCount != 0) {
sb.append("\t... ").append(commonCount).append(" more").append("\n");
}
}
+ private void formatEntry(StackTraceElement element, StackTracePackageElement packageData, StringBuilder sb) {
+ sb.append("\tat ");
+ sb.append(element);
+ sb.append(" ");
+ sb.append(packageData);
+ sb.append("\n");
+ }
+
+ private boolean isSuppressed(StackTraceElement element, List<String> packages) {
+ String className = element.getClassName();
+ for (String pkg : packages) {
+ if (className.startsWith(pkg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Initialize the cache by resolving everything in the current stack trace via Reflection.getCallerClass
* or via the SecurityManager if either are available. These are the only Classes that can be trusted
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java Tue Oct 2 07:15:57 2012
@@ -25,6 +25,9 @@ public enum AnsiEscape {
SUFFIX("m"),
SEPARATOR(";"),
+ /**
+ * General Attributes.
+ */
NORMAL("0"),
BRIGHT("1"),
DIM("2"),
@@ -33,6 +36,9 @@ public enum AnsiEscape {
REVERSE("7"),
HIDDEN("8"),
+ /**
+ * Foreground Colors.
+ */
BLACK("30"),
FG_BLACK("30"),
RED("31"),
@@ -52,6 +58,9 @@ public enum AnsiEscape {
DEFAULT("39"),
FG_DEFAULT("39"),
+ /**
+ * Background Colors.
+ */
BG_BLACK("40"),
BG_RED("41"),
BG_GREEN("42"),
@@ -61,16 +70,16 @@ public enum AnsiEscape {
BG_CYAN("46"),
BG_WHITE("47");
- public static String getDefaultStyle() {
- return PREFIX.getCode() + SUFFIX.getCode();
- }
-
private final String code;
private AnsiEscape(String code) {
this.code = code;
}
+ public static String getDefaultStyle() {
+ return PREFIX.getCode() + SUFFIX.getCode();
+ }
+
public String getCode() {
return code;
}
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java Tue Oct 2 07:15:57 2012
@@ -20,6 +20,10 @@ import org.apache.logging.log4j.core.Log
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
/**
* Outputs the Throwable portion of the LoggingEvent as a full stacktrace
* unless this converter's option is 'short', where it just outputs the first line of the trace, or if
@@ -31,6 +35,11 @@ import org.apache.logging.log4j.core.imp
@Plugin(name = "ExtendedThrowablePatternConverter", type = "Converter")
@ConverterKeys({"xEx", "xThrowable", "xException" })
public final class ExtendedThrowablePatternConverter extends ThrowablePatternConverter {
+
+ private static final String FILTERS = "filters(";
+
+ private List<String> packages = null;
+
/**
* Private constructor.
*
@@ -38,6 +47,18 @@ public final class ExtendedThrowablePatt
*/
private ExtendedThrowablePatternConverter(final String[] options) {
super("ExtendedThrowable", "throwable", options);
+ if (options != null && options.length > 1) {
+ if (options[1].startsWith(FILTERS) && options[1].endsWith(")")) {
+ String filterStr = options[1].substring(FILTERS.length(), options[1].length() - 1);
+ String[] array = filterStr.split(",");
+ if (array.length > 0) {
+ packages = new ArrayList<String>(array.length);
+ for (String token : array) {
+ packages.add(token.trim());
+ }
+ }
+ }
+ }
}
/**
@@ -47,9 +68,24 @@ public final class ExtendedThrowablePatt
* only the first line of the throwable will be formatted.
* @return instance of class.
*/
- public static ExtendedThrowablePatternConverter newInstance(
- final String[] options) {
- return new ExtendedThrowablePatternConverter(options);
+ public static ExtendedThrowablePatternConverter newInstance(final String[] options) {
+ String type = null;
+ String[] array = options;
+ if (options != null && options.length == 1 && options[0].length() > 0) {
+ String[] opts = options[0].split(",", 2);
+ String first = opts[0].trim();
+ String filter;
+ Scanner scanner = new Scanner(first);
+ if (first.equalsIgnoreCase(FULL) || first.equalsIgnoreCase(SHORT) || scanner.hasNextInt()) {
+ type = first;
+ filter = opts[1].trim();
+ } else {
+ filter = options[0].trim();
+ }
+ array = new String[] {type, filter};
+ }
+
+ return new ExtendedThrowablePatternConverter(array);
}
/**
@@ -64,7 +100,7 @@ public final class ExtendedThrowablePatt
return;
}
ThrowableProxy t = (ThrowableProxy) throwable;
- String trace = t.getExtendedStackTrace();
+ String trace = t.getExtendedStackTrace(packages);
int len = toAppendTo.length();
if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
toAppendTo.append(" ");
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java Tue Oct 2 07:15:57 2012
@@ -33,8 +33,6 @@ import java.util.List;
@ConverterKeys({"highlight" })
public final class HighlightConverter extends LogEventPatternConverter {
- private List<PatternFormatter> formatters;
-
private static final EnumMap<Level, String> LEVEL_STYLES = new EnumMap<Level, String>(Level.class);
private static final String[] FATAL = new String[]{"BLINK", "BRIGHT", "RED"};
@@ -44,6 +42,8 @@ public final class HighlightConverter ex
private static final String[] DEBUG = null;
private static final String[] TRACE = null;
+ private List<PatternFormatter> formatters;
+
static {
LEVEL_STYLES.put(Level.FATAL, AnsiEscape.createSequence(FATAL));
LEVEL_STYLES.put(Level.ERROR, AnsiEscape.createSequence(ERROR));
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java Tue Oct 2 07:15:57 2012
@@ -20,6 +20,10 @@ import org.apache.logging.log4j.core.Log
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
/**
* Outputs the Throwable portion of the LoggingEvent as a full stacktrace
@@ -32,6 +36,11 @@ import org.apache.logging.log4j.core.imp
@Plugin(name = "RootThrowablePatternConverter", type = "Converter")
@ConverterKeys({"rEx", "rThrowable", "rException" })
public final class RootThrowablePatternConverter extends ThrowablePatternConverter {
+
+ private static final String FILTERS = "filters(";
+
+ private List<String> packages = null;
+
/**
* Private constructor.
*
@@ -39,6 +48,18 @@ public final class RootThrowablePatternC
*/
private RootThrowablePatternConverter(final String[] options) {
super("RootThrowable", "throwable", options);
+ if (options != null && options.length > 1) {
+ if (options[1].startsWith(FILTERS) && options[1].endsWith(")")) {
+ String filterStr = options[1].substring(FILTERS.length(), options[1].length() - 1);
+ String[] array = filterStr.split(",");
+ if (array.length > 0) {
+ packages = new ArrayList<String>(array.length);
+ for (String token : array) {
+ packages.add(token.trim());
+ }
+ }
+ }
+ }
}
/**
@@ -48,9 +69,24 @@ public final class RootThrowablePatternC
* only the first line of the throwable will be formatted.
* @return instance of class.
*/
- public static RootThrowablePatternConverter newInstance(
- final String[] options) {
- return new RootThrowablePatternConverter(options);
+ public static RootThrowablePatternConverter newInstance(final String[] options) {
+ String type = null;
+ String[] array = options;
+ if (options != null && options.length == 1 && options[0].length() > 0) {
+ String[] opts = options[0].split(",", 2);
+ String first = opts[0].trim();
+ String filter;
+ Scanner scanner = new Scanner(first);
+ if (first.equalsIgnoreCase(FULL) || first.equalsIgnoreCase(SHORT) || scanner.hasNextInt()) {
+ type = first;
+ filter = opts[1].trim();
+ } else {
+ filter = options[0].trim();
+ }
+ array = new String[] {type, filter};
+ }
+
+ return new RootThrowablePatternConverter(array);
}
/**
@@ -65,7 +101,7 @@ public final class RootThrowablePatternC
return;
}
ThrowableProxy t = (ThrowableProxy) throwable;
- String trace = t.getRootCauseStackTrace();
+ String trace = t.getRootCauseStackTrace(packages);
int len = toAppendTo.length();
if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
toAppendTo.append(" ");
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java Tue Oct 2 07:15:57 2012
@@ -16,15 +16,12 @@
*/
package org.apache.logging.log4j.core.pattern;
-import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.layout.PatternLayout;
-import java.util.EnumMap;
import java.util.List;
-import java.util.regex.Pattern;
/**
* Style pattern converter. Adds ANSI color styling to the result of the enclosed pattern.
Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java Tue Oct 2 07:15:57 2012
@@ -63,7 +63,8 @@ public class ThrowablePatternConverter e
int count = 0;
if ((options != null) && (options.length > 0)) {
option = options[0];
- if (option.equalsIgnoreCase(SHORT)) {
+ if (option == null) {
+ } else if (option.equalsIgnoreCase(SHORT)) {
count = 2;
} else if (!option.equalsIgnoreCase(FULL)) {
count = Integer.parseInt(option);
@@ -82,8 +83,7 @@ public class ThrowablePatternConverter e
* only the first line of the throwable will be formatted.
* @return instance of class.
*/
- public static ThrowablePatternConverter newInstance(
- final String[] options) {
+ public static ThrowablePatternConverter newInstance(final String[] options) {
return new ThrowablePatternConverter("Throwable", "throwable", options);
}
Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java Tue Oct 2 07:15:57 2012
@@ -28,6 +28,7 @@ import java.io.StringWriter;
import java.util.List;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
*
@@ -58,4 +59,19 @@ public class ExtendedThrowablePatternCon
String expected = sw.toString().replaceAll("\r", "");
assertEquals(expected, result);
}
+
+ @Test
+ public void testFiltering() {
+ String packages = "filters(org.junit, org.apache.maven, sun.reflect, java.lang.reflect)";
+ String[] options = {packages};
+ ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(options);
+ Throwable cause = new NullPointerException("null pointer");
+ Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+ LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(), Level.DEBUG,
+ new SimpleMessage("test exception"), parent);
+ StringBuilder sb = new StringBuilder();
+ converter.format(event, sb);
+ String result = sb.toString();
+ assertTrue("No suppressed lines", result.contains(" suppressed "));
+ }
}
Copied: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowableTest.java (from r1391705, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowableTest.java?p2=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowableTest.java&p1=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java&r1=1391705&r2=1392762&rev=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RegexReplacementTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowableTest.java Tue Oct 2 07:15:57 2012
@@ -20,10 +20,10 @@ import org.apache.logging.log4j.LogManag
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.test.appender.ListAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -31,22 +31,16 @@ import org.junit.Test;
import java.util.List;
import java.util.Map;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
/**
*
*/
-public class RegexReplacementTest {
- private static final String CONFIG = "log4j-replace.xml";
+public class ExtendedThrowableTest {
+ private static final String CONFIG = "log4j-throwablefilter.xml";
private static Configuration config;
private static ListAppender app;
- private static ListAppender app2;
private static LoggerContext ctx;
-
- private static final String LINE_SEP = System.getProperty("line.separator");
- private static final String EXPECTED = "/RegexReplacementTest" + LINE_SEP;
@BeforeClass
public static void setupClass() {
@@ -57,9 +51,6 @@ public class RegexReplacementTest {
if (entry.getKey().equals("List")) {
app = (ListAppender) entry.getValue();
}
- if (entry.getKey().equals("List2")) {
- app2 = (ListAppender) entry.getValue();
- }
}
}
@@ -68,36 +59,19 @@ public class RegexReplacementTest {
System.clearProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
ctx.reconfigure();
StatusLogger.getLogger().reset();
- ThreadContext.clear();
}
org.apache.logging.log4j.Logger logger = LogManager.getLogger("LoggerTest");
- org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("ReplacementTest");
@Test
- public void testReplacement() {
- logger.error(this.getClass().getName());
+ public void testException() {
+ Throwable cause = new NullPointerException("null pointer");
+ Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+ logger.error("Exception", parent);
List<String> msgs = app.getMessages();
assertNotNull(msgs);
assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
- assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
- app.clear();
- ThreadContext.put("MyKey", "Apache");
- logger.error("This is a test for ${ctx:MyKey}");
- msgs = app.getMessages();
- assertNotNull(msgs);
- assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
- assertEquals("LoggerTest This is a test for Apache" + LINE_SEP , msgs.get(0));
+ assertTrue("No suppressed lines", msgs.get(0).contains("suppressed"));
app.clear();
-
- }
- @Test
- public void testConverter() {
- logger2.error(this.getClass().getName());
- List<String> msgs = app2.getMessages();
- assertNotNull(msgs);
- assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
- assertTrue("Replacement failed - expected ending " + EXPECTED + " Actual " + msgs.get(0), msgs.get(0).endsWith(EXPECTED));
- app2.clear();
}
}
Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowableTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowableTest.java?rev=1392762&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowableTest.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowableTest.java Tue Oct 2 07:15:57 2012
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class RootThrowableTest {
+ private static final String CONFIG = "log4j-rootthrowablefilter.xml";
+ private static Configuration config;
+ private static ListAppender app;
+ private static LoggerContext ctx;
+
+ @BeforeClass
+ public static void setupClass() {
+ System.setProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY, CONFIG);
+ ctx = (LoggerContext) LogManager.getContext(false);
+ config = ctx.getConfiguration();
+ for (Map.Entry<String, Appender> entry : config.getAppenders().entrySet()) {
+ if (entry.getKey().equals("List")) {
+ app = (ListAppender) entry.getValue();
+ }
+ }
+ }
+
+ @AfterClass
+ public static void cleanupClass() {
+ System.clearProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
+ ctx.reconfigure();
+ StatusLogger.getLogger().reset();
+ }
+
+ org.apache.logging.log4j.Logger logger = LogManager.getLogger("LoggerTest");
+
+ @Test
+ public void testException() {
+ Throwable cause = new NullPointerException("null pointer");
+ Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+ logger.error("Exception", parent);
+ List<String> msgs = app.getMessages();
+ assertNotNull(msgs);
+ assertTrue("Incorrect number of messages. Should be 1 is " + msgs.size(), msgs.size() == 1);
+ assertTrue("No suppressed lines", msgs.get(0).contains("suppressed"));
+ app.clear();
+ }
+}
Added: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-rootthrowablefilter.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-rootthrowablefilter.xml?rev=1392762&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-rootthrowablefilter.xml (added)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-rootthrowablefilter.xml Tue Oct 2 07:15:57 2012
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<configuration status="warn" name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+ <properties>
+ <property name="filters">org.junit,org.apache.maven,sun.reflect,java.lang.reflect</property>
+ </properties>
+ <ThresholdFilter level="debug"/>
+
+ <appenders>
+ <Console name="STDOUT">
+ <PatternLayout pattern="%m%rEx{FULL,filters(${filters})}%n"/>
+ </Console>
+ <List name="List">
+ <PatternLayout pattern="%m%rEx{filters(${filters})}%n"/>
+ </List>
+ </appenders>
+
+ <loggers>
+ <root level="error">
+ <appender-ref ref="List"/>
+ </root>
+ </loggers>
+
+</configuration>
\ No newline at end of file
Copied: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-throwablefilter.xml (from r1391705, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-throwablefilter.xml?p2=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-throwablefilter.xml&p1=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml&r1=1391705&r2=1392762&rev=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-throwablefilter.xml Tue Oct 2 07:15:57 2012
@@ -18,40 +18,22 @@
-->
<configuration status="warn" name="XMLConfigTest" packages="org.apache.logging.log4j.test">
<properties>
- <property name="filename">target/test.log</property>
+ <property name="filters">org.junit,org.apache.maven,sun.reflect,java.lang.reflect</property>
</properties>
<ThresholdFilter level="debug"/>
<appenders>
<Console name="STDOUT">
- <PatternLayout pattern="%m%n"/>
+ <PatternLayout pattern="%m%xEx{FULL,filters(${filters})}%n"/>
</Console>
- <File name="File" fileName="${filename}" bufferedIO="false">
- <PatternLayout>
- <pattern>%d %p %C{1.} [%t] %m%n</pattern>
- </PatternLayout>
- </File>
<List name="List">
- <filters>
- <ThresholdFilter level="error"/>
- </filters>
+ <PatternLayout pattern="%m%xEx{filters(${filters})}%n"/>
</List>
</appenders>
<loggers>
- <logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
- <ThreadContextMapFilter>
- <KeyValuePair key="test" value="123"/>
- </ThreadContextMapFilter>
- <appender-ref ref="STDOUT"/>
- </logger>>
-
- <logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
- <appender-ref ref="File"/>
- </logger>>
-
<root level="error">
- <appender-ref ref="STDOUT"/>
+ <appender-ref ref="List"/>
</root>
</loggers>
Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Tue Oct 2 07:15:57 2012
@@ -23,6 +23,9 @@
<body>
<release version="2.0-beta2" date="TBD" description="Bug fixes and enhancements">
+ <action issue="LOG4J2-58" dev="rgoers" type="add">
+ Add support for filtering packages from stack traces.
+ </action>
<action issue="LOG4J2-84" dev="rgoers" type="add">
If system property "disableThreadContextStack" is set pushes to the ThreadContext will be ignored. If
system property "disableThreadContext" is set both puts and pushes will be ignored.
Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml?rev=1392762&r1=1392761&r2=1392762&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml Tue Oct 2 07:15:57 2012
@@ -240,9 +240,9 @@
</tr>
<tr>
<td align="center">
- <b>ex</b>{depth}<br />
- <b>exception</b>{depth}<br />
- <b>throwable</b>{depth}
+ <b>ex</b>{["short"|"full"|depth]}<br />
+ <b>exception</b>{["short"|"full"|depth]}<br />
+ <b>throwable</b>{["short"|"full"|depth]}
</td>
<td>
<p>Used to output the Throwable trace that has been bound to the LoggingEvent, by
@@ -389,15 +389,23 @@
</tr>
<tr>
<td align="center">
- <b>rEx</b>{depth}<br />
- <b>rException</b>{depth}<br />
- <b>rThrowable</b>{depth}
+ <b>rEx</b>["short"|"full"|depth],[filters(packages)}<br />
+ <b>rException</b>["short"|"full"|depth],[filters(packages)}<br />
+ <b>rThrowable</b>["short"|"full"|depth],[filters(packages)}
</td>
<td>
<p>
The same as the %throwable conversion word but the stack trace is printed starting with the
first exception that was thrown followed by each subsequent wrapping exception.
</p>
+ <p>
+ The throwable conversion word can be followed by an option in the form
+ <b>%rEx{short}</b>
+ which will only output the first line of the Throwable or <b>%rEx{n}</b> where
+ the first n lines of the stacktrace will be printed. The conversion word can also be
+ followed by "filters(packages)" where packages is a list of package names that should
+ be suppressed from stack traces.
+ </p>
</td>
</tr>
<tr>
@@ -580,9 +588,9 @@
</tr>
<tr>
<td align="center">
- <b>xEx</b>{depth}<br />
- <b>xException</b>{depth}<br />
- <b>xThrowable</b>{depth}
+ <b>xEx</b>{["short"|"full"|depth],[filters(packages)}<br />
+ <b>xException</b>["short"|"full"|depth],[filters(packages)}<br />
+ <b>xThrowable</b>["short"|"full"|depth],[filters(packages)}
</td>
<td>
<p>
@@ -594,6 +602,14 @@
as found in that jar's manifest will be added. If the information is uncertain, then the class
packaging data will be preceded by a tilde, i.e. the '~' character.
</p>
+ <p>
+ The throwable conversion word can be followed by an option in the form
+ <b>%xEx{short}</b>
+ which will only output the first line of the Throwable or <b>%xEx{n}</b> where
+ the first n lines of the stacktrace will be printed. The conversion word can also be
+ followed by "filters(packages)" where packages is a list of package names that should
+ be suppressed from stack traces.
+ </p>
</td>
</tr>
<tr>
@@ -711,6 +727,32 @@
application and Log4j will automatically make use of it when writing to the console.
</p>
<h4>Example Patterns</h4>
+ <h5>Filtered Throwables</h5>
+ <p>
+ This example shows how to filter out classes from unimportant packages in stack traces.
+ </p>
+ <source><![CDATA[
+ <properties>
+ <property name="filters">org.junit,org.apache.maven,sun.reflect,java.lang.reflect</property>
+ </properties>
+ .
+ .
+ <PatternLayout pattern="%m%xEx{filters(${filters})}%n"/>
+ ]]></source>
+ <p>
+ The result printed to the console will appear similar to:
+ </p>
+ <source>
+ Exception java.lang.IllegalArgumentException: IllegalArgument
+ at org.apache.logging.log4j.core.pattern.ExtendedThrowableTest.testException(ExtendedThrowableTest.java:72) [test-classes/:?]
+ ... suppressed 26 lines
+ at $Proxy0.invoke(Unknown Source) [?:?]
+ ... suppressed 3 lines
+ Caused by: java.lang.NullPointerException: null pointer
+ at org.apache.logging.log4j.core.pattern.ExtendedThrowableTest.testException(ExtendedThrowableTest.java:71) ~[test-classes/:?]
+ ... 30 more
+
+ </source>
<h5>Ansi Styled</h5>
<p>The log level will be highlighted according to the event's log level. All the content that follows
the level will be bright green.</p>