You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2017/03/08 03:58:10 UTC

[04/11] logging-log4j2 git commit: Allow to append a suffix to each line of the throwable stacktrace.

Allow to append a suffix to each line of the throwable stacktrace.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0146bbae
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0146bbae
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0146bbae

Branch: refs/heads/master
Commit: 0146bbae4a94aee9e92e1ba843f0125075debfdc
Parents: f3be879
Author: xnslong <xn...@outlook.com>
Authored: Mon Mar 6 00:57:01 2017 +0800
Committer: xnslong <xn...@outlook.com>
Committed: Mon Mar 6 00:57:01 2017 +0800

----------------------------------------------------------------------
 .../log4j/core/impl/ThrowableFormatOptions.java |  38 +++----
 .../logging/log4j/core/impl/ThrowableProxy.java | 113 +++++++++++--------
 .../ExtendedThrowablePatternConverter.java      |  15 ++-
 .../log4j/core/pattern/PatternParser.java       |   2 +-
 .../pattern/RootThrowablePatternConverter.java  |  15 ++-
 .../core/pattern/ThrowablePatternConverter.java |  49 +++++++-
 .../log4j/core/impl/ThrowableProxyTest.java     |  86 ++++++++++++--
 .../ExtendedThrowablePatternConverterTest.java  |  46 +++++++-
 .../RootThrowablePatternConverterTest.java      |  48 +++++++-
 .../pattern/ThrowablePatternConverterTest.java  |  21 ++--
 10 files changed, 324 insertions(+), 109 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
index 81cb5dc..2d54351 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
@@ -17,14 +17,12 @@
 package org.apache.logging.log4j.core.impl;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Scanner;
 
 import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
-import org.apache.logging.log4j.core.pattern.TextRenderer;
 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
+import org.apache.logging.log4j.core.pattern.TextRenderer;
 import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.core.util.Patterns;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -72,7 +70,7 @@ public final class ThrowableFormatOptions {
      */
     private final String separator;
 
-    private final List<String> mdcKeys;
+    private final String suffix;
 
     /**
      * The list of packages to filter.
@@ -88,22 +86,22 @@ public final class ThrowableFormatOptions {
 
     /**
      * Constructs the options for printing stack trace.
-     *  @param lines
+     * @param lines
      *            The number of lines.
      * @param separator
      *            The stack trace separator.
      * @param ignorePackages
- *            The packages to filter.
+*            The packages to filter.
      * @param textRenderer
-     * @param mdcKeys
+     * @param suffix
      */
     protected ThrowableFormatOptions(final int lines, final String separator, final List<String> ignorePackages,
-                                     final TextRenderer textRenderer, final List<String> mdcKeys) {
+                                     final TextRenderer textRenderer, final String suffix) {
         this.lines = lines;
         this.separator = separator == null ? Strings.LINE_SEPARATOR : separator;
         this.ignorePackages = ignorePackages;
         this.textRenderer = textRenderer == null ? PlainTextRenderer.getInstance() : textRenderer;
-        this.mdcKeys = mdcKeys;
+        this.suffix = suffix;
     }
 
     /**
@@ -247,10 +245,10 @@ public final class ThrowableFormatOptions {
         }
 
         int lines = DEFAULT.lines;
-        List<String> mdcKeys = DEFAULT.mdcKeys;
         String separator = DEFAULT.separator;
         List<String> packages = DEFAULT.ignorePackages;
         TextRenderer ansiRenderer = DEFAULT.textRenderer;
+        String suffix = DEFAULT.getSuffix();
         for (final String rawOption : options) {
             if (rawOption != null) {
                 final String option = rawOption.trim();
@@ -289,26 +287,20 @@ public final class ThrowableFormatOptions {
                         StatusLogger.getLogger().warn(
                                 "You requested ANSI exception rendering but JANSI is not on the classpath. Please see https://logging.apache.org/log4j/2.x/runtime-dependencies.html");
                     }
-                } else if (option.startsWith("mdc(") && option.endsWith(")")){
-                    String suffixPattern = option.substring("mdc(".length(), option.length() - 1);
-                    mdcKeys = parseMdcKeys(suffixPattern);
-                } else if (option.startsWith("X(") && option.endsWith(")")){
-                    String suffixPattern = option.substring("X(".length(), option.length() - 1);
-                    mdcKeys = parseMdcKeys(suffixPattern);
+                } else if (option.startsWith("S(") && option.endsWith(")")){
+                    suffix = option.substring("S(".length(), option.length() - 1);
+                } else if (option.startsWith("suffix(") && option.endsWith(")")){
+                    suffix = option.substring("suffix(".length(), option.length() - 1);
                 } else if (!option.equalsIgnoreCase(FULL)) {
                     lines = Integer.parseInt(option);
                 }
             }
         }
-        return new ThrowableFormatOptions(lines, separator, packages, ansiRenderer, mdcKeys);
+        return new ThrowableFormatOptions(lines, separator, packages, ansiRenderer, suffix);
     }
 
-    private static List<String> parseMdcKeys(final String suffixPattern) {
-        if (suffixPattern.trim().isEmpty()) {
-            return Collections.emptyList();
-        } else {
-            return Arrays.asList(suffixPattern.split(","));
-        }
+    public String getSuffix() {
+        return suffix;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
index 4cff083..f0db83b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
@@ -207,24 +207,25 @@ public class ThrowableProxy implements Serializable {
     }
 
     private void formatCause(final StringBuilder sb, final String prefix, final ThrowableProxy cause,
-                             final List<String> ignorePackages, final TextRenderer textRenderer) {
-        formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, ignorePackages, textRenderer);
+                             final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix) {
+        formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, ignorePackages, textRenderer, suffix);
     }
 
     private void formatThrowableProxy(final StringBuilder sb, final String prefix, final String causeLabel,
                                       final ThrowableProxy throwableProxy, final List<String> ignorePackages,
-                                      final TextRenderer textRenderer) {
+                                      final TextRenderer textRenderer, final String suffix) {
         if (throwableProxy == null) {
             return;
         }
         textRenderer.render(prefix, sb, "Prefix");
         textRenderer.render(causeLabel, sb, "CauseLabel");
         throwableProxy.renderOn(sb, textRenderer);
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
         this.formatElements(sb, prefix, throwableProxy.commonElementCount,
-            throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, ignorePackages, textRenderer);
-        this.formatSuppressed(sb, prefix + TAB, throwableProxy.suppressedProxies, ignorePackages, textRenderer);
-        this.formatCause(sb, prefix, throwableProxy.causeProxy, ignorePackages, textRenderer);
+            throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, ignorePackages, textRenderer, suffix);
+        this.formatSuppressed(sb, prefix + TAB, throwableProxy.suppressedProxies, ignorePackages, textRenderer, suffix);
+        this.formatCause(sb, prefix, throwableProxy.causeProxy, ignorePackages, textRenderer, suffix);
     }
 
     void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
@@ -237,37 +238,37 @@ public class ThrowableProxy implements Serializable {
     }
 
     private void formatSuppressed(final StringBuilder sb, final String prefix, final ThrowableProxy[] suppressedProxies,
-                                  final List<String> ignorePackages, final TextRenderer textRenderer) {
+                                  final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix) {
         if (suppressedProxies == null) {
             return;
         }
         for (final ThrowableProxy suppressedProxy : suppressedProxies) {
-            formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, suppressedProxy, ignorePackages, textRenderer);
+            formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, suppressedProxy, ignorePackages, textRenderer, suffix);
         }
     }
 
     private void formatElements(final StringBuilder sb, final String prefix, final int commonCount,
                                 final StackTraceElement[] causedTrace, final ExtendedStackTraceElement[] extStackTrace,
-                                final List<String> ignorePackages, final TextRenderer textRenderer) {
+                                final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix) {
         if (ignorePackages == null || ignorePackages.isEmpty()) {
             for (final ExtendedStackTraceElement element : extStackTrace) {
-                this.formatEntry(element, sb, prefix, textRenderer);
+                this.formatEntry(element, sb, prefix, textRenderer, suffix);
             }
         } else {
             int count = 0;
             for (int i = 0; i < extStackTrace.length; ++i) {
                 if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
                     if (count > 0) {
-                        appendSuppressedCount(sb, prefix, count, textRenderer);
+                        appendSuppressedCount(sb, prefix, count, textRenderer, suffix);
                         count = 0;
                     }
-                    this.formatEntry(extStackTrace[i], sb, prefix, textRenderer);
+                    this.formatEntry(extStackTrace[i], sb, prefix, textRenderer, suffix);
                 } else {
                     ++count;
                 }
             }
             if (count > 0) {
-                appendSuppressedCount(sb, prefix, count, textRenderer);
+                appendSuppressedCount(sb, prefix, count, textRenderer, suffix);
             }
         }
         if (commonCount != 0) {
@@ -275,12 +276,20 @@ public class ThrowableProxy implements Serializable {
             textRenderer.render("\t... ", sb, "More");
             textRenderer.render(Integer.toString(commonCount), sb, "More");
             textRenderer.render(" more", sb, "More");
+            renderSuffix(suffix, sb, textRenderer);
             textRenderer.render(EOL_STR, sb, "Text");
         }
     }
 
+    private void renderSuffix(final String suffix, final StringBuilder sb, final TextRenderer textRenderer) {
+        if (!suffix.isEmpty()) {
+            textRenderer.render(" ", sb, "Suffix");
+            textRenderer.render(suffix, sb, "Suffix");
+        }
+    }
+
     private void appendSuppressedCount(final StringBuilder sb, final String prefix, final int count,
-                                       final TextRenderer textRenderer) {
+                                       final TextRenderer textRenderer, final String suffix) {
         textRenderer.render(prefix, sb, "Prefix");
         if (count == 1) {
             textRenderer.render("\t... ", sb, "Suppressed");
@@ -289,59 +298,63 @@ public class ThrowableProxy implements Serializable {
             textRenderer.render(Integer.toString(count), sb, "Suppressed");
             textRenderer.render(" lines", sb, "Suppressed");
         }
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
     }
 
     private void formatEntry(final ExtendedStackTraceElement extStackTraceElement, final StringBuilder sb,
-                             final String prefix, final TextRenderer textRenderer) {
+                             final String prefix, final TextRenderer textRenderer, final String suffix) {
         textRenderer.render(prefix, sb, "Prefix");
         textRenderer.render("\tat ", sb, "At");
         extStackTraceElement.renderOn(sb, textRenderer);
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
     }
 
     /**
      * Formats the specified Throwable.
-     *
-     * @param sb    StringBuilder to contain the formatted Throwable.
+     *  @param sb    StringBuilder to contain the formatted Throwable.
      * @param cause The Throwable to format.
+     * @param suffix
      */
-    public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause) {
-        this.formatWrapper(sb, cause, null, PlainTextRenderer.getInstance());
+    public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final String suffix) {
+        this.formatWrapper(sb, cause, null, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
      * Formats the specified Throwable.
-     *
-     * @param sb             StringBuilder to contain the formatted Throwable.
+     *  @param sb             StringBuilder to contain the formatted Throwable.
      * @param cause          The Throwable to format.
      * @param ignorePackages The List of packages to be suppressed from the trace.
+     * @param suffix
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-    public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> ignorePackages) {
-        this.formatWrapper(sb, cause, ignorePackages, PlainTextRenderer.getInstance());
+    public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> ignorePackages, final String suffix) {
+        this.formatWrapper(sb, cause, ignorePackages, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
      * Formats the specified Throwable.
-     *
-     * @param sb             StringBuilder to contain the formatted Throwable.
+     *  @param sb             StringBuilder to contain the formatted Throwable.
      * @param cause          The Throwable to format.
      * @param ignorePackages The List of packages to be suppressed from the trace.
      * @param textRenderer   The text render
+     * @param suffix
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause, final List<String> ignorePackages,
-                              final TextRenderer textRenderer) {
+                              final TextRenderer textRenderer, final String suffix) {
         final Throwable caused = cause.getCauseProxy() != null ? cause.getCauseProxy().getThrowable() : null;
         if (caused != null) {
-            this.formatWrapper(sb, cause.causeProxy, ignorePackages, textRenderer);
+            this.formatWrapper(sb, cause.causeProxy, ignorePackages, textRenderer, suffix);
             sb.append(WRAPPED_BY_LABEL);
+            renderSuffix(suffix, sb, textRenderer);
         }
         cause.renderOn(sb, textRenderer);
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
         this.formatElements(sb, Strings.EMPTY, cause.commonElementCount,
-            cause.getThrowable().getStackTrace(), cause.extendedStackTrace, ignorePackages, textRenderer);
+            cause.getThrowable().getStackTrace(), cause.extendedStackTrace, ignorePackages, textRenderer, suffix);
     }
 
     public ThrowableProxy getCauseProxy() {
@@ -352,19 +365,21 @@ public class ThrowableProxy implements Serializable {
      * Formats the Throwable that is the cause of this Throwable.
      *
      * @return The formatted Throwable that caused this Throwable.
+     * @param suffix
      */
-    public String getCauseStackTraceAsString() {
-        return this.getCauseStackTraceAsString(null, PlainTextRenderer.getInstance());
+    public String getCauseStackTraceAsString(final String suffix) {
+        return this.getCauseStackTraceAsString(null, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
      * Formats the Throwable that is the cause of this Throwable.
      *
      * @param packages The List of packages to be suppressed from the trace.
+     * @param suffix
      * @return The formatted Throwable that caused this Throwable.
      */
-    public String getCauseStackTraceAsString(final List<String> packages) {
-        return getCauseStackTraceAsString(packages, PlainTextRenderer.getInstance());
+    public String getCauseStackTraceAsString(final List<String> packages, final String suffix) {
+        return getCauseStackTraceAsString(packages, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
@@ -372,18 +387,21 @@ public class ThrowableProxy implements Serializable {
      *
      * @param ignorePackages The List of packages to be suppressed from the trace.
      * @param textRenderer   the text renderer
+     * @param suffix
      * @return The formatted Throwable that caused this Throwable.
      */
-    public String getCauseStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer) {
+    public String getCauseStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix) {
         final StringBuilder sb = new StringBuilder();
         if (this.causeProxy != null) {
-            this.formatWrapper(sb, this.causeProxy, ignorePackages, textRenderer);
+            this.formatWrapper(sb, this.causeProxy, ignorePackages, textRenderer, suffix);
             sb.append(WRAPPED_BY_LABEL);
+            renderSuffix(suffix, sb, textRenderer);
         }
         this.renderOn(sb, textRenderer);
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
         this.formatElements(sb, Strings.EMPTY, 0, this.throwable.getStackTrace(), this.extendedStackTrace,
-            ignorePackages, textRenderer);
+            ignorePackages, textRenderer, suffix);
         return sb.toString();
     }
 
@@ -410,19 +428,21 @@ public class ThrowableProxy implements Serializable {
      * Format the stack trace including packaging information.
      *
      * @return The formatted stack trace including packaging information.
+     * @param suffix
      */
-    public String getExtendedStackTraceAsString() {
-        return this.getExtendedStackTraceAsString(null, PlainTextRenderer.getInstance());
+    public String getExtendedStackTraceAsString(final String suffix) {
+        return this.getExtendedStackTraceAsString(null, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
      * Format the stack trace including packaging information.
      *
      * @param ignorePackages List of packages to be ignored in the trace.
+     * @param suffix
      * @return The formatted stack trace including packaging information.
      */
-    public String getExtendedStackTraceAsString(final List<String> ignorePackages) {
-        return getExtendedStackTraceAsString(ignorePackages, PlainTextRenderer.getInstance());
+    public String getExtendedStackTraceAsString(final List<String> ignorePackages, final String suffix) {
+        return getExtendedStackTraceAsString(ignorePackages, PlainTextRenderer.getInstance(), suffix);
     }
 
     /**
@@ -430,18 +450,20 @@ public class ThrowableProxy implements Serializable {
      *
      * @param ignorePackages List of packages to be ignored in the trace.
      * @param textRenderer   The message renderer
+     * @param suffix
      * @return The formatted stack trace including packaging information.
      */
-    public String getExtendedStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer) {
+    public String getExtendedStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix) {
         final StringBuilder sb = new StringBuilder(1024);
         textRenderer.render(name, sb, "Name");
         textRenderer.render(": ", sb, "NameMessageSeparator");
         textRenderer.render(this.message, sb, "Message");
+        renderSuffix(suffix, sb, textRenderer);
         textRenderer.render(EOL_STR, sb, "Text");
         final StackTraceElement[] causedTrace = this.throwable != null ? this.throwable.getStackTrace() : null;
-        this.formatElements(sb, Strings.EMPTY, 0, causedTrace, this.extendedStackTrace, ignorePackages, textRenderer);
-        this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, textRenderer);
-        this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, textRenderer);
+        this.formatElements(sb, Strings.EMPTY, 0, causedTrace, this.extendedStackTrace, ignorePackages, textRenderer, suffix);
+        this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, textRenderer, suffix);
+        this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, textRenderer, suffix);
         return sb.toString();
     }
 
@@ -479,15 +501,16 @@ public class ThrowableProxy implements Serializable {
      * Format the suppressed Throwables.
      *
      * @return The formatted suppressed Throwables.
+     * @param suffix
      */
-    public String getSuppressedStackTrace() {
+    public String getSuppressedStackTrace(final String suffix) {
         final ThrowableProxy[] suppressed = this.getSuppressedProxies();
         if (suppressed == null || suppressed.length == 0) {
             return Strings.EMPTY;
         }
         final StringBuilder sb = new StringBuilder("Suppressed Stack Trace Elements:").append(EOL);
         for (final ThrowableProxy proxy : suppressed) {
-            sb.append(proxy.getExtendedStackTraceAsString());
+            sb.append(proxy.getExtendedStackTraceAsString(suffix));
         }
         return sb.toString();
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
index a5cdcda..4cd0725 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.pattern;
 
 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.impl.ThrowableProxy;
 import org.apache.logging.log4j.util.Strings;
@@ -35,22 +36,23 @@ public final class ExtendedThrowablePatternConverter extends ThrowablePatternCon
 
     /**
      * Private constructor.
-     *
+     * @param config
      * @param options options, may be null.
      */
-    private ExtendedThrowablePatternConverter(final String[] options) {
-        super("ExtendedThrowable", "throwable", options);
+    private ExtendedThrowablePatternConverter(final Configuration config, final String[] options) {
+        super("ExtendedThrowable", "throwable", options, config);
     }
 
     /**
      * Gets an instance of the class.
      *
+     * @param config The current Configuration.
      * @param options pattern options, may be null.  If first element is "short",
      *                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 Configuration config, final String[] options) {
+        return new ExtendedThrowablePatternConverter(config, options);
     }
 
     /**
@@ -65,7 +67,8 @@ public final class ExtendedThrowablePatternConverter extends ThrowablePatternCon
                 super.format(event, toAppendTo);
                 return;
             }
-            final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getIgnorePackages(), options.getTextRenderer());
+            String suffix = getSuffix(event);
+            final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getIgnorePackages(), options.getTextRenderer(), suffix);
             final int len = toAppendTo.length();
             if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
                 toAppendTo.append(' ');

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
index 8b8983c..065ab9c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
@@ -204,7 +204,7 @@ public final class PatternParser {
             list.add(new PatternFormatter(pc, field));
         }
         if (alwaysWriteExceptions && !handlesThrowable) {
-            final LogEventPatternConverter pc = ExtendedThrowablePatternConverter.newInstance(null);
+            final LogEventPatternConverter pc = ExtendedThrowablePatternConverter.newInstance(config, null);
             list.add(new PatternFormatter(pc, FormattingInfo.getDefault()));
         }
         return list;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
index b2e101c..80beaf6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.pattern;
 
 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.impl.ThrowableProxy;
 import org.apache.logging.log4j.util.Strings;
@@ -36,22 +37,23 @@ public final class RootThrowablePatternConverter extends ThrowablePatternConvert
     /**
      * Private constructor.
      *
+     * @param config
      * @param options options, may be null.
      */
-    private RootThrowablePatternConverter(final String[] options) {
-        super("RootThrowable", "throwable", options);
+    private RootThrowablePatternConverter(final Configuration config, final String[] options) {
+        super("RootThrowable", "throwable", options, config);
     }
 
     /**
      * Gets an instance of the class.
      *
-     *
+     * @param config
      * @param options pattern options, may be null.  If first element is "short",
      *                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 Configuration config, final String[] options) {
+        return new RootThrowablePatternConverter(config, options);
     }
 
     /**
@@ -66,7 +68,8 @@ public final class RootThrowablePatternConverter extends ThrowablePatternConvert
                 super.format(event, toAppendTo);
                 return;
             }
-            final String trace = proxy.getCauseStackTraceAsString(options.getIgnorePackages());
+            String suffix = getSuffix(event);
+            final String trace = proxy.getCauseStackTraceAsString(options.getIgnorePackages(), suffix);
             final int len = toAppendTo.length();
             if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
                 toAppendTo.append(' ');

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
index a746130..91b6bab 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
@@ -18,10 +18,15 @@ package org.apache.logging.log4j.core.pattern;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 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.impl.ThrowableFormatOptions;
+import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.util.Strings;
 
 
@@ -34,6 +39,7 @@ import org.apache.logging.log4j.util.Strings;
 @ConverterKeys({ "ex", "throwable", "exception" })
 public class ThrowablePatternConverter extends LogEventPatternConverter {
 
+    protected final List<PatternFormatter> formatters;
     private String rawOption;
 
     /**
@@ -46,24 +52,52 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
      * @param name Name of converter.
      * @param style CSS style for output.
      * @param options options, may be null.
+     * @param config
      */
-    protected ThrowablePatternConverter(final String name, final String style, final String[] options) {
+    protected ThrowablePatternConverter(final String name, final String style, final String[] options, final Configuration config) {
         super(name, style);
         this.options = ThrowableFormatOptions.newInstance(options);
         if (options != null && options.length > 0) {
             rawOption = options[0];
         }
+        if (this.options.getSuffix() != null) {
+            final PatternParser parser = PatternLayout.createPatternParser(config);
+            List<PatternFormatter> parsedFormatters = parser.parse(this.options.getSuffix());
+            // filter out nested formatters that will handle throwable
+            boolean hasThrowableFormatter = false;
+            for (PatternFormatter formatter : parsedFormatters) {
+                if (formatter.handlesThrowable()) {
+                    hasThrowableFormatter = true;
+                }
+            }
+            if (!hasThrowableFormatter) {
+                this.formatters = parsedFormatters;
+            } else {
+                List<PatternFormatter> formatters = new ArrayList<>();
+                for (PatternFormatter formatter : parsedFormatters) {
+                    if (!formatter.handlesThrowable()) {
+                        formatters.add(formatter);
+                    }
+                }
+                this.formatters = formatters;
+            }
+        } else {
+            this.formatters = Collections.emptyList();
+        }
+
     }
 
     /**
      * Gets an instance of the class.
      *
+     *
+     * @param config
      * @param options pattern options, may be null.  If first element is "short",
      *                only the first line of the throwable will be formatted.
      * @return instance of class.
      */
-    public static ThrowablePatternConverter newInstance(final String[] options) {
-        return new ThrowablePatternConverter("Throwable", "throwable", options);
+    public static ThrowablePatternConverter newInstance(final Configuration config, final String[] options) {
+        return new ThrowablePatternConverter("Throwable", "throwable", options, config);
     }
 
     /**
@@ -166,4 +200,13 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
     public boolean handlesThrowable() {
         return true;
     }
+
+    protected String getSuffix(LogEvent event) {
+        //noinspection ForLoopReplaceableByForEach
+        StringBuilder toAppendTo = new StringBuilder();
+        for (int i = 0, size = formatters.size(); i <  size; i++) {
+            formatters.get(i).format(event, toAppendTo);
+        }
+        return toAppendTo.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
index 76fe83b..08f10de 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
@@ -35,22 +35,21 @@ import java.security.SecureRandom;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
-
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
 import javax.crypto.spec.IvParameterSpec;
 import javax.xml.bind.DatatypeConverter;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
 import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
+import org.apache.logging.log4j.util.Strings;
 import org.junit.Test;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
 /**
  *
  */
@@ -82,6 +81,19 @@ public class ThrowableProxyTest {
         return arr.toByteArray();
     }
 
+    private boolean allLinesContain(final String text, final String containedText) {
+        String[] lines = text.split("\n");
+        for (String line : lines) {
+            if (line.isEmpty()) {
+                continue;
+            }
+            if (!line.contains(containedText)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void testIoContainer(final ObjectMapper objectMapper ) throws IOException {
         final Fixture expected = new Fixture();
         final String s = objectMapper.writeValueAsString(expected);
@@ -228,7 +240,7 @@ public class ThrowableProxyTest {
         final byte[] binary = serialize(proxy);
         final ThrowableProxy proxy2 = deserialize(binary);
 
-        assertEquals(proxy.getExtendedStackTraceAsString(), proxy2.getExtendedStackTraceAsString());
+        assertEquals(proxy.getExtendedStackTraceAsString(Strings.EMPTY), proxy2.getExtendedStackTraceAsString(Strings.EMPTY));
     }
 
     @Test
@@ -256,7 +268,7 @@ public class ThrowableProxyTest {
         final byte[] binary = serialize(proxy);
         final ThrowableProxy proxy2 = deserialize(binary);
 
-        assertEquals(proxy.getExtendedStackTraceAsString(), proxy2.getExtendedStackTraceAsString());
+        assertEquals(proxy.getExtendedStackTraceAsString(Strings.EMPTY), proxy2.getExtendedStackTraceAsString(Strings.EMPTY));
     }
 
     @Test
@@ -282,6 +294,64 @@ public class ThrowableProxyTest {
     }
 
     @Test
+    public void testSuffix_getExtendedStackTraceAsString() throws Exception {
+        final Throwable throwable = new IllegalArgumentException("This is a test");
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getExtendedStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
+    public void testSuffix_getExtendedStackTraceAsStringWithCausedThrowable() throws Exception {
+        final Throwable throwable = new RuntimeException(new IllegalArgumentException("This is a test"));
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getExtendedStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
+    public void testSuffix_getExtendedStackTraceAsStringWithSuppressedThrowable() throws Exception {
+        IllegalArgumentException cause = new IllegalArgumentException("This is a test");
+        final Throwable throwable = new RuntimeException(cause);
+        throwable.addSuppressed(new IOException("This is a test"));
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getExtendedStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
+    public void testSuffix_getCauseStackTraceAsString() throws Exception {
+        final Throwable throwable = new IllegalArgumentException("This is a test");
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getCauseStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
+    public void testSuffix_getCauseStackTraceAsStringWithCausedThrowable() throws Exception {
+        final Throwable throwable = new RuntimeException(new IllegalArgumentException("This is a test"));
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getCauseStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
+    public void testSuffix_getCauseStackTraceAsStringWithSuppressedThrowable() throws Exception {
+        IllegalArgumentException cause = new IllegalArgumentException("This is a test");
+        final Throwable throwable = new RuntimeException(cause);
+        throwable.addSuppressed(new IOException("This is a test"));
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        String suffix = "some suffix";
+        assertTrue(allLinesContain(proxy.getCauseStackTraceAsString(suffix), suffix));
+    }
+
+    @Test
     public void testStack() {
         final Map<String, ThrowableProxy.CacheEntry> map = new HashMap<>();
         final Stack<Class<?>> stack = new Stack<>();
@@ -332,7 +402,7 @@ public class ThrowableProxyTest {
 		e.addSuppressed(new IOException("Suppressed #2"));
 		LogManager.getLogger().error("Error", e);
 		final ThrowableProxy proxy = new ThrowableProxy(e);
-		final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString();
+		final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString("same suffix");
 		assertTrue(extendedStackTraceAsString.contains("\tSuppressed: java.io.IOException: Suppressed #1"));
 		assertTrue(extendedStackTraceAsString.contains("\tSuppressed: java.io.IOException: Suppressed #1"));
 	}
@@ -344,7 +414,7 @@ public class ThrowableProxyTest {
 		cause.addSuppressed(new IOException("Suppressed #2"));
 		LogManager.getLogger().error("Error", new Exception(cause));
 		final ThrowableProxy proxy = new ThrowableProxy(new Exception("Root exception", cause));
-		final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString();
+		final String extendedStackTraceAsString = proxy.getExtendedStackTraceAsString("same suffix");
 		assertTrue(extendedStackTraceAsString.contains("\tSuppressed: java.io.IOException: Suppressed #1"));
 		assertTrue(extendedStackTraceAsString.contains("\tSuppressed: java.io.IOException: Suppressed #1"));
 	}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
index 8dfb2f5..9bd30d4 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
@@ -23,6 +23,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
@@ -36,8 +37,47 @@ import org.junit.Test;
 public class ExtendedThrowablePatternConverterTest {
 
     @Test
+    public void testSuffixFromNormalPattern() {
+        final String suffix = "suffix(%mdc{key})";
+        ThreadContext.put("key", "test suffix ");
+        final String[] options = {suffix};
+        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setLoggerName("testLogger") //
+                .setLoggerFqcn(this.getClass().getName()) //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("test exception")) //
+                .setThrown(parent).build();
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertTrue("No suffix", result.contains("test suffix"));
+    }
+
+    @Test
+    public void testSuffix() {
+        final String suffix = "suffix(test suffix)";
+        final String[] options = {suffix};
+        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setLoggerName("testLogger") //
+                .setLoggerFqcn(this.getClass().getName()) //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("test exception")) //
+                .setThrown(parent).build();
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertTrue("No suffix", result.contains("test suffix"));
+    }
+
+    @Test
 	public void testDeserializedLogEventWithThrowableProxyButNoThrowable() {
-		final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null);
+		final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, null);
 		final Throwable originalThrowable = new Exception("something bad happened");
 		final ThrowableProxy throwableProxy = new ThrowableProxy(originalThrowable);
 		final Throwable deserializedThrowable = null;
@@ -60,7 +100,7 @@ public class ExtendedThrowablePatternConverterTest {
     public void testFiltering() {
         final String packages = "filters(org.junit, org.apache.maven, sun.reflect, java.lang.reflect)";
         final String[] options = {packages};
-        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(options);
+        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //
@@ -77,7 +117,7 @@ public class ExtendedThrowablePatternConverterTest {
 
     @Test
     public void testFull() {
-        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null);
+        final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, null);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverterTest.java
index 7c07d3f..3c45c7a 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverterTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverterTest.java
@@ -16,22 +16,62 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import static org.junit.Assert.assertTrue;
+
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-
 /**
  *
  */
 public class RootThrowablePatternConverterTest {
 
     @Test
+    public void testSuffix() {
+        final String suffix = "suffix(test suffix)";
+        final String[] options = {suffix};
+        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null, options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setLoggerName("testLogger") //
+                .setLoggerFqcn(this.getClass().getName()) //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("test exception")) //
+                .setThrown(parent).build();
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertTrue("No suffix", result.contains("test suffix"));
+    }
+
+    @Test
+    public void testSuffixFromNormalPattern() {
+        final String suffix = "suffix(%mdc{key})";
+        ThreadContext.put("key", "test suffix ");
+        final String[] options = {suffix};
+        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null, options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = Log4jLogEvent.newBuilder() //
+                .setLoggerName("testLogger") //
+                .setLoggerFqcn(this.getClass().getName()) //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("test exception")) //
+                .setThrown(parent).build();
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertTrue("No suffix", result.contains("test suffix"));
+    }
+
+    @Test
     public void testFull1() {
-        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null);
+        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null, null);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //
@@ -55,7 +95,7 @@ public class RootThrowablePatternConverterTest {
      */
     @Test
     public void testFull2() {
-        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null);
+        final RootThrowablePatternConverter converter = RootThrowablePatternConverter.newInstance(null, null);
         Throwable parent;
         try {
             try {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0146bbae/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
index e3c1f45..55aa895 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
@@ -16,14 +16,15 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-
 public class ThrowablePatternConverterTest {
 
     private final static class LocalizedException extends Exception {
@@ -42,13 +43,13 @@ public class ThrowablePatternConverterTest {
     @Test(expected = Exception.class)
     public void testBadShortOption() {
         final String[] options = { "short.UNKNOWN" };
-        ThrowablePatternConverter.newInstance(options);
+        ThrowablePatternConverter.newInstance(null, options);
     }
 
     @Test
     public void testFull() {
         final String[] options = { "full" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         Throwable parent;
         try {
             try {
@@ -77,7 +78,7 @@ public class ThrowablePatternConverterTest {
     public void testShortClassName() {
         final String packageName = "org.apache.logging.log4j.core.pattern.";
         final String[] options = { "short.className" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //
@@ -95,7 +96,7 @@ public class ThrowablePatternConverterTest {
     @Test
     public void testShortFileName() {
         final String[] options = { "short.fileName" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //
@@ -113,7 +114,7 @@ public class ThrowablePatternConverterTest {
     @Test
     public void testShortLineNumber() {
         final String[] options = { "short.lineNumber" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final StackTraceElement top = parent.getStackTrace()[0];
@@ -134,7 +135,7 @@ public class ThrowablePatternConverterTest {
     @Test
     public void testShortLocalizedMessage() {
         final String[] options = { "short.localizedMessage" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable parent = new LocalizedException();
         final LogEvent event = Log4jLogEvent.newBuilder() //
                 .setLoggerName("testLogger") //
@@ -151,7 +152,7 @@ public class ThrowablePatternConverterTest {
     @Test
     public void testShortMessage() {
         final String[] options = { "short.message" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //
@@ -169,7 +170,7 @@ public class ThrowablePatternConverterTest {
     @Test
     public void testShortMethodName() {
         final String[] options = { "short.methodName" };
-        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(null, options);
         final Throwable cause = new NullPointerException("null pointer");
         final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
         final LogEvent event = Log4jLogEvent.newBuilder() //