私のプロジェクトのテストスイートでは、
System.out.println
これらの出力をログ ファイルにリダイレクトしようとしています (構成を通じて、またはプロジェクト全体をリファクタリングせずに単一のポイントから) パフォーマンスを向上させるために必要なときに無効にできるようにします。ロギングには log4j を使用しています。これが可能であることを知っている人はいますか?もしそうなら、それを行う方法は?前もって感謝します。
を置き換えたほうがよいことを考えると、System.out.println()
選択の余地がない場合もあります。とにかく、私はそのための小さなユーティリティを作成しました:
SystemOutToSlf4j.enableForClass(MyClass.class)
次に、MyClass から発信されたすべての println がロガーにリダイレクトされます。 詳細については、この投稿を参照してください...
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;
}
}
System.setOut(PrintStream)
出力をファイル出力ストリームに設定するために使用できると思います。次に、この行を BeforeClass メソッドに入れることができます。BaseTest クラスを使用して、このコード行をそのクラスの beforeclass メソッドに入れるのが好きです。次に、すべてのテスト ケースがこの cclass を拡張するようにします。
私の提案は、可能であればリファクタリングすることです。可能な解決策については、これらの同様の質問を確認してください
シェル リダイレクトを使用します。ほとんどのあいまいな UNIX ライクなシステムを使用している場合は、プロジェクトの "java" 呼び出しを把握してください。grep java が役立ちます。
次に、このコマンドを > /path/to/logfile で実行します。例:
java -jar myjar.jar -cp path/to/lib.jar:path/to/otherlib.jar com.bigcorp.myproject.Main > /var/log/myproject.log
私のソリューションは非常にシンプルで、すべてを過負荷にすることなく、すべての PrintStream 機能をサポートしています。新しい行ごとに PrintStream メソッドによって呼び出されるため、flush() のみをオーバーロードします。
public class ConsoleToLogger
{
private Logger log;
private PrintStream originalStream;
private Level logLevel;
private ByteArrayBufferOutStream buffer;
private PrintStream bufferPrintStream;
ConsoleToLogger(PrintStream realPrintStream, Level pLogLevel)
{
buffer = new ByteArrayBufferOutStream();
bufferPrintStream = new PrintStream(buffer);
originalStream = realPrintStream;
logLevel = pLogLevel;
log = Logger.getLogger(Level.ERROR.equals(pLogLevel) ? "STDERR" : "STDOUT");
}
public PrintStream getPrintStream()
{
return bufferPrintStream;
}
private class ByteArrayBufferOutStream
extends ByteArrayOutputStream
{
@Override
public void flush()
throws IOException
{
super.flush();
String message = buffer.toString();
originalStream.println(message);
log.log(logLevel, message);
buffer.reset();
}
}
}
// assign to System.out and system.err
System.setOut(new ConsoleToLogger(System.out, Level.INFO).getPrintStream());
System.setErr(new ConsoleToLogger(System.err, Level.ERROR).getPrintStream());