117

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

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

log4net:ERROR [RollingFileAppender] Unable to acquire lock on file C:\folder\file.log.

该进程无法访问文件“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.

配置部分应如下所示:

<section
  name="log4net"
  type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

我们当前针对该问题的解决方法是重命名最后一个日志文件。我们当然希望这会失败(由于前面提到的文件锁定),但通常不会。由于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>

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

4

3 回答 3

176

尝试添加

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

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

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

(在调试时,不正常的终止和启动大量新的工作进程正是可能发生的事情。)

祝你好运!

于 2010-01-04T13:12:15.593 回答
42

还要注意log4net 常见问题解答

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

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

FileAppender 为这个用例提供了可插入的锁定模型,但所有现有的实现都有问题和缺点。

默认情况下,FileAppender 在记录时对日志文件持有独占写入锁。这可以防止其他进程写入文件。众所周知,这种模型在 Linux 上(至少在某些版本的)Mono 上会崩溃,并且一旦另一个进程尝试访问日志文件,日志文件可能会损坏。

MinimalLock 仅在写入日志时获取写入锁。 这允许多个进程交错写入同一个文件,尽管性能上有相当大的损失。

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

如果您使用 RollingFileAppender,情况会变得更糟,因为多个进程可能会尝试同时开始滚动日志文件。RollingFileAppender 在滚动文件时完全忽略了锁定模型,滚动文件根本不兼容这种场景。

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

于 2013-06-06T15:30:54.567 回答
8

如果你有

<staticLogFileName value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />

并添加

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

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

于 2010-12-20T10:45:09.963 回答