39

I want to log only the first few lines of Exceptions in my program. I know, I can do something like this to print only the first 5 lines of a stacktrace:

Throwable e = ...;
StackTraceElement[] stack = e.getStackTrace();
int maxLines = (stack.length > 4) ? 5 : stack.length;
for (int n = 0; n < maxLines; n++) {
    System.err.println(stack[n].toString());
}

But I would rather use log4j (or slf4j over log4j to be more precise) for logging. Is there a way to tell log4j that it should only print the first 5 lines of a stacktrace?

rompetroll
  • 4,781
  • 2
  • 37
  • 50

5 Answers5

40

You can use a EnhancedPatternLayout in log4j to format your stacktraces.

See http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html, specifically the section about the "throwable" pattern in the pattern table.

Note that support for the %throwable{n} support is rather new and requires at least log4j 1.2.16 (which is the latest at time of writing)

For tracking purposes, this is the ticket that dealt with its implementation: https://issues.apache.org/bugzilla/show_bug.cgi?id=48902

Hendrik
  • 1,981
  • 16
  • 11
  • 10
    Note that in case of nested Exceptions, this will mercylessly cut off the nested messages, so for many real-world use-cases, this is useless. What developers would need would be to limit the number of stack elements per exception in the trace. – tkruse Nov 07 '16 at 07:29
  • Is this `%throwable{...}` pattern available with slf4j, too, if `slf4j-log4j12` or `log4j-slf4j-impl` is used? – Gerold Broser Aug 30 '18 at 12:36
  • 1
    Yes it works, need to add the log4j-over-slf4j bridge dependency. @GeroldBroser – galgal Nov 11 '21 at 23:21
  • is there a solution for JsonTemplateLayout? – BabyishTank Jun 20 '22 at 03:41
12

Yup... EnhancedPatternLayout provides this functionality. (Since Log4J-1.2.16, was in extra companions before).

For a log4j config of

<appender name="Console" class="org.apache.log4j.ConsoleAppender">
    <param name="Threshold" value="debug"/>
    <layout class="org.apache.log4j.EnhancedPatternLayout">
        <param name="ConversionPattern" value="%d %-5p [%t] %c.%M - %m%n %throwable{short}"/>
    </layout>
</appender>

and for a piece of Java code like

throw new Exception(new Exception("Inner Exception"));

You get the following in the log file...

java.lang.Exception: java.lang.Exception: Inner Exception

If we remove the '%throwable{short}' from our log4j config file we would get the full stack trace

YMomb
  • 2,366
  • 1
  • 27
  • 36
prav
  • 166
  • 5
4

In log4j2.xml simply add %throwable{short} at end. No need to add param name.

<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n %throwable{short} %n"/>

ref : https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout

vsingh
  • 6,365
  • 3
  • 53
  • 57
1

I don't know of such an option. But you can extend your current appender (for example RollingFileAppender) and provide an append / doAppend / subAppend method (depending on which class you are extending) to handle this.

The throwable information is contained in LoggingEvent.throwableInformation

That said, I'm not sure you should do this - you can lose important information that way.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
1

Yes, it is part of log4j since log4j 1.2.16

Here is the original proposal in the Apache issue tracker that describes in detail how each of the applications of the %throwable pattern looks like: https://issues.apache.org/bugzilla/show_bug.cgi?id=48902#c0

Kai Sternad
  • 22,214
  • 7
  • 47
  • 42