22

We use Log4j (and Commons Logging) to log our error messages. Now we want to set up an additional log appender that outputs fatal errors to syslog, but without the exceptionally long Java stacktraces (those will still be available in the full log file).

How would one configure this (using log4j.xml)? Is there a filter available to ignore the stack traces?

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Another use case where one could want this is when you are running a suite of tests that contain negative tests that are expected to throw exceptions that we always want to log in production. We don't want our test logs to be crowded with exceptions that are par for the course – Sridhar Sarnobat Aug 06 '15 at 22:14

8 Answers8

16

Edit after reading some more of the source:

You still need to subclass PatternLayout, but the method you want to override is ignoresThrowable(): it should return false, which will prevent the appender from writing the Throwable (it assumes that the layout has done so already).

No way to specify this in the configuration: PatternLayout has a hardcoded "return true".

kdgregory
  • 38,754
  • 10
  • 77
  • 102
  • 2
    Okay, that works, thanks. Too bad that this is not a configuration option with log4j. I wonder why this is handled so much different than the other options available to PatternLayout. Seems like a natural formatting option to me... – Thilo Dec 08 '08 at 05:11
  • 1
    It is a little strange: when I first looked at the code, I figured that the layouts handled everything, then discovered that it was actually the appender. And that the appenders are slightly different. If you're going to do this, you could add a setter for the ignoreThroable() and submit a patch. – kdgregory Dec 08 '08 at 12:22
12

Here's the actual code I use:

import org.apache.log4j.PatternLayout;

public class NoStackTracePatterLayout extends PatternLayout {

 @Override
 public boolean ignoresThrowable(){
  return false;
 }
}
Totach
  • 1,861
  • 2
  • 16
  • 20
  • 1
    Thanks. Again, having to write a subclass just for this is not nice. Should have been a configuration option on PatternLayout. – Thilo Nov 25 '09 at 00:46
10

If you use log4j > 1.2.16, you can use the EnhancedPatternLayout layout.

Example (with a log4j.properties file), define it as the layout of your appender, and then add %throwable{0} in the conversion pattern:

log4j.appender.XXX.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.XXX.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n%throwable{0}
boumbh
  • 2,010
  • 1
  • 19
  • 21
  • 1
    This is exactly what I need, but with the slf4j wrapper `slf4j-log4j12` version `1.7.12` (under the hood using `log4j` version `1.2.17`) it's still showing the full JSONException :( Does anyone have any idea why? – Sridhar Sarnobat Aug 06 '15 at 22:23
6

In 1.2.16 you can use EnhancedPatternLayout

Javier
  • 376
  • 2
  • 12
4

As of Log4j2, you can just add "%ex{0}" to your log pattern (assuming you're using PatternLayout)

https://logging.apache.org/log4j/log4j-2.1/manual/layouts.html

Dasmowenator
  • 5,505
  • 5
  • 36
  • 50
2

The "nopex" or "nopexception" conversion word in logback-classic (log4j's successor) disables printing stack traces. The "nopex" conversion word is documented along with the rest of conversion words. You need to scroll down a little.

If you need further information on this topic, please contact the logback-user mailing list.

Ceki
  • 26,753
  • 7
  • 62
  • 71
1

You may need to write a custom layout to do it (which isn't that bad to do; you could subclass PatternLayout).

davetron5000
  • 24,123
  • 11
  • 70
  • 98
0

If you can change the source code, then another option is available for consideration.

In my applications, I always and only log FATAL messages from my applications entry point (e.g., "main()"), since I only know that they are fatal if I am about to exit the application because of them.

Therefore, in this one place (or handful if you have multiple application entry points), instantiate a Log4j Logger with a special class or MDC of "syslog" or similar. Upon catching a soon-to-be-FATAL error, log it in the usual way (for your other log files and such), but also invoke the fatal() method on this new "syslog" Logger with only the precise message that you want (such as only the exception class and message but without the stack trace). Then configure Log4j to direct only this "syslog" class or MDC to a newly-configured Appender that targets the SysLog.

Ta-dum!

Rob Williams
  • 7,919
  • 1
  • 35
  • 42