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

17,667

Solution 1

The only way I can think of would be to write your own PrintStream implementation which created a stack trace when the println method was called, in order to work out the class name. It would be pretty horrible, but it should work... proof of concept sample code:

import java.io.*;

class TracingPrintStream extends PrintStream {
  public TracingPrintStream(PrintStream original) {
    super(original);
  }

  // You'd want to override other methods too, of course.
  @Override
  public void println(String line) {
    StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    // Element 0 is getStackTrace
    // Element 1 is println
    // Element 2 is the caller
    StackTraceElement caller = stack[2];
    super.println(caller.getClassName() + ": " + line);
  }
}

public class Test {
  public static void main(String[] args) throws Exception {
    System.setOut(new TracingPrintStream(System.out));
    System.out.println("Sample line");
  }
}

(In your code you would make it log to log4j instead of course... or possibly as well.)

Solution 2

If you can modify the source code, then have a look at the Eclipse Plugin Log4E. It provides a function to convert System.out.println into logger statements (and many other cool stuff dealing with logging).

Share:
17,667
David Parks
Author by

David Parks

Merge Keep

Updated on June 04, 2022

Comments

  • David Parks
    David Parks almost 2 years

    I have some libraries that are calling System.out.println on me, I'd like to redirect them through log4j or commons logging. But in particular I'd like to keep the fully-qualified-classname so I know what component generated the logs.

    Is there a nice, orderly way to accomplish this?


    UPDATE: After accomplishing this I posted the code here:
    http://www.bukisa.com/articles/487009_java-how-to-redirect-stderr-and-stdout-to-commons-logging-with-the-calling-class

  • David Parks
    David Parks about 13 years
    Nope, they're 3rd party libraries that are doing it. It's not worth changing their code, and requesting them to do it may take years.
  • Liviu T.
    Liviu T. about 13 years
    The only thing that comes to mind when you can't modify source code is byte code manipulation but you need to intercept the class loading process and create a new class file with the System.out replaced with Logger statements, but that sounds way to intensive
  • Liviu T.
    Liviu T. about 13 years
    scratch that, Jon Skeet came to the rescue :)
  • toolforger
    toolforger over 4 years
    @DavidParks a particularly annoying case of 3rd-party code is the JDK's own debug output in the HTTPS subsystem, which uses System.stdout, including the write() functions that PrintStream wrappers typically neglect to redirect.