使用并发线程跟踪操作

nep*_*epa 4 .net trace

在MSDN中,我发现了一篇关于如何为特定操作分配一些跟踪的文章.在Microsoft服务跟踪查看器中检查跟踪日志时,这很方便,因为您可以单击某个活动以查看该特定操作的进展情况.

以下是本文中的代码示例,如何为操作分配一些跟踪事件:

Guid traceID = Guid.NewGuid();
ts.TraceTransfer(0, "transfer", traceID);
Trace.CorrelationManager.ActivityId = traceID; // Trace is static
ts.TraceEvent(TraceEventType.Start, 0, "Add request");
Run Code Online (Sandbox Code Playgroud)

问题是:CorrelationManager是静态的,因此影响整个应用程序.你在多线程应用程序中做什么?不幸的是,我发现无法完成多个并行活动.提前致谢!

wag*_*ghe 5

跟踪是静态的.但是,CorrelationManager以线程本地存储的形式存储ActivityId和LogicalOperationStack.CorrelationManager使用CallContext.LogicalSetData存储中的值CallContext中.

这意味着每个线程都可以拥有自己的ActivityId和LogicalOperationStack.

在伪代码中,Trace.CorrelationManager和CorrelationManager.ActivityId的实现看起来像这样:

public static class Trace
{
  private static correlationManager = null;
  public CorrelationManager CorrelationManager
  {
    get
    {
      if (correlationManager == null) correlationManager = new CorrelationManager();
      return correlationManager;
    }
  }
}


public class CorrelationManager
{
  public Guid ActivityId
  {
    get
    {
      object id = CallContext.LogicalGetData("CorelationManager.ActivityId");
      if (id == null)
      {
        return Guid.Empty;
      }
      return (Guid) id;
    }
    set
    {
      CallContext.LogicalSetData("CorrelationManager.ActivityId", value);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,只有一个Trace"对象"(因为它是静态的)并且只有一个CorrelationManager(因为它是一个属性,一个真实的对象实例,在Trace对象上).通过CallContext对象实现上下文数据(ActivityId和LogicalOperationStack)的每线程实例化.

通过CallContext.LogicalSetData存储的数据也"流"到下游线程.因此,如果在线程的开头设置ActivityId并且该线程随后生成线程(可能产生其他线程),则所有这些下游线程将具有相同的ActivityId.

您可以在此处查看Trace和CorrelationManager的源代码(不确定.Net的版本来自哪个版本,但我怀疑它与Trace和CorrelationManager今天的工作方式非常接近:

跟踪

CorrelationManager

  • 嗯,它有一些问题 - 我们在MVC应用程序中尝试了Trace.CorrelationManager.ActivityId,它工作正常,直到我们启动多个并行Web请求 - 然后ActivityId有时会突然转到'00000000-0000-0000-0000-000000000000'.好像有什么东西坏了.也许我们必须在HttpContext中存储我们自己的ActivityId,但我们不确定它是否会有所帮助. (4认同)