间歇性log4net RollingFileAppender锁定文件问题

Ric*_*ett 110 log4net locking rollingfileappender

我们在开发和生产机器上看到一个间歇性问题,我们的日志文件没有被记录.

使用Visual Studio在开发和调试中运行时,我们在VS输出窗口中收到以下log4net错误消息:

log4net:ERROR [RollingFileAppender] Unable to acquire lock on file C:\folder\file.log.
Run Code Online (Sandbox Code Playgroud)

该进程无法访问文件"C:\ folder\file.log",因为它正由另一个进程使用.

log4net:ERROR XmlConfigurator: Failed to find configuration section 'log4net' in the application's .config file.
Check your .config file for the <log4net> and <configSections> elements.
Run Code Online (Sandbox Code Playgroud)

配置部分应如下所示:

<section
  name="log4net"
  type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
Run Code Online (Sandbox Code Playgroud)

我们当前解决此问题的方法是重命名最后一个日志文件.我们当然希望这会失败(由于前面提到的文件锁定),但通常不会.由于aspnet_wp.exe进程的锁定,重命名一次或两次失败.

我们的log4net配置部分如下所示:

<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="C:\folder\file.log"/>
    <appendToFile value="true" />
    <datePattern value="yyyyMMdd" />
    <rollingStyle value="Date" />
    <maximumFileSize value="10MB" />
    <maxSizeRollBackups value="100" />
    <layout type="log4net.Layout.PatternLayout">
      <header value="[Header]&#xA;"/>
      <footer value="[Footer]&#xA;"/>
      <conversionPattern value="%date %-5level %logger ${COMPUTERNAME} %property{UserHostAddress} [%property{SessionID}] - %message%newline"/>
    </layout>
  </appender>
  <root>
    <level value="INFO"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>
Run Code Online (Sandbox Code Playgroud)

如上所述,我们在机器上间歇性地看到这种情况,但一旦问题发生,它就会持续存在.

Nic*_*cki 165

尝试添加

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

你的<appender />元素.存在一些性能影响,因为这意味着log4net将锁定文件,写入文件并为每次写入操作解锁(与默认行为相反,后者长时间获取并保持锁定).

默认行为的一个含义是,如果您在同一台机器上运行的多个工作进程下执行的Web站点下使用它,则每个站点将尝试无限期地获取并保留该锁定,其中两个是只会输.将锁定模型更改为最小锁定可解决此问题.

(调试时,不正常的终止并激活大量新工作进程正是可能发生的事情.)

祝好运!

  • 我只想读取文件,但是log4net也会锁定以进行读取...它可以仅锁定以进行写入和共享读取 (2认同)

Cip*_*anu 35

另请注意log4net常见问题:

如何让多个进程登录到同一个文件?

在你开始尝试提供的任何替代方案之前,先问问自己是否真的需要让多个进程登录到同一个文件,然后不要这样做;-).

FileAppender为此用例提供可插入锁定模型,但所有现有实现都有问题和缺点.

默认情况下,FileAppender在日志记录时保留对日志文件的独占写锁定.这可以防止其他进程写入该文件.已知此模型在Linux上与(至少在某些版本上)Mono分解,并且一旦另一个进程尝试访问日志文件,日志文件可能会被破坏.

MinimalLock仅在写入日志时获取写锁定. 这允许多个进程将写入交错到同一文件,尽管性能相当大.

InterProcessLock根本不锁定文件,而是使用系统范围的Mutex进行同步.这仅在所有进程协作(并使用相同的锁定模型)时才有效.为每个要写入的日志条目获取和释放Mutex将导致性能损失,但Mutex优于使用MinimalLock.

如果使用RollingFileAppender,事情会变得更糟,因为多个进程可能会尝试同时开始滚动日志文件.RollingFileAppender在滚动文件时完全忽略锁定模型,滚动文件与此方案完全不兼容.

更好的选择是让您的进程登录到RemotingAppenders.使用RemoteLoggingServerPlugin(或IRemoteLoggingSink),进程可以接收所有事件并将它们记录到单个日志文件中.其中一个示例显示了如何使用RemoteLoggingServerPlugin.


小智 6

如果你有

<staticLogFileName value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
Run Code Online (Sandbox Code Playgroud)

并添加

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
Run Code Online (Sandbox Code Playgroud)

滚动发生时会出现错误.第一个进程将创建新文件并重命名当前文件.然后下一个进程将执行相同操作并获取新创建的文件并覆盖新重命名的文件.导致最后一天的logfiel为空.