Log4jで、BufferedIO = trueおよびBufferSize = xxxプロパティを指定してFileAppenderを使用する場合(つまり、バッファリングが有効になっている場合)、通常のシャットダウン手順中にログをフラッシュできるようにしたい。これを行う方法についてのアイデアはありますか?
public static void flushAllLogs()
{
try
{
Set<FileAppender> flushedFileAppenders = new HashSet<FileAppender>();
Enumeration currentLoggers = LogManager.getLoggerRepository().getCurrentLoggers();
while(currentLoggers.hasMoreElements())
{
Object nextLogger = currentLoggers.nextElement();
if(nextLogger instanceof Logger)
{
Logger currentLogger = (Logger) nextLogger;
Enumeration allAppenders = currentLogger.getAllAppenders();
while(allAppenders.hasMoreElements())
{
Object nextElement = allAppenders.nextElement();
if(nextElement instanceof FileAppender)
{
FileAppender fileAppender = (FileAppender) nextElement;
if(!flushedFileAppenders.contains(fileAppender) && !fileAppender.getImmediateFlush())
{
flushedFileAppenders.add(fileAppender);
//log.info("Appender "+fileAppender.getName()+" is not doing immediateFlush ");
fileAppender.setImmediateFlush(true);
currentLogger.info("FLUSH");
fileAppender.setImmediateFlush(false);
}
else
{
//log.info("fileAppender"+fileAppender.getName()+" is doing immediateFlush");
}
}
}
}
}
}
catch(RuntimeException e)
{
log.error("Failed flushing logs",e);
}
}
私自身の質問になんとか答えました:-)
LogManagerをシャットダウンする場合:
LogManager.shutdown();
バッファリングされたすべてのログがフラッシュされます。
public static void flushAll() {
final LoggerContext logCtx = ((LoggerContext) LogManager.getContext());
for(final org.Apache.logging.log4j.core.Logger logger : logCtx.getLoggers()) {
for(final Appender appender : logger.getAppenders().values()) {
if(appender instanceof AbstractOutputStreamAppender) {
((AbstractOutputStreamAppender) appender).getManager().flush();
}
}
}
}
おそらく、WriterAppender#shouldFlush( LoggingEvent )
をオーバーライドして、log4j.flush.now
などの特別なロギングカテゴリに対してtrue
を返すようにしてから、次のように呼び出します。
LoggerFactory.getLogger("log4j.flush.now").info("Flush")
「AndreyKurilov」のコード例、または少なくとも同様の使用に関する私の経験を共有します。
私が実際に達成したかったのは、手動フラッシュを使用して非同期ログエントリを実装することでした(immediateFlush = false)
bufferSizeに達する前に、アイドル状態のバッファの内容が確実にフラッシュされるようにします。
初期のパフォーマンス結果は、実際にはAsyncAppender
で達成された結果と同等でした。したがって、これは良い代替手段だと思います。
AsyncAppender
は別のスレッド(およびdisruptor
jarへの追加の依存関係)を使用しているため、パフォーマンスは向上しますが、CPUとディスクのフラッシュがさらに多くなります(負荷が高い場合でも)フラッシュはバッチで行われます)。
したがって、ディスクIO操作とCPU負荷を節約したいが、ある時点でバッファーが非同期にフラッシュされるようにしたい場合は、それが方法です。
試してください:
LogFactory.releaseAll();
これを修正するアペンダーを作成しました。 GitHub を参照するか、Mavenでname.wramner.log4j:FlushAppenderを使用してください。重大度の高いイベントでフラッシュするように構成でき、「シャットダウン」などの特定のメッセージを受信したときにアペンダーのバッファーを解除できます。構成例については、単体テストを確認してください。もちろん無料です。