1

I have an application that uses below code to output the stack trace for exceptions a lot, but when I run it on the server it doesn't log anything in log4j files.

Normally I would have used logger.error("msg...", e), but I can't change the code so Im stuck with printStackTrace() methods.

Is there any way to configure log4j to include those in the logs? I understand they go to System.err rather than System.out so can I redirect that somehow using log4j config (i.e. without changing the code)?

Any ideas much appreciated.

try {
...
} catch (Exception e) {
e.printStackTrace();
}
BlackVegetable
  • 12,594
  • 8
  • 50
  • 82
Zyga
  • 2,367
  • 3
  • 22
  • 32

1 Answers1

3

Borrowing from the example provided by Black Vegetable, see if this helps move you in the direction you want to go:

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import org.apache.log4j.Logger;

public class TestSystemErrCapture {

  private static final Logger log = Logger.getLogger(TestSystemErrCapture.class);

  public static void main(String[] args) {
    // First, redirect STDERR
    System.setErr(new PrintStream(new OutputStream() {
      private StringBuilder message = new StringBuilder();
      @Override
      public void write(int b) throws IOException {
        if (b == '\n') {
          log.error(message);
          message.setLength(0);
        } else {
          message.append((char)b);
        }
      }
    }));
    // Now test to make sure output is redirected
    TestThirdPartyClass t3pc = new TestThirdPartyClass();
    t3pc.doIt();
  }

  public static class TestThirdPartyClass {
    public void doIt() {
      try {
        throw new RuntimeException("Evil");
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

}

log4j.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration PUBLIC
  "-//APACHE//DTD LOG4J 1.2//EN"     "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
  <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
  <appender name="Console"
            class="org.apache.log4j.ConsoleAppender">
    <!-- Only allow INFO+ in the Console. Use other logs for DEBUG-
    <param name="Threshold" value="INFO"/>-->
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern"
             value="%d{MM/dd/yyyy HH:mm:ss}: %l%n%-5p - %m%n"/>
    </layout>
  </appender>
  <root>
    <level value="INFO"/>
    <appender-ref ref="Console"/>
  </root>
</log4j:configuration>

The following output is produced (I ran this in Eclipse):

02/11/2014 10:26:53: TestSystemErrCapture$1.write(TestSystemErrCapture.java:18)
ERROR - java.lang.RuntimeException: Evil

02/11/2014 10:26:53: TestSystemErrCapture$1.write(TestSystemErrCapture.java:18)
ERROR -     at     TestSystemErrCapture$TestThirdPartyClass.doIt(TestSystemErrCapture.java:33)

02/11/2014 10:26:53: TestSystemErrCapture$1.write(TestSystemErrCapture.java:18)
ERROR -     at TestSystemErrCapture.main(TestSystemErrCapture.java:27)

The output is a little funky, and maybe not exactly what you want for your application, but I think it should get you started.

HTH --jsp

J Steven Perry
  • 1,711
  • 1
  • 17
  • 28