15

アプリケーションをシャットダウンし、保留中のログ メッセージを書き込みたいです。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;
    }
4

3 に答える 3

6

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

LogManager.Shutdown()は実際にAsyncTargetWrapper同期的に効果的にフラッシュするように強制しますがLogManager.Flush()、 などのターゲットBufferingTargetWrapperは実際にはクローズ時にフラッシュしないため、後で使用する必要があります。これによりLogManager.Configuration = null、フラッシュが実行され、1 回のヒットでターゲットが閉じられ、次に使用する必要があるときに構成が再ロードされる (構成ファイルを使用している場合) ため、設定する方がよい場合があります。

私は両方をテストしましたが、問題を修正した後にログをバックアップして実行したいので、後者を使用しましたが、質問が Silverlight にあることを考えると、次のことをお勧めします。

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

編集

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

于 2016-08-22T04:19:34.600 に答える
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 に答える