System.Diagnostics.Activity- Parent/Child 关系在使用多个线程时不起作用

System.Diagnostics.Activity- Parent/Child relation doesnt work when using multiple Threads

我有一个问题,当父 activity 由另一个线程启动时,主线程将看不到这个 activity,而下一个应该是正在创建的子活动的活动主线程,不会添加到我在另一个线程中创建的父 Activity。

我有:

  1. Sytem.Diagnostics.ActivitySource的静态定义:

     public static readonly ActivitySource MyActivitySource = new ActivitySource("myAppName");
    
  2. 跟踪器提供程序的静态定义OpenTelemetry.Trace.TraceProvider:

     public static TracerProvider traceProvider;
    
  3. 父类的静态定义Activity:

     public static Activity parentActivity;
    

现在它是如何工作的:

  1. 首先在另一个线程中创建Activity(使用System.Timers.Timer),然后在主线程中调用函数。下面的代码只执行一次——当 parentActivity 没有初始化时:

     parentActivity = MyActivitySource.StartActivity("CycleActivity", ActivityKind.Internal);
     parentActivity.AddTag("hostname", Environment.MachineName)
     parentActivity.Start();
     mainForm.Invoke(new Action(() => initiateProcess()));
    
  2. 然后在 initiateProcess 函数中我们启动子 activity- 一切正常,我可以在日志中看到子 activity 有父 'CycleActivity' 这是在第 4 步中从另一个线程创建的。

     public void initiateProcess()
     {
         using (var subActivity= global.MyActivitySource.StartActivity("sendingTriggerToDevice"))
         {
             subActivity.Start();
             deviceTcp.Send("Trigger");
             subActivity.Stop();
         }
     }
    
  3. 问题发生在下一步,等待数据来自deviceTcp。 我已经定义了回调函数,即 运行 当 deviceTcp 向我的应用程序发送数据时。 我在该函数中创建了 activity,主体看起来像:

    public void deviceTcpMessageReceived(string data)
    {
      using (var subActivity = global.MyActivitySource.StartActivity("deviceTcpMessageReceived"))
      {
         subActivity.Start();
         //.... additional stuff
      }
      parentActivity.Stop();
    }
    

已在第 4 步启动的父 activity 在此期间未停止。 我知道 deviceTcpMessageReceived 是 运行,并且一切正常,除了在名为 deviceTcpMessageReceived 的回调中创建的 activity 没有连接到父 activity。

  1. 总结

任何想法,为什么当我在主线程上同步调用 initiateProcess 的调用(从子线程)时,父 Activity 仅对 MyActivitySource 可见,而它不是可见,当来自设备的消息正在到来时,回调函数 deviceTcpMessageReceived 正在主线程上 运行?

我在文档 System.Diagnostics.Activity 中读到,当我开始新的 Activity 时,我可以设置一个 ActivityKind:

By default, all new Activities are set to Internal, which is appropriate for Activities that are an internal operation within an application with no remote parent or children.

但我不知道 Activity Kind 我应该使用什么。 IMO 他们不应该影响 parent/children 活动之间的关系行为。 (当您查看我描述的第 4 步和第 5 步时,他们显然不会这样做)。

同时子线程的父activity也没有关闭(没有using, or Stop being called in meantime),直到我们成功接收到来自deviceTcp的数据,所以我不明白为什么Activity创建在第6个没有父

欢迎任何帮助或建议。

如果活动不在同一范围内,它们可能不会相互连接。 要解决您的问题,您必须在回调函数中设置 Parent Activity 。 如果您想将回调事件连接到 Cycle Activity,您必须调用 SetParentId 方法来连接您的回调 Activity,您的代码可能如下所示:

public void deviceTcpMessageReceived(string data)
{
  using (var subActivity = global.MyActivitySource.StartActivity("deviceTcpMessageReceived"))
  {
     subActivity.SetParentId(parentActivity.TraceId, parentActivity.SpanId);
     subActivity.Start();
     //.... additional stuff
  }
  parentActivity.Stop();
}