Log4Net RollingFileAppender没有使用低容量日志刷新IO缓冲区

时间:2013-02-19 17:29:36

标签: logging io buffer log4net flush

我正在考虑same issue as HENRI COOK did。据我们从简短描述中可以看出,它被报告为bug on Apache Jira

我的问题实质上是只在应用程序关闭时记录事件(甚至在事件发生后几周)。当记录量非常低时会发生这种情况。我在Windows Server 2008 R2上看到了这一点。这可以防止我们捕获并对生产错误做出反应。

现在appender不是缓冲的。默认情况下,每次附加消息时,它还会在基础流上调用Flush()。

我的问题是为什么不冲洗?除了programatically flushing all appenders之外还有什么补救措施吗?你会考虑pulsing appender一个可行的解决方法吗?

appender配置:

<appender name="RollingErrorFileAppender" type="log4net.Appender.RollingFileAppender">
  <param name="File" value="D:\LogFiles\zzzz\xxxxxx__ERROR" />
  <param name="AppendToFile" value="true" />
  <param name="DatePattern" value="_yyyyMMddHH&quot;.log&quot;" />
  <param name="RollingStyle" value="Date" />
  <param name="StaticLogFileName" value="false" />
  <filter type="log4net.Filter.LevelRangeFilter">
    <param name="LevelMin" value="ERROR" />
    <param name="LevelMax" value="FATAL" />
  </filter>
  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%utcdate{yyyy-MM-dd HH:mm:ss.fff},[%thread],%level,%logger,%m%n"/>
  </layout>
</appender>

更新2013-06-19

我无法使用任何代码重现该行为。无论我尝试多么糟糕,数据总是立即写入磁盘。但是,进行了一项重要的观察:如果对文件的第一次写入大于1KiB,则修改时间永远不会随后写入而更新。只有在关闭时关闭文件时才会更新它。另一方面,如果第一次写入是短的一行,则任何后续写入都将更新修改时间。这种行为在log4net和手动IO操作之间,在32位WinXP和64位W2k8R2之间,在.NET 2.0,3.5和.NET 4.0之间是一致的。这仍然没有解决问题,但至少我现在可以理解奇怪的修改时间模式。

谢谢,Rob

1 个答案:

答案 0 :(得分:29)

由于您只关心错误级别或更糟的日志事件,并且幸运的是流量很少,我建议您将appender配置为立即刷新。

<param name="ImmediateFlush" value="true" />

这使您无需在每个日志事件上以编程方式刷新appender(无论如何它都无法正常工作)。现在,如果你希望打开你的appender到更多的日志级别,那么当然立即刷新所有事件可能会有更大的性能问题。

修改

我添加了配置文件和一个用于测试的简单主程序。使用以下内容,我确实看到立即刷新日志事件。关于您的评论,我还可以从xml中删除ImmediateFlush行,并查看默认的true值是否适用于刷新。我在示例中保留了这一行,以明确说明所需的行为。

基本主要编程:

class Program
{
    static void Main(string[] args)
    {
        ILog log = LogManager.GetLogger(typeof(Program));
        XmlConfigurator.Configure(new FileInfo(@"C:\temp\logTest.config"));

        string msg;
        while ((msg = Console.ReadLine()) != "Done")
        {
            log.Error(msg);
        }

        LogManager.Shutdown();
    }
}
主程序引用的

logTest.config:

<log4net>
    <appender name="RollingErrorFileAppender" type="log4net.Appender.RollingFileAppender">
        <param name="File" value="C:\temp\log" />
        <param name="AppendToFile" value="true" />
        <param name="DatePattern" value="_yyyyMMddHH&quot;.log&quot;" />
        <param name="RollingStyle" value="Date" />
        <param name="StaticLogFileName" value="false" />
        <param name="ImmediateFlush" value="true" />
        <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="ERROR" />
            <param name="LevelMax" value="FATAL" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%utcdate{yyyy-MM-dd HH:mm:ss.fff},[%thread],%level,%logger,%m%n"/>
        </layout>
    </appender>
    <root>
        <level value="INFO" />
        <appender-ref ref="RollingErrorFileAppender" />
    </root>
</log4net>