在log4j中,当使用具有BufferedIO = true和BufferSize = xxx属性的FileAppender(即启用了缓冲)时,我希望能够在正常关闭过程中刷新日志。关于如何做到这一点的任何想法?
答案 0 :(得分:37)
管理回答我自己的问题: - )
关闭LogManager时:
LogManager.shutdown();
所有缓冲的日志都被刷新。
答案 1 :(得分:6)
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 :(得分:3)
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();
}
}
}
}
答案 3 :(得分:1)
也许您可以覆盖WriterAppender#shouldFlush( LoggingEvent )
,因此它会返回true
作为特殊记录类别,例如log4j.flush.now
,然后您调用:
LoggerFactory.getLogger("log4j.flush.now").info("Flush")
答案 4 :(得分:1)
分享我使用“ Andrey Kurilov”的代码示例的经验,或者至少是相似的。
我真正想要实现的是使用手动刷新AsyncAppender
实现一个异步日志条目,以确保在达到bufferSize之前刷新空闲缓冲区的内容。
最初的性能结果实际上可以与AsyncAppender
所获得的结果相比较-因此,我认为这是一个很好的选择。
disruptor
使用一个单独的线程(以及对ConfigurationSet
jar的附加依赖),这使其性能更高,但是却要花费更多的CPU和甚至更多的磁盘刷新(无论高批量刷新)。
因此,如果您想节省磁盘IO操作和CPU负载,但仍要确保在某些时候异步刷新缓冲区,那是必须的方法。
答案 5 :(得分:0)
尝试:
LogFactory.releaseAll();
答案 6 :(得分:0)
我编写了一个修复此问题的appender,请参阅GitHub或使用name.wramner.log4j:Maven中的FlushAppender。它可以配置为刷新具有高严重性的事件,并且当收到特定消息时,它可以使appender无缓冲,例如“Shutting down”。检查单元测试以获取配置示例。当然是免费的。