EventSource 入门

本文适用范围:✔️ .NET Core 3.1 及更高版本 ✔️ .NET Framework 4.5 及更高版本

本演练演示如何使用 System.Diagnostics.Tracing.EventSource 记录新事件、在跟踪文件中收集事件、查看跟踪并了解基本的 EventSource 概念。

注意

与 EventSource 集成的许多技术使用术语“Tracing”和“Traces”(跟踪),而不是“Logging”和“Logs”(记录)。 这里的含义是相同的。

记录事件

EventSource 的目标是让 .NET 开发人员能够编写如下所示的代码来记录事件:

DemoEventSource.Log.AppStarted("Hello World!", 12);

此代码行包含一个日志记录对象 (DemoEventSource.Log)、一个表示要记录的事件的方法 (AppStarted),以及一些可选的强类型事件参数(HelloWorld!12)。 没有详细级别、事件 ID、消息模板或其他不需要位于调用站点的任何内容。 有关事件的所有其他信息都是通过定义派生自 System.Diagnostics.Tracing.EventSource 的新类编写的。

下面是完整的最小示例:

using System.Diagnostics.Tracing;

namespace EventSourceDemo
{
    public static class Program
    {
        public static void Main(string[] args)
        {
            DemoEventSource.Log.AppStarted("Hello World!", 12);
        }
    }

    [EventSource(Name = "Demo")]
    class DemoEventSource : EventSource
    {
        public static DemoEventSource Log { get; } = new DemoEventSource();

        [Event(1)]
        public void AppStarted(string message, int favoriteNumber) => WriteEvent(1, message, favoriteNumber);
    }
}

DemoEventSource 类为你要记录的每种类型的事件声明了一个方法。 在本例中,名为“AppStarted”的单个事件由 AppStarted() 方法定义。 每次代码调用 AppStarted 方法时,如果启用了另一个 AppStarted 事件,该事件被将记录在跟踪中。 下面是可通过每个事件捕获的一些数据:

  • 事件名称 - 用于标识已记录的事件类型的名称。 事件名称与方法名称相同,在本例中是“AppStarted”。
  • 事件 ID - 用于标识已记录的事件类型的数字 ID。 这会向名称提供类似的角色,但有助于快速进行自动日志处理。 AppStarted 事件具有值为 1 的 ID,在 EventAttribute 中指定。
  • 源名称 - 包含事件的 EventSource 的名称。 这用作事件的命名空间。 事件名称和 ID 只需在其源范围内是唯一的。 这里的源名为“Demo”,在类定义上的 EventSourceAttribute 中指定。 源名称通常也被称为提供程序名称。
  • 参数 - 所有的方法参数值都被序列化。
  • 其他信息 - 事件还可以包含时间戳、线程 ID、处理器 ID、活动 ID、堆栈跟踪和事件元数据(如消息模板、详细级别和关键字)。

有关创建事件的详细信息和最佳做法,请参阅用于创建事件的检测代码

收集和查看跟踪文件

代码中没有必需的配置来描述应启用哪些事件、应在何处发送记录的数据,或应采用哪种格式存储数据。 如果现在运行应用,默认情况下不会生成任何跟踪文件。 EventSource 使用发布-订阅模式,该模式要求订阅者指明应启用哪些事件,并控制已订阅事件的所有序列化。 EventSource 具有用于从 Windows 事件跟踪 (ETW)EventPipe(仅适用于 .NET Core)订阅的集成。 此外,也可以使用 System.Diagnostics.Tracing.EventListener API 创建自定义订阅者。

本演示展示了 .NET Core 应用的 EventPipe 示例。 若要了解更多选项,请参阅收集和查看事件跟踪EventPipe 是一种开放的跨平台跟踪技术,内置于 .NET Core 运行时中,为 .NET 开发人员提供跟踪收集工具和可移植的紧凑跟踪格式(*.nettrace 文件)。 dotnet-trace 是用于收集 EventPipe 跟踪的命令行工具。

  1. 下载并安装 dotnet-trace
  2. 生成上述控制台应用。 本演示假定应用名为 EventSourceDemo.exe 且位于当前目录中。 在命令行上,运行:
>dotnet-trace collect --providers Demo -- EventSourceDemo.exe

应显示类似于以下内容的输出:

Provider Name                           Keywords            Level               Enabled By
Demo                                    0xFFFFFFFFFFFFFFFF  Verbose(5)          --providers

Launching: EventSourceDemo.exe
Process        : E:\temp\EventSourceDemo\bin\Debug\net6.0\EventSourceDemo.exe
Output File    : E:\temp\EventSourceDemo\bin\Debug\net6.0\EventSourceDemo.exe_20220303_001619.nettrace

[00:00:00:00]   Recording trace 0.00     (B)
Press <Enter> or <Ctrl+C> to exit...

Trace completed.

此命令运行了 EventSourceDemo.exe,启用了“Demo”EventSource中的所有事件,并输出了跟踪文件 EventSourceDemo.exe_20220303_001619.nettrace。 在 Visual Studio 中打开文件,将显示已记录的事件。

Visual Studio nettrace file

在列表视图中,你可以看到第一个事件是 Demo/AppStarted 事件。 文本列具有已保存的参数,时间戳列显示在日志记录开始后 27 毫秒发生的事件,右侧可以看到调用堆栈。 其他事件在 dotnet-trace 收集的每个跟踪中自动启用,但如果它们分散你的注意力,可以将其忽略并在 UI 的视图中筛选掉。 这些额外事件捕获了一些有关进程和实时编译的代码的信息,使得 Visual Studio 可以重构事件堆栈跟踪。

详细了解 EventSource