Repository: logging-log4j2
Updated Branches:
  refs/heads/master 96327da7d -> 825f15574


[LOG4J2-684] ExtendedThrowablePatternConverter does not print suppressed
exceptions.

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

Branch: refs/heads/master
Commit: 825f15574d9cd020432e99ddfa307fb0287d825c
Parents: 96327da
Author: ggregory <[email protected]>
Authored: Mon Jun 29 12:14:40 2015 -0700
Committer: ggregory <[email protected]>
Committed: Mon Jun 29 12:14:40 2015 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/impl/ThrowableProxy.java | 112 +++++++++++--------
 ...nsoleAppenderDefaultSuppressedThrowable.java |  67 +++++++++++
 .../log4j/core/impl/ThrowableProxyTest.java     |  25 +++++
 ...4j2-console-default-suppressed-throwable.xml |  31 +++++
 src/changes/changes.xml                         |   3 +
 5 files changed, 194 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/825f1557/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 d0800cc..bcd38dd 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
@@ -51,7 +51,11 @@ import org.apache.logging.log4j.util.Strings;
  */
 public class ThrowableProxy implements Serializable {
 
-    /**
+       private static final String CAUSED_BY_LABEL = "Caused by: ";
+       private static final String SUPPRESSED_LABEL = "Suppressed: ";
+    private static final String WRAPPED_BY_LABEL = "Wrapped by: ";
+
+       /**
      * Cached StackTracePackageElement and ClassLoader.
      * <p>
      * Consider this class private.
@@ -201,46 +205,64 @@ public class ThrowableProxy implements Serializable {
         return true;
     }
 
-    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-       private void formatCause(final StringBuilder sb, final ThrowableProxy 
cause, final List<String> ignorePackages) {
-               if (cause == null) {
+       private void formatCause(final StringBuilder sb, String prefix, final 
ThrowableProxy cause, final List<String> ignorePackages) {
+               formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, 
ignorePackages);
+       }
+
+       private void formatThrowableProxy(final StringBuilder sb, String 
prefix, final String causeLabel,
+                       final ThrowableProxy throwableProxy, final List<String> 
ignorePackages) {
+               if (throwableProxy == null) {
                        return;
                }
-               sb.append("Caused by: ").append(cause).append(EOL);
-               this.formatElements(sb, cause.commonElementCount, 
cause.getStackTrace(), cause.extendedStackTrace,
-                               ignorePackages);
-               this.formatCause(sb, cause.causeProxy, ignorePackages);
+               
sb.append(prefix).append(causeLabel).append(throwableProxy).append(EOL);
+               this.formatElements(sb, prefix, 
throwableProxy.commonElementCount,
+                               throwableProxy.getStackTrace(), 
throwableProxy.extendedStackTrace, ignorePackages);
+               this.formatSuppressed(sb, prefix + "\t", 
throwableProxy.suppressedProxies, ignorePackages);
+               this.formatCause(sb, prefix, throwableProxy.causeProxy, 
ignorePackages);
        }
 
-    private void formatElements(final StringBuilder sb, final int commonCount, 
final StackTraceElement[] causedTrace,
-            final ExtendedStackTraceElement[] extStackTrace, final 
List<String> ignorePackages) {
-        if (ignorePackages == null || ignorePackages.isEmpty()) {
-            for (final ExtendedStackTraceElement element : extStackTrace) {
-                this.formatEntry(element, sb);
-            }
-        } else {
-            int count = 0;
-            for (int i = 0; i < extStackTrace.length; ++i) {
-                if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
-                    if (count > 0) {
-                        appendSuppressedCount(sb, count);
-                        count = 0;
-                    }
-                    this.formatEntry(extStackTrace[i], sb);
-                } else {
-                    ++count;
-                }
-            }
-            if (count > 0) {
-                appendSuppressedCount(sb, count);
-            }
-        }
-        if (commonCount != 0) {
-            sb.append("\t... ").append(commonCount).append(" 
more").append(EOL);
-        }
-    }
+       private void formatSuppressed(final StringBuilder sb, String prefix, 
final ThrowableProxy[] suppressedProxies,
+                       final List<String> ignorePackages) {
+               if (suppressedProxies == null) {
+                       return;
+               }
+               for (ThrowableProxy suppressedProxy : suppressedProxies) {
+                       final ThrowableProxy cause = suppressedProxy;
+                       formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, 
cause, ignorePackages);
+               }
+       }
+
+       private void formatElements(final StringBuilder sb, String prefix, 
final int commonCount,
+                       final StackTraceElement[] causedTrace, final 
ExtendedStackTraceElement[] extStackTrace,
+                       final List<String> ignorePackages) {
+               if (ignorePackages == null || ignorePackages.isEmpty()) {
+                       for (final ExtendedStackTraceElement element : 
extStackTrace) {
+                               this.formatEntry(element, sb, prefix);
+                       }
+               } 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);
+                                               count = 0;
+                                       }
+                                       this.formatEntry(extStackTrace[i], sb, 
prefix);
+                               } else {
+                                       ++count;
+                               }
+                       }
+                       if (count > 0) {
+                               appendSuppressedCount(sb, prefix, count);
+                       }
+               }
+               if (commonCount != 0) {
+                       sb.append(prefix).append("\t... 
").append(commonCount).append(" more").append(EOL);
+               }
+       }
 
-    private void appendSuppressedCount(final StringBuilder sb, final int 
count) {
+    private void appendSuppressedCount(final StringBuilder sb, String prefix, 
final int count) {
+       sb.append(prefix);
         if (count == 1) {
             sb.append("\t....").append(EOL);
         } else {
@@ -248,7 +270,8 @@ public class ThrowableProxy implements Serializable {
         }
     }
 
-    private void formatEntry(final ExtendedStackTraceElement 
extStackTraceElement, final StringBuilder sb) {
+    private void formatEntry(final ExtendedStackTraceElement 
extStackTraceElement, final StringBuilder sb, String prefix) {
+        sb.append(prefix);
         sb.append("\tat ");
         sb.append(extStackTraceElement);
         sb.append(EOL);
@@ -281,11 +304,11 @@ public class ThrowableProxy implements Serializable {
         final Throwable caused = cause.getCauseProxy() != null ? 
cause.getCauseProxy().getThrowable() : null;
         if (caused != null) {
             this.formatWrapper(sb, cause.causeProxy);
-            sb.append("Wrapped by: ");
+            sb.append(WRAPPED_BY_LABEL);
         }
         sb.append(cause).append(EOL);
-        this.formatElements(sb, cause.commonElementCount, 
cause.getThrowable().getStackTrace(),
-                cause.extendedStackTrace, packages);
+        this.formatElements(sb, "", cause.commonElementCount,
+                cause.getThrowable().getStackTrace(), 
cause.extendedStackTrace, packages);
     }
 
     public ThrowableProxy getCauseProxy() {
@@ -312,11 +335,11 @@ public class ThrowableProxy implements Serializable {
         final StringBuilder sb = new StringBuilder();
         if (this.causeProxy != null) {
             this.formatWrapper(sb, this.causeProxy);
-            sb.append("Wrapped by: ");
+            sb.append(WRAPPED_BY_LABEL);
         }
         sb.append(this.toString());
         sb.append(EOL);
-        this.formatElements(sb, 0, this.throwable.getStackTrace(), 
this.extendedStackTrace, packages);
+        this.formatElements(sb, "", 0, this.throwable.getStackTrace(), 
this.extendedStackTrace, packages);
         return sb.toString();
     }
 
@@ -363,8 +386,9 @@ public class ThrowableProxy implements Serializable {
         }
         sb.append(EOL);
         final StackTraceElement[] causedTrace = this.throwable != null ? 
this.throwable.getStackTrace() : null;
-        this.formatElements(sb, 0, causedTrace, this.extendedStackTrace, 
ignorePackages);
-        this.formatCause(sb, this.causeProxy, ignorePackages);
+        this.formatElements(sb, "", 0, causedTrace, this.extendedStackTrace, 
ignorePackages);
+        this.formatSuppressed(sb, "\t", this.suppressedProxies, 
ignorePackages);
+        this.formatCause(sb, "", this.causeProxy, ignorePackages);
         return sb.toString();
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/825f1557/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
new file mode 100644
index 0000000..e3295c0
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderDefaultSuppressedThrowable.java
@@ -0,0 +1,67 @@
+/*
+ * 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.appender;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configurator;
+
+/**
+ * Shows how to use ANSI escape codes to color messages. Each message is 
printed
+ * to the console in color, but the rest of the log entry (time stamp for
+ * example) is in the default color for that console.
+ * <p>
+ * Running from a Windows command line from the root of the project:
+ * </p>
+ * 
+ * <pre>
+ * java -classpath 
log4j-core\target\test-classes;log4j-core\target\classes;log4j-api\target\classes;%HOME%\.m2\repository\org\fusesource\jansi\jansi\1.11\jansi-1.11.jar;
 org.apache.logging.log4j.core.appender.ConsoleAppenderNoAnsiStyleLayoutMain 
log4j-core/target/test-classes/log4j2-console-style-ansi.xml
+ * </pre>
+ */
+public class ConsoleAppenderDefaultSuppressedThrowable {
+
+       private static final Logger LOG = 
LogManager.getLogger(ConsoleAppenderDefaultSuppressedThrowable.class);
+
+       public static void main(final String[] args) {
+               final String config = args.length == 0 ? 
"target/test-classes/log4j2-console-default-suppressed-throwable.xml"
+                               : args[0];
+               test(args, config);
+       }
+
+       static void test(final String[] args, final String config) {
+               // System.out.println(System.getProperty("java.class.path"));
+               final LoggerContext ctx = 
Configurator.initialize(ConsoleAppenderDefaultSuppressedThrowable.class.getName(),
+                               config);
+               try {
+                       IOException ioEx = new IOException("test suppressed");
+                       ioEx.addSuppressed(new IOException("test suppressed 1", 
new IOException("test 1")));
+                       IOException ioEx2 = new IOException("test 2");
+                       ioEx2.addSuppressed(new IOException("test 3"));
+                       ioEx.addSuppressed(new IOException("test suppressed 2", 
ioEx2));
+                       IOException e = new IOException("test", ioEx);
+                       LOG.error("Error message {}, suppressed?", "Hi", e);
+                       System.out.println("printStackTrace");
+                       e.printStackTrace();
+               } finally {
+                       Configurator.shutdown(ctx);
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/825f1557/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 08d0a4b..c3128d4 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
@@ -19,6 +19,7 @@ package org.apache.logging.log4j.core.impl;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
@@ -240,6 +241,30 @@ public class ThrowableProxyTest {
         LogManager.getLogger().error("Error", e1);
     }
 
+    @Test
+    public void testSuppressedExceptions() {
+        Exception e = new Exception();
+        e.addSuppressed(new IOException("Suppressed #1"));
+        e.addSuppressed(new IOException("Suppressed #2"));
+        LogManager.getLogger().error("Error", e);
+        final ThrowableProxy proxy = new ThrowableProxy(e);
+        String extendedStackTraceAsString = 
proxy.getExtendedStackTraceAsString();
+        assertTrue(extendedStackTraceAsString.contains("Suppressed #1"));
+        assertTrue(extendedStackTraceAsString.contains("Suppressed #2"));
+    }
+
+    @Test
+    public void testCauseSuppressedExceptions() {
+        Exception cause = new Exception();
+        cause.addSuppressed(new IOException("Suppressed #1"));
+        cause.addSuppressed(new IOException("Suppressed #2"));
+        LogManager.getLogger().error("Error", cause);
+        final ThrowableProxy proxy = new ThrowableProxy(new Exception(cause));
+        String extendedStackTraceAsString = 
proxy.getExtendedStackTraceAsString();
+        assertTrue(extendedStackTraceAsString.contains("Suppressed #1"));
+        assertTrue(extendedStackTraceAsString.contains("Suppressed #2"));
+    }
+
     /**
      * Tests LOG4J2-934.
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/825f1557/log4j-core/src/test/resources/log4j2-console-default-suppressed-throwable.xml
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/resources/log4j2-console-default-suppressed-throwable.xml 
b/log4j-core/src/test/resources/log4j2-console-default-suppressed-throwable.xml
new file mode 100644
index 0000000..90f9373
--- /dev/null
+++ 
b/log4j-core/src/test/resources/log4j2-console-default-suppressed-throwable.xml
@@ -0,0 +1,31 @@
+<?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">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout noConsoleNoAnsi="true" pattern="[%-5p] %d{yyyy/MM/dd 
HH:mm:ss} - %t - %c - %m%n" />
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Logger name="org.foo" level="DEBUG" />
+    <Root level="TRACE">
+      <AppenderRef ref="Console" />
+    </Root>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/825f1557/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c6ad6dc..e682373 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -48,6 +48,9 @@
       <action issue="LOG4J2-1051" dev="ggregory" type="fix" due-to="Lukasz 
Lenart">
         NoClassDefFoundError when starting app on Google App Engine.
       </action>
+      <action issue="LOG4J2-684" dev="ggregory" type="fix" due-to="Joern 
Huxhorn, Mauro Molinari">
+        ExtendedThrowablePatternConverter does not print suppressed exceptions.
+      </action>
       <action issue="LOG4J2-1069" dev="ggregory" type="fix" due-to="Sam Braam">
         Improper handling of JSON escape chars when deserializing JSON log 
events.
       </action>

Reply via email to