在log4j中,当使用一个FileAppender,并且BufferedIO=true和BufferSize=xxx属性(即启用了缓冲)时,我希望能够在正常的关机过程中刷新日志。
cgh8pdjw1#
关闭日志管理器时:
LogManager.shutdown();
所有缓冲日志都将被刷新。
zzlelutf2#
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); } }
n1bvdmb63#
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(); } } } }
0sgqnhkj4#
也许你可以重写WriterAppender#shouldFlush( LoggingEvent ),这样它会为一个特殊的日志记录类别返回true,比如log4j.flush.now,然后你调用:
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
3pvhb19x5#
分享我的经验与使用“安德烈库里洛夫”的代码示例,或至少相似。我实际上想要实现的是实现一个带有手动刷新(immediateFlush = false)的异步日志条目,以确保在达到bufferSize之前刷新空闲缓冲区的内容。最初的性能结果实际上与AsyncAppender相当,因此我认为它是一个很好的替代品。AsyncAppender使用单独的线程(以及对disruptor jar的额外依赖),这使其性能更高,但代价是更多的CPU和甚至更多的磁盘刷新(无论高负载刷新是在批处理上进行的)。因此,如果您希望保存磁盘IO操作和CPU负载,但仍希望确保缓冲区在某个时间点异步刷新,这是一种可行的方法。
(immediateFlush = false)
AsyncAppender
disruptor
5lhxktic6#
请尝试:
LogFactory.releaseAll();
qacovj5a7#
我已经写了一个附加器来修复这个问题,请参见GitHub或使用Maven中的name.wramner.log4j:FlushAppender。它可以被配置为对严重性高的事件进行刷新,并且当它接收到特定的消息时,可以使附加器不缓冲,例如“正在关闭”。请查看单元测试中的配置示例。当然,它是免费的。
643ylb088#
对我有效的唯一解决办法是等待一段时间:
private void flushAppender(Appender appender) { // this flush seems to be useless ((AbstractOutputStreamAppender<?>) appender).getManager().flush(); try { Thread.sleep(500); // wait for log4j to flush logs } catch (InterruptedException ignore) { } }
8条答案
按热度按时间cgh8pdjw1#
关闭日志管理器时:
所有缓冲日志都将被刷新。
zzlelutf2#
n1bvdmb63#
0sgqnhkj4#
也许你可以重写
WriterAppender#shouldFlush( LoggingEvent )
,这样它会为一个特殊的日志记录类别返回true
,比如log4j.flush.now
,然后你调用:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/WriterAppender.html#shouldFlush%28org.apache.log4j.spi.LoggingEvent%29
3pvhb19x5#
分享我的经验与使用“安德烈库里洛夫”的代码示例,或至少相似。
我实际上想要实现的是实现一个带有手动刷新
(immediateFlush = false)
的异步日志条目,以确保在达到bufferSize之前刷新空闲缓冲区的内容。最初的性能结果实际上与
AsyncAppender
相当,因此我认为它是一个很好的替代品。AsyncAppender
使用单独的线程(以及对disruptor
jar的额外依赖),这使其性能更高,但代价是更多的CPU和甚至更多的磁盘刷新(无论高负载刷新是在批处理上进行的)。因此,如果您希望保存磁盘IO操作和CPU负载,但仍希望确保缓冲区在某个时间点异步刷新,这是一种可行的方法。
5lhxktic6#
请尝试:
qacovj5a7#
我已经写了一个附加器来修复这个问题,请参见GitHub或使用Maven中的name.wramner.log4j:FlushAppender。它可以被配置为对严重性高的事件进行刷新,并且当它接收到特定的消息时,可以使附加器不缓冲,例如“正在关闭”。请查看单元测试中的配置示例。当然,它是免费的。
643ylb088#
对我有效的唯一解决办法是等待一段时间: