【问题标题】:NLog FileTarget wrapped with BufferingTargetWrapper fails to write log if there is a delay如果有延迟,使用 BufferingTargetWrapper 包装的 NLog FileTarget 无法写入日志
【发布时间】:2012-12-22 23:26:48
【问题描述】:

我可能偶然发现了一个关于 NLog 的问题,但我想我会先在这里查看答案:

为了重现问题,我克隆了 NLog 源,这样我就可以添加延迟来导致问题。在 Visual Studio 中打开后,我添加了一个控制台应用程序,该应用程序引用了 NLog 源项目并进行了一些非常简单的日志调用。 NLog.config如下:

<nlog>
  <targets>
    <target name="buffer" type="BufferingWrapper">
      <target name="logfile" type="File" fileName="log.txt"/>
    </target>
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
  </rules>
</nlog>

到目前为止,一切都按预期工作。下一步是在FileTarget 的刷新逻辑中插入延迟。 (我发现这是问题的原因是我最初使用的是MailTarget,它在连接到邮件服务器时会挂起一段时间 - 我在这里用它代替了FileTarget,而不是重新创建问题更容易)。

打开 FileTarget.cs 并找到 Write(AsyncLogEventInfo[] logEvents) 方法。在第一行插入Thread.Sleep(5000),使方法如下所示:

protected override void Write(AsyncLogEventInfo[] logEvents)
{
    Thread.Sleep(5000);

    // ... omitted
}

现在,编译并重新运行。日志没有写。

据我所知,当进程退出时刷新所有目标的逻辑使用了一个默认超时时间为 15 秒的异步方法调用,可以在 LogFactory.cs Flush() 方法中找到 - 这显然是没有被超过。

但是,NLog 使用ThreadPool.QueueUserWorkItem()(在 AsyncHelpers.cs 中找到)来并行协调每个目标的刷新。这是否可以简单归结为一个问题,即这种形式的方法调用如何响应对 Thread.Sleep() 的调用或任何其他形式的阻塞(例如连接到远程服务器,就像我原来的问题一样)?

有什么想法吗?

【问题讨论】:

标签: c# asynchronous threadpool nlog


【解决方案1】:

我终于弄清楚为什么什么都没有记录,不幸的是,对此无能为力。

根据 AppDomain.ProcessExit 的 MSDN 文档,这是由 NLog 处理的事件:

所有 ProcessExit 事件处理程序的总执行时间是有限的, 正如所有终结器的总执行时间被限制在 进程关闭。默认值为两秒。非托管主机可以 通过调用 带有 OPR_ProcessExit 的 ICLRPolicyManager::SetTimeout 方法 枚举值。

因此,从托管代码处理此问题的唯一方法似乎是在允许应用程序退出之前手动调用 LogManager.Flush()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2020-07-08
    • 2015-09-15
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 2016-05-05
    相关资源
    最近更新 更多