Bug 48902 - log4j-extras - Enhancement : add %throwable{compact} to EnhancedPatternLayout
log4j-extras - Enhancement : add %throwable{compact} to EnhancedPatternLayout
Status: RESOLVED FIXED
Product: Log4j
Classification: Unclassified
Component: Appender
unspecified
PC Mac OS X 10.4
: P2 normal
: ---
Assigned To: log4j-dev
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2010-03-12 17:48 UTC by Cyrille Le Clerc
Modified: 2014-02-17 13:57 UTC (History)
1 user (show)



Attachments
proposed implementation of the enhancement (4.58 KB, patch)
2010-03-12 17:51 UTC, Cyrille Le Clerc
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Cyrille Le Clerc 2010-03-12 17:48:20 UTC
Here is a proposal to add an intermediate way to emit throwables in the logs. It is between '%throwable{short}' that only add the class name and message of the given throwable and standard '%throwable' that emits the full stacktrace.

This proposed '%throwable{compact}' concatenates the class name and message of the given throwable and its causes on the same line as the .

SAMPLES
======

NONE
-----

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss,SSS} %5p [%t] %c - %m %throwable{none} %n

2010/03/12 18:39:00,083 ERROR [main] my-category - An exception occured  

SHORT
-----

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss,SSS} %5p [%t] %c - %m %throwable{short} %n

2010/03/12 18:37:34,580 ERROR [main] my-category - An exception occured java.io.IOException: Exception invoking http://example.com/


COMPACT
--------

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss,SSS} %5p [%t] %c - %m %throwable{compact} %n

2010/03/12 18:35:34,934 ERROR [main] my-category - An exception occured  - java.io.IOException: Exception invoking http://example.com/ java.net.SocketTimeoutException: Read timed out 

STANDARD
---------

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss,SSS} %5p [%t] %c - %m %throwable %n

2010/03/12 18:40:01,930 ERROR [main] my-category - An exception occured java.io.IOException: Exception invoking http://example.com/
	at ExceptionTest.main(ExceptionTest.java:11)
Caused by: java.net.SocketTimeoutException: Read timed out
	... 1 more
Comment 1 Cyrille Le Clerc 2010-03-12 17:51:17 UTC
Created attachment 25121 [details]
proposed implementation of the enhancement

Patch description : 
* ThrowableInformationPatternConverter : update 'format' method to support %throwable{compact}
* EnhancedPatternLayout : javadoc
Comment 2 Curt Arnold 2010-03-19 03:59:14 UTC
Bug 45721 introduced configurable ThrowableRenderer's and may be a more general solution to the issue instead of attempting to do it at layout time.   The throwable in the ThrowableInformation is not serialized which comes into play if the converter was used on a logging event that had been deserialized by a receiver in Chainsaw.  The SocketAppender and similar classes force a call to getThrowableStringRep() which results in the string representation being generated before the instance is serialized.  When it deserialized, the ThrowableInformation has the string representation, but not the Throwable.

From looking at the code, it would seem that %throwable{compact} would in that case result in less output than %throwable{short} where normally it is the other way around.

With the Chainsaw serialization issue, I'd like to avoid introducing anything into ThrowableInfoPatternConverter that depends on the presence of the throwable.  Also, I'd like to avoid anything that attempts to parse a stack trace to find causes, etc.

If you'd always like "compact" rendering in the current SVN HEAD, you can specify an alternative ThrowableRenderer either in configuration or programmatically.  I think it is cleaner doing this at that phase, but it requires writing a ThrowableRenderer and not just  configuration.  If we had a CompactThrowableRenderer in either extras.jar or log4j.jar, then it would be back to just a configuration issue.

If you'd like different renderings on different appenders, then we are back at adding some enhancement to %throwable{}, but I'd be more inclined to support %throwable{n} to do the first n lines or %throwable{regexp} to output only those lines that match a regular expression.
Comment 3 Cyrille Le Clerc 2010-03-22 15:13:03 UTC
Would the log4j project be interested in a contribution to limit the number of stacktrace lines emitted in the logs ?

If so, I would be very happy to help.
Comment 4 Curt Arnold 2010-03-23 13:08:20 UTC
I thought about it.  The existing options could easily be represented as an integer number of lines to emit.
Comment 5 Curt Arnold 2010-03-23 14:18:27 UTC
I also thought that negative values could be used to indicate the number of lines from the bottom to truncate.
Comment 6 Curt Arnold 2010-03-28 03:35:52 UTC
Committed support for %throwable{n} in rev 928324.  A positive n will print up to n lines of stack trace, a negative n will drop the last n lines from the trace and 0 will suppress the stack trace.
Comment 7 Julien Nicoulaud 2010-11-12 09:02:39 UTC
Hi, here is an implementation of this as a custom ThrowableRenderer:
https://github.com/nicoulaj/log4j-extras/blob/trunk/src/main/java/org/apache/log4j/spi/CompactThrowableRenderer.java
Comment 8 Cyrille Le Clerc 2010-11-12 09:30:21 UTC
Hello Julien,

This CompactThrowableRenderer.java seems to be fragile to infinite hierarchies of throwables (e.g. A.cause=B, B.cause=C and C.cause=A): it would cause a StackOverFlowError.

The "getThrowableList(Throwable throwable)" method I used in my proposed patch prevents it. Commons-lang's ExceptionUtils.getThrowableList(Throwable) is a more sophisticated approach.

Cyrille
Comment 9 Julien Nicoulaud 2010-11-12 10:47:54 UTC
You are right, thank you ! Besides, I must say my implementation suits my need but is not very efficient and probably easily breakable. Just posting it in case it could be useful to someone.