15

我想关闭我的应用程序并写入任何待处理的日志消息。所以我LogManager.Flush()在关机过程中打电话。但是,我没有看到所有写出的消息。相反,如果我等待几秒钟(使用Thread.Sleep()),我会看到这些消息。

在检查了 NLog 在 GitHub 上的代码后,我发现该AsyncTargetWrapper.FlushAsync()方法只是调度惰性写入器线程以在下一批中写入所有待处理的消息。它没有同步写入日志消息。

这是预期的行为吗?我期望LogManager.Flush()是同步的,即:阻塞直到所有待处理的消息都被写入(或超时)。


我在关机时使用的代码:

LogManager.Flush(ex => { }, TimeSpan.FromSeconds(15));

然后是初始化 Nlog 的代码(这是一个 Silverlight 应用程序,所以我没有使用任何配置文件)。

    public static void InitialiseNLog(LogLevel forLevel)
    {
        var config = new LoggingConfiguration();

        // Add targets.
        // We need an async target wrapping a custom web service call back to the server.
        var serverTarget = new RemoteServiceTarget();
        var asyncWrapper = new AsyncTargetWrapper(serverTarget, 10000, AsyncTargetWrapperOverflowAction.Discard);
        asyncWrapper.TimeToSleepBetweenBatches = (int)TimeSpan.FromSeconds(2).TotalMilliseconds;
        asyncWrapper.BatchSize = 200;

        // Add rules.
        var rule = new LoggingRule("Company.Application.SilverlightApp.*", forLevel, asyncWrapper);
        config.LoggingRules.Add(rule);

        // Activate the configuration.
        LogManager.Configuration = config;
        LogManager.GlobalThreshold = forLevel;
    }
4

3 回答 3

6

ligos的评论是正确的。由于NLog 问题 134修改了该AsyncTargetWrapper.CloseTarget()方法,其中嵌套在域卸载时没有被刷新。BufferingTargetWrapper

LogManager.Shutdown()确实会强制AsyncTargetWrapper同步有效地刷新,但必须在之后使用它,LogManager.Flush()因为诸如 之类的目标BufferingTargetWrapper实际上并没有在关闭时刷新。设置可能会更好,LogManager.Configuration = null因为这会执行刷新,然后一次关闭目标,并且下次需要使用配置时将重新加载(如果使用配置文件)。

我已经对两者都进行了测试,并且我选择了后者,因为我希望在我把事情做好后重新启动并运行日志记录,但鉴于问题是在 Silverlight 中,我建议:

LogManager.Flush();
LogManager.Shutdown();

编辑

LogManager在域卸载或进程退出时将配置设置为 null,因此除非运行旧的 NLog 版本,否则我们不应该看到这个问题。NLog 问题已于 2012 年 10 月修复。在没有显式关闭或将 config 设置为 null 的情况下进行了测试,并且可以确认调用LogManager.Flush()就足够了。

于 2016-08-22T04:19:34.600 回答
1

公然盗取: 在 NLog 中缓冲日志消息并手动将它们刷新到目标

LogManager.Configuration.AllTargets
.OfType<BufferingTargetWrapper>()
.ToList()
.ForEach(b => b.Flush(e =>
    {
        //do nothing here
    }));
于 2016-09-21T09:21:00.820 回答
0

我通过编辑当前的 NLog 源代码实现了修复。

在 AsyncTargetWrapper.cs 中,将FlushAsync()方法更改为:

protected override void FlushAsync(AsyncContinuation asyncContinuation)
{
    this.flushAllContinuation = asyncContinuation;
}

到:

protected override void FlushAsync(AsyncContinuation asyncContinuation)
{
    this.flushAllContinuation = asyncContinuation;
    this.ProcessPendingEvents(null);        // Added to make this flush synchronous.
}
于 2012-05-09T01:02:23.830 回答