Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect System.out.println to log

Tags:

java

logging

In my project test suite there is big usage of

System.out.println 

I'm trying to redirect these output to log file (through configuration or from single point without refactoring whole project ) so that can be disabled when necessary to improve performance. I'm using log4j for logging. Does any one know is this possible ? if so how to do it ? Thanks in advance.

like image 796
Viraj Avatar asked Mar 14 '13 07:03

Viraj


People also ask

How do you redirect the system out standard output stream to a file?

Instantiate a PrintStream class by passing the above created File object as a parameter. Invoke the out() method of the System class, pass the PrintStream object to it. Finally, print data using the println() method, and it will be redirected to the file represented by the File object created in the first step.

Why do we use Logger instead of system out Println?

If you are running a Java program in Linux or any UNIX-based system, Log4j or SLF4j or any other logging framework offers a lot more features, flexibility, and improvement on message quality, which is not possible using the System. out. println() statement.


2 Answers

Given that it's better replace the System.out.println(), sometimes we have no choice. Anyway I've made a little utility for that:

SystemOutToSlf4j.enableForClass(MyClass.class)

Then all the println originated from MyClass will be redirected to the logger. See this post for more details...

public class SystemOutToSlf4j extends PrintStream {

  private static final PrintStream originalSystemOut = System.out;
  private static SystemOutToSlf4j systemOutToLogger;

  /**
   * Enable forwarding System.out.println calls to the logger if the stacktrace contains the class parameter
   * @param clazz
   */
  public static void enableForClass(Class clazz) {
    systemOutToLogger = new SystemOutToSlf4j(originalSystemOut, clazz.getName());
    System.setOut(systemOutToLogger);
  }


  /**
   * Enable forwarding System.out.println calls to the logger if the stacktrace contains the package parameter
   * @param packageToLog
   */
  public static void enableForPackage(String packageToLog) {
    systemOutToLogger = new SystemOutToSlf4j(originalSystemOut, packageToLog);
    System.setOut(systemOutToLogger);
  }

  /**
   * Disable forwarding to the logger resetting the standard output to the console
   */
  public static void disable() {
    System.setOut(originalSystemOut);
    systemOutToLogger = null;
  }

  private String packageOrClassToLog;

  private SystemOutToSlf4j(PrintStream original, String packageOrClassToLog) {
    super(original);
    this.packageOrClassToLog = packageOrClassToLog;
  }

  @Override
  public void println(String line) {
    StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    StackTraceElement caller = findCallerToLog(stack);
    if (caller == null) {
      super.println(line);
      return;
    }

    org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(caller.getClass());
    log.info(line);
  }

  public StackTraceElement findCallerToLog(StackTraceElement[] stack) {
    for (StackTraceElement element : stack) {
      if (element.getClassName().startsWith(packageOrClassToLog))
        return element;
    }

    return null;
  }

}
like image 110
Fabio Bonfante Avatar answered Oct 10 '22 07:10

Fabio Bonfante


My suggestion would be to refactor if possible. For a possible solution, check these similar questions

log4j redirect stdout to DailyRollingFileAppender

Redirect System.out.println to Log4J, while keeping class name information

like image 38
rajesh Avatar answered Oct 10 '22 08:10

rajesh