web-dev-qa-db-ja.com

バッファリングされたlog4jFileAppenderをどのようにフラッシュしますか?

Log4jで、BufferedIO = trueおよびBufferSize = xxxプロパティを指定してFileAppenderを使用する場合(つまり、バッファリングが有効になっている場合)、通常のシャットダウン手順中にログをフラッシュできるようにしたい。これを行う方法についてのアイデアはありますか?

18
Amos
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);
    }
}
6
Niv

私自身の質問になんとか答えました:-)

LogManagerをシャットダウンする場合:

LogManager.shutdown();

バッファリングされたすべてのログがフラッシュされます。

39
Amos
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();
            }
        }
    }
}
5
Andrey Kurilov

おそらく、WriterAppender#shouldFlush( LoggingEvent )をオーバーライドして、log4j.flush.nowなどの特別なロギングカテゴリに対してtrueを返すようにしてから、次のように呼び出します。

LoggerFactory.getLogger("log4j.flush.now").info("Flush")

http://logging.Apache.org/log4j/1.2/apidocs/org/Apache/log4j/WriterAppender.html#shouldFlush%28org.Apache.log4j.spi.LoggingEvent%29

1
Ondra Žižka

「AndreyKurilov」のコード例、または少なくとも同様の使用に関する私の経験を共有します。

私が実際に達成したかったのは、手動フラッシュを使用して非同期ログエントリを実装することでした(immediateFlush = false) bufferSizeに達する前に、アイドル状態のバッファの内容が確実にフラッシュされるようにします。

初期のパフォーマンス結果は、実際にはAsyncAppenderで達成された結果と同等でした。したがって、これは良い代替手段だと思います。

AsyncAppenderは別のスレッド(およびdisruptor jarへの追加の依存関係)を使用しているため、パフォーマンスは向上しますが、CPUとディスクのフラッシュがさらに多くなります(負荷が高い場合でも)フラッシュはバッチで行われます)。

したがって、ディスクIO操作とCPU負荷を節約したいが、ある時点でバッファーが非同期にフラッシュされるようにしたい場合は、それが方法です。

試してください:

LogFactory.releaseAll();
0
rsp

これを修正するアペンダーを作成しました。 GitHub を参照するか、Mavenでname.wramner.log4j:FlushAppenderを使用してください。重大度の高いイベントでフラッシュするように構成でき、「シャットダウン」などの特定のメッセージを受信したときにアペンダーのバッファーを解除できます。構成例については、単体テストを確認してください。もちろん無料です。

0
ewramner