Захват stdout в log4j / log4net
У меня есть библиотека, которая пишет в stdout на Java. Я хотел бы записать этот вывод в журнал с помощью log4j. (я не писал эту библиотеку, поэтому у меня нет контроля над кодом внутри библиотеки).
Есть ли простой способ сделать это? Это Система.наметить правильный подход? Что я передаю системе?в путь?
Кроме того, как бы вы это сделали в .NET/C#?
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