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
Created attachment 25121 [details] proposed implementation of the enhancement Patch description : * ThrowableInformationPatternConverter : update 'format' method to support %throwable{compact} * EnhancedPatternLayout : javadoc
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.
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.
I thought about it. The existing options could easily be represented as an integer number of lines to emit.
I also thought that negative values could be used to indicate the number of lines from the bottom to truncate.
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.
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
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
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.