如果有延迟,使用BufferingTargetWrapper包装的NLog filettarget将无法写入日志



我可能偶然发现了NLog的一个问题,但我想我应该先检查一下这里的答案:

为了重新创建这个问题,我克隆了NLog源,这样我就可以添加延迟来引起这个问题。在visual studio中打开后,我添加了一个控制台应用程序,它引用NLog源项目并进行一些非常简单的日志调用。NLog。配置如下:

<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,以使重新创建问题更容易)。

打开filettarget .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()的调用,或任何其他形式的阻塞(例如连接到远程服务器,就像我最初的问题一样)?

任何想法?

我终于弄清楚了为什么没有记录,不幸的是,对此没有太多可以做的。

根据AppDomain的MSDN文档。processsexit,这是NLog处理的事件:

所有processsexit事件处理程序的总执行时间是有限的,正如所有终结器的总执行时间被限制在关闭过程。默认值是2秒。非托管主机可以方法更改此执行时间ICLRPolicyManager::使用opr_processsexit设置timeout方法枚举值。

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