跟踪参与者

跟踪参与者是扩展点,允许工作流开发人员访问 TrackingRecord 对象并对其进行处理。 .NET Framework 4.6.1 包括一个标准跟踪参与者,该参与者将跟踪记录写入 Windows 事件跟踪(ETW)事件中。 如果这不符合你的要求,还可以编写自定义跟踪参与者。

跟踪参与者

跟踪基础结构允许对传出跟踪记录应用筛选器,以便参与者可以订阅记录的子集。 应用筛选器的机制是通过跟踪配置文件来实现的。

.NET Framework 4.6.1 中的 Windows Workflow Foundation (WF)提供将跟踪记录写入 ETW 会话的跟踪参与者。 通过在配置文件中添加特定于跟踪的行为,可以对工作流服务配置参与者。 启用 ETW 跟踪参与者可在事件查看器中查看跟踪记录。 基于 ETW 的跟踪的 SDK 示例是一种很好的方法,可使用基于 ETW 的跟踪参与者来熟悉 WF 跟踪。

ETW 跟踪参与者

.NET Framework 4.6.1 包括将跟踪记录写入 ETW 会话的 ETW 跟踪参与者。 这是以非常高效的方式完成的,对应用程序的性能或服务器的吞吐量的影响最小。 使用标准 ETW 跟踪参与者的优点是,可以使用 Windows 事件查看器中的其他应用程序和系统日志查看它收到的跟踪记录。

在 Web.config 文件中配置标准 ETW 跟踪参与者,如下例所示。

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <etwTracking profileName="Sample Tracking Profile"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
   <tracking>
      <profiles>
        <trackingProfile name="Sample Tracking Profile">
        ….
       </trackingProfile>
      </profiles>
    </tracking>
  </system.serviceModel>
</configuration>

注释

如果未指定 trackingProfile 名称,例如只使用 <etwTracking/><etwTracking profileName=""/>,则使用 Machine.config 文件中随 .NET Framework 4.6.1 安装的默认跟踪配置文件。

在 Machine.config 文件中,默认跟踪配置文件订阅工作流实例记录和错误。

在 ETW 中,事件通过提供程序 ID 写入 ETW 会话中。 ETW 跟踪参与者用于将跟踪记录写入 ETW 的提供程序 ID 在 Web.config 文件的 diagnostics 节(<system.serviceModel><diagnostics> 下)中定义。 默认情况下,ETW 跟踪参与者在未指定提供程序 ID 时使用默认提供程序 ID,如以下示例所示。

<system.serviceModel>
        <diagnostics etwProviderId="52A3165D-4AD9-405C-B1E8-7D9A257EAC9F" />

下图显示了通过 ETW 跟踪参与者的跟踪数据流。 跟踪数据到达 ETW 会话后,可以通过多种方式访问它。 访问这些事件的最有用方法之一是通过事件查看器,这是用于查看应用程序和服务的日志和跟踪的常见 Windows 工具。

通过 ETW 跟踪提供程序跟踪数据的流程。

跟踪参与者事件数据

跟踪参与者以每个跟踪记录一个事件的格式将被跟踪的事件数据序列化到 ETW 会话中。 使用 100 到 199 范围内的 ID 标识事件。 有关跟踪参与者发出的跟踪事件记录的定义,请参阅 跟踪事件参考 主题。

ETW 事件的大小受 ETW 缓冲区大小限制,或者由 ETW 事件的最大有效负载限制,以较小的值为准。 如果事件的大小超过了任一 ETW 限制,则事件会被截断,其内容会以任意方式被删除。 不会有选择地删除变量、参数、注释和自定义数据。 发生截断时,所有这些内容都将被截断,无论导致事件大小超出 ETW 限制的是哪个值。 已删除的数据将替换为 <item>..<item>

变量、参数和自定义数据项中的复杂类型使用 NetDataContractSerializer 类序列化为 ETW 事件记录。 此类在序列化的 XML 流中包括 CLR 类型的信息。

由于 ETW 限制而截断负载数据可导致向同一 ETW 会话发送重复的跟踪记录。 如果多个会话正在侦听事件,并且会话对事件有不同的有效负载限制,则可能会出现这种情况。

对于具有较低限制的会话,可能会截断事件。 ETW 跟踪参与者不知道侦听事件的会话的数量;如果某个会话截断了一个事件,则 ETW 参与者会重新尝试发送一次该事件。 在这种情况下,配置为可接受较大负载大小的会话将获取该事件两次(未截断的和已截断的事件)。 可以通过配置具有相同缓冲区大小限制的所有 ETW 会话来防止重复。

在事件查看器中访问 ETW 跟踪参与者的跟踪数据

可以通过事件查看器(使用默认提供程序 ID 时)访问 ETW 跟踪参与者写入 ETW 会话的事件。 这样就可以快速查看工作流发出的跟踪记录。

注释

向 ETW 会话发出的跟踪记录事件使用从 100 到 199 范围内的事件 ID。

启用在事件查看器中查看跟踪记录的功能

  1. 启动事件查看器(EVENTVWR.EXE)

  2. 选择 事件查看器、应用程序和服务日志、Microsoft、Windows、Application Server-Applications

  3. 右键单击并确保已选择 “查看”、“显示分析和调试日志 ”。 如果未选中,请选中它以使选中标记显示在它旁边。 这会显示 AnalyticPerfDebug 日志。

  4. 右键单击 分析 日志,然后选择“ 启用日志”。 日志将存在于 %SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-Application Server-Applications%4Analytic.etl 文件中。

自定义跟踪参与者

跟踪参与者 API 允许使用用户提供的跟踪参与者扩展跟踪运行时,该参与者可以包含自定义逻辑来处理工作流运行时发出的跟踪记录。 若要编写自定义跟踪参与者,开发人员必须在Track类上实现TrackingParticipant方法。 当工作流运行时发出跟踪记录时调用此方法。

跟踪参与者从 TrackingParticipant 类派生。 系统提供的 EtwTrackingParticipant 为每个收到的跟踪记录发出一个 Windows 事件跟踪 (ETW) 事件。 若要创建自定义跟踪参与者,将创建派生自 TrackingParticipant的类。 若要提供基本的跟踪功能,请重写 Track。在运行时发送跟踪记录时,会调用 Track,然后可以根据需要进行处理。 在以下示例中,定义了一个自定义跟踪参与者类,用于向控制台窗口发出所有跟踪记录。 你还可以实现一个 TrackingParticipant 对象,该对象使用其 BeginTrackEndTrack 方法来异步处理跟踪记录。

class ConsoleTrackingParticipant : TrackingParticipant
{
    protected override void Track(TrackingRecord record, TimeSpan timeout)
    {
        if (record != null)
        {
            Console.WriteLine("=================================");
            Console.WriteLine(record);
        }
    }
}

若要使用特定的跟踪参与者,请将其注册到要跟踪的工作流实例,如以下示例所示。

myInstance.Extensions.Add(new ConsoleTrackingParticipant());

在以下示例中,创建了一个由包含 Sequence 活动的 WriteLine 活动组成的工作流。 将 ConsoleTrackingParticipant 添加到扩展,并调用工作流。

Activity activity= new Sequence()
{
    Activities =
    {
        new WriteLine()
        {
            Text = "Hello World."
        }
    }
};

WorkflowApplication instance = new WorkflowApplication(activity);

instance.Extensions.Add(new ConsoleTrackingParticipant());
  instance.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
            {
                Console.WriteLine("workflow instance completed, Id = " + instance.Id);
                resetEvent.Set();
            };
            instance.Run();
            Console.ReadLine();

另请参阅