Redirect System.out.println to log

前端 未结 5 1314
孤城傲影
孤城傲影 2021-01-11 15:51

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

相关标签:
5条回答
  • 2021-01-11 16:39

    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;
      }
    
    }
    
    0 讨论(0)
  • 2021-01-11 16:40
    public class RecursiveLogging {
    public static void main(String[] args) {
        System.setOut(new PrintStream(new CustomOutputStream()));
    
        TestMyException.testPrint();
    }
    
    }
    
    class CustomOutputStream extends OutputStream {
    private Logger logger = Logger.getLogger(this.getClass());
    
    @Override
    public final void write(int b) throws IOException {
        // the correct way of doing this would be using a buffer
        // to store characters until a newline is encountered,
        // this implementation is for illustration only
        logger.info((char) b);
    }
    
    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        byte[] pb = new byte[len];
        for (int i = 0 ; i < len ; i++) {
            pb[i] = (b[off + i]);
        }
        String str = new String(pb);
        logger.info(str);
    }
    }
    
    0 讨论(0)
  • 2021-01-11 16:43

    I think you can use System.setOut(PrintStream) to set your output to a file output stream. Then you can put this line in your BeforeClass method. I like to use a BaseTest class and put this line of code in the beforeclass method of that class. Then make all test cases extend this cclass.

    0 讨论(0)
  • 2021-01-11 16:43

    Use shell redirection. Figure out the "java" invocation for your project, if you're on most vaguely UNIX-like systems, ps aux | grep java will help.

    Then just run this command with > /path/to/logfile. Example:

    java -jar myjar.jar -cp path/to/lib.jar:path/to/otherlib.jar com.bigcorp.myproject.Main > /var/log/myproject.log
    
    0 讨论(0)
  • 2021-01-11 16:46

    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

    0 讨论(0)
提交回复
热议问题