Захватить стандартный вывод в log4j / log4net - PullRequest
4 голосов
/ 23 февраля 2009

У меня есть библиотека, которая пишет в стандартный вывод на Java. Я хотел бы захватить этот вывод в журнале, используя log4j. (Я не писал эту библиотеку, поэтому не могу контролировать код внутри библиотеки).

Есть ли простой способ сделать это? Является ли System.setOut правильным подходом? Что я передаю в System.setOut?

Кроме того, как бы вы сделали это в .NET / C #?

Ответы [ 5 ]

3 голосов
/ 23 февраля 2009

Одним из решений является подкласс OutputStream. Вам нужно только реализовать write( int b ). Затем создайте PrintStream с вашим OutputStream в конструкторе.

Это может выглядеть так:

public class L4JOS extends OutputStream {
  logger = Logger.getLogger( "std.out" );
  private int lineEnd = (int)'\n';
  private ByteArrayOutputStream baos = new ByteArrayOutputStream();

  public void write( int b ) throws IOException {
    baos.write( b );
    if ( b == lineEnd ) {
      logger.info( baos.toString() );
      baos.reset();
    }
  }

}

Если он многопоточный, значит, у вас больше работы. И убедитесь, что appender не заходит на System.out.

2 голосов
/ 23 февраля 2009

Вы можете реализовать свой собственный OutputStream, который просто регистрирует все, что выходит, в log4j, а затем пользователь System.setOut к экземпляру этого OutputStream.

Имейте в виду, что это может привести к бесконечному циклу в случае, когда log4j выводит материал на стандартный выход.

Так что вы, вероятно, должны выполнить некоторую фильтрацию, чтобы определить, что передать в log4j, а что передать в исходный поток stdout

0 голосов
/ 27 мая 2009

Я бы не хотел использовать setOut (), потому что это глобальная переменная. Вы столкнетесь с «действием на расстоянии»: вы хотите перехватить стандартный вывод только для этой библиотеки, но не растоптать что-либо еще, что может потребоваться для использования стандартного вывода.

Если это вообще возможно, запустите код, который вызывает библиотечные функции, в отдельном пространстве процесса; затем вы можете написать поток, который читает stdout из этого процесса и отправляет его регистратору.

new Thread() {
  public void run() {
    ProcessBuilder pb = new ProcessBuilder(command);
    Process p = pb.start();
    BufferedReader in = new BufferedReader(p.getInputStream());
    String line;
    while ((line = in.readLine()) != null) {
      log.info(line);
      // or you could parse line and try to dynamically pick a log level
    }
  }
}

Вам понадобится хороший способ вернуть выходные данные из вызываемого процесса вызывающей стороне, но если это так же просто, как вернуть значение, тогда должно быть легко вернуть его в качестве последней строки вашего стандартного вывода или строка со специальным сигнальным кодом или что-то в этом роде.

0 голосов
/ 23 февраля 2009

Вы должны иметь возможность подключить приложение GUI бензопилу к списку на стандартный вывод и получить необходимые результаты.

0 голосов
/ 23 февраля 2009

Почему вы хотите это сделать. Вы не должны писать в sysout напрямую, вы должны написать в log4j и настроить консольный appender, если вы хотите выводить в sysout.

...