19

我正在思考与 HENRI COOK 相同的问题。据我们从简短描述中可以看出,它已被报告为Apache Jira 上的一个错误。

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

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

我的问题是为什么它不冲洗?除了以编程方式刷新所有附加程序之外,还有什么补救措施吗?您是否认为脉冲附加程序是一种可行的解决方法?

附加程序配置:

<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 之间是一致的。这仍然不能解决问题,但至少我现在可以理解奇怪的修改时间模式。

谢谢,罗伯

4

1 回答 1

31

Since you are only concerned with error level or worse log events, and that traffic is fortunately infrequent, I would suggest configuring your appender to immediately flush.

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

This saves you from having to programmatically flush your appender on every log event (which wasn't working anyway from the sound of it). Now, if you wish to open your appender up to more log levels, then of course immediately flushing all events could have greater performance concerns.

EDIT

I added the config file and a simple main program I used for testing. Using the following, I do see log events immediately flushed. In regard to your comment, I can also strip out the ImmediateFlush line from the xml and see the default true value work for flushing. I kept the line in my example for purposes of explicitly stating the desired behavior.

Basic main prog:

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 referenced by main prog:

<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>
于 2013-02-27T18:09:04.987 回答