2

ログが作成されるparallel.forループ内のファイルに対していくつかの操作を実行します。しかし、どの操作が特定のログエントリを作成したかを知る必要があります。nlog-configで{ThreadID}を使用しようとしましたが、threadIDがparallel.forループによって再利用されるため、一意の識別子がないようです。すべてのファイルに一意のログ識別子を与える方法についての提案はありますか?

基本コード:

Private Sub DoParallel
 Private Logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger 
 Dim ListOfFolder as New List(of String)
 ListOfFolder.add("C:\Test.txt")

 Parallel.ForEach(listOfFolders, Sub(elem As String)
     logger.warn("Doing stuff, need to know on which elem it is done")
  End Sub)
End Sub

Nlog構成:

 layout="${threadid} | ${time} | ${level:uppercase=true} | ${logger} | ${message} | ${exception}"
4

1 に答える 1

2

Trace.CorrelationManager.ActivityIdを使用してみてください。値を設定してから、カスタムNLog LayoutRendererを使用して、その値を出力ログにレンダリングできます。これを行うLayoutRendererの例をSOで見つけることができます。一番上の答えの真ん中で見てください。

その投稿のLayoutRenderのコードは次のとおりです(NLog2.0ではなくNLog1.0に対して作成されていることに注意してください。更新するのは難しいことではありません)。

[LayoutRenderer("ActivityId")]
class ActivityIdLayoutRenderer : LayoutRenderer
{
  int estimatedSize = Guid.Empty.ToString().Length;

  protected override void Append(StringBuilder builder, LogEventInfo logEvent)
  {
    builder.Append(Trace.CorrelationManager.ActivityId);
  }

  protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
  {
    return estimatedSize;
  }
}

NLog.configは次のようになります。

NLog拡張機能が配置されている場所をNLogに通知します。

<extensions>
    <add assembly="MyNLogExtensions"/>
</extensions>

layout="${threadid} | ${ActivityId} | ${time} | ${level:uppercase=true} | ${logger} | ${message} | ${exception}"

元のサンプルコードを使用して、次のようなログを記録できます。

Private Sub DoParallel
 Private Logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger 
 Dim ListOfFolder as New List(of String)
 ListOfFolder.add("C:\Test.txt")

 Trace.CorrelationManager.ActivityId = Guid.Empty;
 Parallel.ForEach(listOfFolders, Sub(elem As String)
     Trace.CorrelationManager.ActivityId = Guid.NewGuid();
     logger.warn("Doing stuff, need to know on which elem it is done")
     Trace.CorrelationManager.ActivityId = Guid.Empty;
  End Sub)
End Sub

これにより、各ロギングステートメントが一意に識別され、アクションにさらに多くのコード行がある場合、アクションの特定の実行からのすべてのロギングステートメントに同じGUIDがタグ付けされます。

このアプローチがうまくいく場合は、ActivityIdの設定/設定解除をIDisposableクラスで簡単にラップし、usingステートメントを使用してプロセスを自動化できます。

C#をご容赦ください:

public class ActivityIdContext : IDisposable
{
  Guid oldActivityId;

  public ActivityIdContext(Guid id)
  {
    oldActivityId = Trace.CorrelationManager.ActivityId;
    Trace.CorrelationManager.ActivityId = Guid.NewGuid();
  }

  public ActivityIdContext() : this(Guid.NewGuid()) { }

  public Dispose()
  {
    Trace.CorrelationManager.ActivityId = oldActivityId;
  }
}

次に、Parallel.ForEachアクションの本体を囲んで、このようなことを行うことができます(これもC#で)

Parallel.ForEach(listOfFolders, () =>
{
  using(new ActivityIdContext())
  {
    logger.Warn("Hello!  I hope the ActivityId helps!");
  }
});
于 2012-10-16T15:15:33.503 に答える