log4j redirect stdout to DailyRollingFileAppender

Viewed 95190

I have a java app that uses log4j.

Config:

log4j.rootLogger=info, file

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=${user.home}/logs/app.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d [%t] %c %p %m%n

So all the log statements are correctly appended to the file, but i am losing stdout and stderr. How do i redirect exception stack traces and sysouts to the daily rolled file ?

10 Answers

If you are using an application server, servlet container or something similar, see kgiannakakis's answer.

For standalone apps see this. You can reassing stdin, stdout and stderr using java.lang.System class. Basically you create a new subclass of PrintStream and set that instance to System.out.

Something along these lines in start of your app (untested).

// PrintStream object that prints stuff to log4j logger
public class Log4jStream extends PrintStream {
      public void write(byte buf[], int off, int len) {
        try {
           // write stuff to Log4J logger
        } catch (Exception e) {
       }
    }
}

// reassign standard output to go to log4j
System.setOut(new Log4jStream());

For those looking for how to do this in log4j2. There is now a component to create these streams for you.

Requires including the log4j-iostreams jar
See: https://logging.apache.org/log4j/2.x/log4j-iostreams/index.html

Example:

PrintStream logger = IoBuilder.forLogger("System.out").setLevel(Level.DEBUG).buildPrintStream();
PrintStream errorLogger = IoBuilder.forLogger("System.err").setLevel(Level.ERROR).buildPrintStream();
System.setOut(logger);
System.setErr(errorLogger);

I presume you're logging stacktraces via e.printStackTrace() ? You can pass an exception object into the Log4j logging methods and those will appear in your log (see Logger.error(Object obj, Throwable t))

Note that you can change System.out and System.err to another PrintStream that redirects to Log4j. That would be a straightforward change and save you converting all your System.out.println() statements.

Standard output and error streams are managed from your container. For example Tomcat uses JULI to log output and error streams.

My recommendation is to leave these as it is. Avoid using System.out.print in your application. See here for stack traces.

Related