簡體   English   中英

當調用Flush()時,NLog是否應該刷新AsyncTargetWrapper中的所有排隊消息?

[英]Should NLog flush all queued messages in the AsyncTargetWrapper when Flush() is called?

我想關閉我的應用程序並寫入任何掛起的日志消息。 所以我在關機過程中調用了LogManager.Flush() 但是,我沒有看到所有的消息寫出來。 相反,如果我等待幾秒鍾(使用Thread.Sleep() ),我會看到消息。

GitHUB上檢查NLog的代碼之后 ,我發現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;
    }

ligos的評論是在正確的軌道上。 由於NLog問題134AsyncTargetWrapper.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()就足夠了。

還不完美,但是這個怎么樣:

var reset = new ManualResetEventSlim(false);
LogManager.Flush(ex => reset.Set(), TimeSpan.FromSeconds(15));
reset.Wait(TimeSpan.FromSeconds(15));

公然被盜: 在NLog中緩沖日志消息並手動將它們刷回目標

LogManager.Configuration.AllTargets
.OfType<BufferingTargetWrapper>()
.ToList()
.ForEach(b => b.Flush(e =>
    {
        //do nothing here
    }));

我通過編輯當前的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.
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM