logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ggreg...@apache.org
Subject svn commit: r1519707 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ src/chan...
Date Tue, 03 Sep 2013 14:55:31 GMT
Author: ggregory
Date: Tue Sep  3 14:55:31 2013
New Revision: 1519707

URL: http://svn.apache.org/r1519707
Log:
[LOG4J2-374] Add more options to PatternLayout to display more detailed information about
a Throwable.

Added:
    logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
  (with props)
Modified:
    logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
    logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm

Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java?rev=1519707&r1=1519706&r2=1519707&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
(original)
+++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptions.java
Tue Sep  3 14:55:31 2013
@@ -64,6 +64,13 @@ public final class ThrowableFormatOption
      */
     private final List<String> packages;
 
+    public static final String CLASS_NAME = "short.className";
+    public static final String METHOD_NAME = "short.methodName";
+    public static final String LINE_NUMBER = "short.lineNumber";
+    public static final String FILE_NAME = "short.fileName";
+    public static final String MESSAGE = "short.message";
+    public static final String LOCALIZED_MESSAGE = "short.localizedMessage";
+
     /**
      * Construct the options for printing stack trace.
      * @param lines The number of lines.
@@ -217,7 +224,10 @@ public final class ThrowableFormatOption
                     }
                 } else if (option.equalsIgnoreCase(NONE)) {
                     lines = 0;
-                } else if (option.equalsIgnoreCase(SHORT)) {
+                } else if (option.equalsIgnoreCase(SHORT) || option.equalsIgnoreCase(CLASS_NAME)
||
+                        option.equalsIgnoreCase(METHOD_NAME) || option.equalsIgnoreCase(LINE_NUMBER)
||
+                        option.equalsIgnoreCase(FILE_NAME) || option.equalsIgnoreCase(MESSAGE)
|| 
+                        option.equalsIgnoreCase(LOCALIZED_MESSAGE)) {
                     lines = 2;
                 } else if (!option.equalsIgnoreCase(FULL)) {
                     lines = Integer.parseInt(option);

Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java?rev=1519707&r1=1519706&r2=1519707&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
(original)
+++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
Tue Sep  3 14:55:31 2013
@@ -34,6 +34,8 @@ import org.apache.logging.log4j.core.imp
 @ConverterKeys({"ex", "throwable", "exception" })
 public class ThrowablePatternConverter extends LogEventPatternConverter {
 
+    private String rawOption;
+
     /**
      * The number of lines to write.
      */
@@ -48,6 +50,9 @@ public class ThrowablePatternConverter e
     protected ThrowablePatternConverter(final String name, final String style, final String[]
options) {
         super(name, style);
         this.options = ThrowableFormatOptions.newInstance(options);
+        if (options != null && options.length > 0) {
+            rawOption = options[0];
+        }
     }
 
     /**
@@ -65,31 +70,90 @@ public class ThrowablePatternConverter e
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+    public void format(final LogEvent event, final StringBuilder buffer) {
         final Throwable t = event.getThrown();
 
-        if (t != null && options.anyLines()) {
-            final StringWriter w = new StringWriter();
-            t.printStackTrace(new PrintWriter(w));
-            final int len = toAppendTo.length();
-            if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1)))
{
-                toAppendTo.append(" ");
-            }
-            if (!options.allLines() || !Constants.LINE_SEP.equals(options.getSeparator()))
{
-                final StringBuilder sb = new StringBuilder();
-                final String[] array = w.toString().split(Constants.LINE_SEP);
-                final int limit = options.minLines(array.length) - 1;
-                for (int i = 0; i <= limit; ++i) {
-                    sb.append(array[i]);
-                    if (i < limit) {
-                        sb.append(options.getSeparator());
-                    }
-                }
-                toAppendTo.append(sb.toString());
+        if (isSubShortOption()) {
+            formatSubShortOption(t, buffer);
+        }
+        else if (t != null && options.anyLines()) {
+            formatOption(t, buffer);
+        }
+    }
+
+    private boolean isSubShortOption() {
+        return ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption);
+    }
+
+    private void formatSubShortOption(final Throwable t, final StringBuilder buffer) {
+        StackTraceElement[] trace;
+        StackTraceElement throwingMethod = null;
+        int len;
+
+        if (t != null) {
+            trace = t.getStackTrace();
+            if (trace !=null && trace.length > 0) {
+                throwingMethod = trace[0];
+            }
+        }
 
-            } else {
-                toAppendTo.append(w.toString());
+        if (t != null && throwingMethod != null) {
+            String toAppend = "";
+
+            if (ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption)) {
+                toAppend = throwingMethod.getClassName();
+            }
+            else if (ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption)) {
+                toAppend = throwingMethod.getMethodName();
+            }
+            else if (ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption)) {
+                toAppend = String.valueOf(throwingMethod.getLineNumber());
             }
+            else if (ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption)) {
+                toAppend = t.getMessage();
+            }
+            else if (ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption))
{
+                toAppend = t.getLocalizedMessage();
+            }
+            else if (ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption)) {
+                toAppend = throwingMethod.getFileName();
+            }
+
+            len = buffer.length();
+            if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
+                buffer.append(" ");
+            }
+            buffer.append(toAppend);
+        }
+    }
+
+    private void formatOption(final Throwable t, final StringBuilder buffer) {
+        final StringWriter w = new StringWriter();
+
+        t.printStackTrace(new PrintWriter(w));
+        final int len = buffer.length();
+        if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
+            buffer.append(' ');
+        }
+        if (!options.allLines() || !Constants.LINE_SEP.equals(options.getSeparator())) {
+            final StringBuilder sb = new StringBuilder();
+            final String[] array = w.toString().split(Constants.LINE_SEP);
+            final int limit = options.minLines(array.length) - 1;
+            for (int i = 0; i <= limit; ++i) {
+                sb.append(array[i]);
+                if (i < limit) {
+                    sb.append(options.getSeparator());
+                }
+            }
+            buffer.append(sb.toString());
+
+        } else {
+            buffer.append(w.toString());
         }
     }
 

Added: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java?rev=1519707&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
(added)
+++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
Tue Sep  3 14:55:31 2013
@@ -0,0 +1,119 @@
+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;
+
+public class ThrowablePatternConverterTest {
+
+    private final static class LocalizedException extends Exception {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String getLocalizedMessage() {
+            return "I am localized.";
+        }
+    }
+
+    /**
+     * TODO: Needs better a better exception? NumberFormatException is NOT helpful.
+     */
+    @Test(expected=Exception.class)
+    public void testBadShortOption() {
+        final String[] options = { "short.UNKNOWN" };
+        ThrowablePatternConverter.newInstance(options);
+    }
+
+    @Test
+    public void testClassName() {
+        final String packageName = "org.apache.logging.log4j.core.pattern.";
+        final String[] options = { "short.className" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertEquals("The class names should be same", packageName + "ThrowablePatternConverterTest",
result);
+    }
+
+    @Test
+    public void testFileName() {
+        final String[] options = { "short.fileName" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertEquals("The file names should be same", "ThrowablePatternConverterTest.java",
result);
+    }
+
+    @Test
+    public void testLineNumber() {
+        final String[] options = { "short.lineNumber" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final StackTraceElement top = parent.getStackTrace()[0];
+        final int expectedLineNumber = top.getLineNumber();
+
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertTrue("The line numbers should be same", expectedLineNumber == Integer.parseInt(result));
+    }
+    
+    @Test
+    public void testLocalizedMessage() {
+        final String[] options = { "short.localizedMessage" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable parent = new LocalizedException();
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertEquals("The messages should be same", "I am localized.", result);
+    }
+
+    @Test
+    public void testMessage() {
+        final String[] options = { "short.message" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertEquals("The messages should be same", "IllegalArgument", result);
+    }
+
+    @Test
+    public void testMethodName() {
+        final String[] options = { "short.methodName" };
+        final ThrowablePatternConverter converter = ThrowablePatternConverter.newInstance(options);
+        final Throwable cause = new NullPointerException("null pointer");
+        final Throwable parent = new IllegalArgumentException("IllegalArgument", cause);
+        final LogEvent event = new Log4jLogEvent("testLogger", null, this.getClass().getName(),
Level.DEBUG,
+                new SimpleMessage("test exception"), parent);
+        final StringBuilder sb = new StringBuilder();
+        converter.format(event, sb);
+        final String result = sb.toString();
+        assertEquals("The method names should be same", "testMethodName", result);
+    }
+}

Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1519707&r1=1519706&r2=1519707&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Tue Sep  3 14:55:31 2013
@@ -62,6 +62,9 @@
         Changed the Servlet 3.0 auto-initializer so that it does nothing in a Servlet 2.5
or older application. This
         ensures behavioral consistency across containers.
       </action>
+      <action issue="LOG4J2-374" dev="ggregory" type="add" due-to="Tibor Benke">
+        Add more options to PatternLayout to display more detailed information about a Throwable.
+      </action>
       <action dev="nickwilliams" type="update">
         Cleaned up tests and cleared up documentation for the JPA appender following the
resolution of EclipseLink
         issue #412454.

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm?rev=1519707&r1=1519706&r2=1519707&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/layouts.xml.vm Tue Sep  3 14:55:31 2013
@@ -365,19 +365,52 @@ WARN  [main]: Message 2</pre>
             </tr>
             <tr>
               <td align="center">
-                <b>ex</b>{["none"|"short"|"full"|depth]}<br />
-                <b>exception</b>{["none"|"short"|"full"|depth]}<br />
-                <b>throwable</b>{["none"|"short"|"full"|depth]}
+                <b>ex</b>|<b>exception</b>|<b>throwable</b><br
/>
+                &nbsp;&nbsp;{["none"<br />
+                &nbsp;&nbsp;|"full"<br />
+                &nbsp;&nbsp;|depth<br />
+                &nbsp;&nbsp;|"short"<br />
+                &nbsp;&nbsp;|"short.className"<br />
+                &nbsp;&nbsp;|"short.fileName"<br />
+                &nbsp;&nbsp;|"short.lineNumber"<br />
+                &nbsp;&nbsp;|"short.methodName"<br />
+                &nbsp;&nbsp;|"short.message"<br />
+                &nbsp;&nbsp;|"short.localizedMessage"]}
               </td>
               <td>
-                <p>Outputs the Throwable trace that has been bound to the LoggingEvent,
by
-                  default this will output the full trace as one would normally find by a
call to
-                  Throwable.printStackTrace().
-                  The throwable conversion word can be followed by an option in the form
-                  <b>%throwable{short}</b>
-                  which will only output the first line of the Throwable or <b>%throwable{n}</b>
where
-                  the first n lines of the stacktrace will be printed. Specifying <b>%throwable{none}</b>
-                  or <b>%throwable{0}</b> will suppress printing of the exception.
+                <p>
+                  Outputs the Throwable trace bound to the LoggingEvent, by default this
will output the full trace 
+                  as one would normally find with a call to Throwable.printStackTrace().
+                </p>
+                <p>
+                  You can follow the throwable conversion word with an option in the form
<b>%throwable{option}</b>.
+                </p>
+                <p> 
+                  <b>%throwable{short}</b> outputs the first line of the Throwable.
+                </p>
+                <p> 
+                  <b>%throwable{short.className}</b> outputs the name of the
class where the exception occurred.
+                </p>
+                <p> 
+                  <b>%throwable{short.methodName}</b> outputs the method name
where the exception occurred.
+                </p>
+                <p> 
+                  <b>%throwable{short.fileName}</b> outputs the name of the class
where the exception occurred.
+                </p>
+                <p> 
+                  <b>%throwable{short.lineNumber}</b> outputs the line number
where the exception occurred.
+                </p>
+                <p> 
+                  <b>%throwable{short.message}</b> outputs the message.
+                </p>
+                <p> 
+                  <b>%throwable{short.localizedMessage}</b> outputs the localized
message.
+                </p>
+                <p> 
+                  <b>%throwable{n}</b> outputs the first n lines of the stack
trace. 
+                </p> 
+                <p> 
+                  Specifying <b>%throwable{none}</b> or <b>%throwable{0}</b>
suppresses output of the exception.
                 </p>
               </td>
             </tr>



Mime
View raw message