代码之家  ›  专栏  ›  技术社区  ›  Amos

如何刷新缓冲的log4j文件附加器?

  •  17
  • Amos  · 技术社区  · 15 年前

    在log4j中,当使用BufferedIO=true和BufferSize=xxx属性的FileAppender时(即启用了缓冲),我希望能够在正常关闭过程中刷新日志。有什么办法吗?

    6 回复  |  直到 15 年前
        1
  •  7
  •   Evan Langlois    15 年前
    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);
        }
    }
    
        2
  •  47
  •   Kalle Richter    4 年前

    关闭LogManager时:

    LogManager.shutdown();
    

    所有缓冲日志都被刷新。

        3
  •  5
  •   Andrey Kurilov    8 年前
    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();
                }
            }
        }
    }
    
        4
  •  1
  •   Ondra Žižka David Lilljegren    14 年前

    WriterAppender#shouldFlush( LoggingEvent ) ,所以它会回来 true 对于一个特殊的日志类别,比如 log4j.flush.now ,然后您拨打:

    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

        5
  •  1
  •   Alex Ciocan Gaurav Varshney    5 年前

    分享我使用“Andrey Kurilov”的代码示例的经验,或者至少是similar。

    我真正想要实现的是实现一个带有手动刷新的异步日志条目 (immediateFlush = false) 为确保在达到缓冲区大小之前刷新空闲缓冲区内容。

    最初的绩效结果实际上与使用 AsyncAppender

    这个 正在使用一个单独的线程(以及对 disruptor jar),这使得它的性能更高,但是需要花费更多的CPU和更多的磁盘刷新(不管高负载刷新是在批处理上进行的)。

    因此,如果您希望节省磁盘IO操作和CPU负载,但仍然希望确保缓冲区在某个时间点异步刷新,那么这就是解决方法。

        6
  •  0
  •   rsp    15 年前

    LogFactory.releaseAll();
    
        7
  •  0
  •   ewramner    10 年前

    我已经写了一个附录来解决这个问题,看到了吗 GitHub 或者在Maven中使用name.wramner.log4j:FlushAppender。它可以配置为在严重性很高的事件上刷新,并且可以在收到特定消息(例如“Shutting down”)时取消对附加器的缓冲。检查单元测试中的配置示例。当然是免费的。