2012-05-08 6 views
11

アプリケーションをシャットダウンし、保留中のログメッセージを書き込みたいとします。だから私はLogManager.Flush()私のシャットダウンプロセス中に呼び出します。しかし、私は書き出されたすべてのメッセージは表示されません。代わりに、私が(Thread.Sleep()を使用して)数秒待つと、メッセージが表示されます。Flush()が呼び出されたときにNLogがAsyncTargetWrapperのすべてのキューに入れられたメッセージをフラッシュしますか?

NLog's code on 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; 
    } 

答えて

-1

現在のNLogソースコードを編集して修正を実装しました。 AsyncTargetWrapper.csで

、からFlushAsync()方法を変更:TO

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. 
} 
+1

。 –

+0

これはちょっと古いので、全体の文脈を覚えていません。しかし、シャットダウン時に 'Thread.Sleep()'を呼び出す方が良い方法にはなりません。現在のNLogには 'LogManager.Shutdown()'メソッドがありますが、これは(テストしていませんが)より良い選択肢かもしれません。 – ligos

0

ない完璧な、しかしこれはどう:によって

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

コメントligosが正しい軌道にあります。 AsyncTargetWrapper.CloseTarget()メソッドがNLog issue 134の結果として変更されました。ネストされたBufferingTargetWrapperは、ドメインのアンロード時にフラッシュされませんでした。

LogManager.Shutdown()は確かに同期しAsyncTargetWrapperに効果的にフラッシュを強制しないが、そのようなBufferingTargetWrapperなどの目標が近くに実際にフラッシュしませんので、それは、LogManager.Flush()後に使用しなければならないであろう。 LogManager.Configuration = nullを設定する方が良いかもしれません。これは、フラッシュを実行した後、ターゲットを1ヒットで閉じて、次回の使用が必要になると設定がリロードされます(設定ファイルを使用する場合)。

は、私は両方をテストしてきたと私はバックアップ私のロギングを望むと私は物事が右に置いてきた後に実行しているように私は後者で行っているが、Silverlightで私が推薦された質問を与えられた:

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

編集

LogManagerは、ドメインのアンロードや古いNLogのバージョンを実行しない限り、我々はこの問題を見てすべきではないので、プロセスの終了時にnullに設定を設定します。 NLogの問題は2012年10月に修正されました。明示的なシャットダウンや設定をnullにしないでテストし、LogManager.Flush()が十分であることを確認できます。

関連する問題