Захват stdout в log4j / log4net



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



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



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

527   5  

5 ответов:

Одним из решений является подкласс 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();
    }
  }

}

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

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

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

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

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

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

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

Если это вообще возможно, запустите код, который вызывает библиотечные функции в отдельном пространстве процесса; затем вы можете написать поток, который считывает 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
    }
  }
}

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

Comments

    Ничего не найдено.