如何刷新缓冲的log4j FileAppender?
在log4j中,当使用具有BufferedIO = true和BufferSize = xxx属性的FileAppender(即启用了缓冲)时,我希望能够在正常关闭过程中刷新日志。 关于如何做到这一点的任何想法?
public static void flushAllLogs() { try { Set flushedFileAppenders = new HashSet (); 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 )
,所以它会为特殊的日志记录类别返回true
,比如log4j.flush.now
,然后你调用:
LoggerFactory.getLogger("log4j.flush.now").info("Flush")
尝试:
LogFactory.releaseAll();
我写了一个修复此问题的appender,请参阅GitHub或使用name.wramner.log4j:Maven中的FlushAppender。 它可以配置为刷新具有高严重性的事件,并且可以在收到特定消息时使appender无缓冲,例如“Shutting down”。 检查unit testing以获取配置示例。 当然是免费的。