启用 SqlClient 中的事件跟踪

适用于: .NET Framework .NET .NET Standard

下载 ADO.NET

Windows 事件跟踪 (ETW) 是一种高效的内核级别跟踪功能,通过此功能,你可以记录用于调试和测试的驱动程序定义的事件。 SqlClient 支持在不同的信息级别捕获 ETW 事件。 若要开始捕获事件跟踪,客户端应用程序应侦听来自 SqlClient 的 EventSource 实现的事件:

Microsoft.Data.SqlClient.EventSource

当前实现支持以下事件关键字:

关键字名称 描述
ExecutionTrace 1 启用命令执行前后捕获启动/停止事件。
跟踪 2 启用捕获基本应用程序流跟踪事件。
范围 4 启用捕获进入和退出事件
NotificationTrace 8 启用捕获 SqlNotification 跟踪事件
NotificationScope 16 启用捕获 SqlNotification 范围进入和退出事件
PoolerTrace 32 启用捕获连接池流跟踪事件。
PoolerScope 64 启用捕获连接池范围跟踪事件。
AdvancedTrace 128 启用捕获高级流跟踪事件。
AdvancedTraceBin 256 启用捕获带有其他信息的高级流跟踪事件。
CorrelationTrace 512 启用捕获关联流跟踪事件。
StateDump 1024 启用捕获完整状态转储 SqlConnection
SNITrace 2048 启用从托管网络实现捕获流跟踪事件(仅适用于 .NET Core)
SNIScope 4096 启用从托管网络实现捕获范围事件(仅适用于 .NET Core)

示例

下面的示例对“AdventureWorks”示例数据库上的数据操作启用事件跟踪,并在控制台窗口中显示事件。

using System;
using System.Diagnostics.Tracing;
using Microsoft.Data.SqlClient;

// This listener class will listen for events from the SqlClientEventSource class.
// SqlClientEventSource is an implementation of the EventSource class which gives 
// it the ability to create events.
public class SqlClientListener : EventListener
{
    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        // Only enable events from SqlClientEventSource.
        if (eventSource.Name.Equals("Microsoft.Data.SqlClient.EventSource"))
        {
            // Use EventKeyWord 2 to capture basic application flow events.
            // See the above table for all available keywords.
            EnableEvents(eventSource, EventLevel.Informational, (EventKeywords)2);
        }
    }

    // This callback runs whenever an event is written by SqlClientEventSource.
    // Event data is accessed through the EventWrittenEventArgs parameter.
    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        // Print event data.
        Console.WriteLine(eventData.Payload[0]);
    }
}

class Program
{
    public static void Main()
    {
        // Create a new event listener.
        using (SqlClientListener listener = new SqlClientListener())
        {
            string connectionString = "Data Source=localhost; " +
                "Initial Catalog=AdventureWorks; Integrated Security=true";

            // Open a connection to the AdventureWorks database.
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                string sql = "SELECT * FROM Sales.Currency";
                SqlCommand command = new SqlCommand(sql, connection);

                // Perform a data operation on the server.
                SqlDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    // Read the data.
                }
                reader.Close();
            }
        }
    }
}

本机 SNI 中的事件跟踪支持

Microsoft.Data.SqlClient 在 Microsoft.Data.SqlClient.SNI 和 Microsoft.Data.SqlClient.SNI.runtime(从 v2.1 开始)中提供了事件跟踪支持 。 可使用 XperfPerfView 工具从本机 DLL 收集事件。

从 Microsoft.Data.SqlClient v3.0 开始,可使用事件收集工具启用事件跟踪,而无需在客户端应用程序中进行任何修改。

对于 Microsoft.Data.SqlClient v2.1,需要通过使用事件源侦听器配置 EventCommand 来启用事件跟踪。 适用于本机 SNI 的有效 EventCommand 值如以下所示:


// Enables trace events:
EventSource.SendCommand(eventSource, (EventCommand)8192, null);

// Enables flow events:
EventSource.SendCommand(eventSource, (EventCommand)16384, null);

// Enables both trace and flow events:
EventSource.SendCommand(eventSource, (EventCommand)(8192 | 16384), null);

下面的示例在本机 SNI DLL 中启用了事件跟踪。

// Native SNI tracing example
using System;
using System.Diagnostics.Tracing;
using Microsoft.Data.SqlClient;

public class SqlClientListener : EventListener
{
    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        if (eventSource.Name.Equals("Microsoft.Data.SqlClient.EventSource"))
        {
            // Enables both trace and flow events
            EventSource.SendCommand(eventSource, (EventCommand)(8192 | 16384), null);
        }
    }
}

class Program
{
    static string connectionString = @"Data Source = localhost; Initial Catalog = AdventureWorks;Integrated Security=true;";

    static void Main(string[] args)
    {
        // Event source listener configuration is not required in v3.0 onwards.
        using (SqlClientListener listener = new SqlClientListener())
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
        }
    }
}

使用 Xperf 收集跟踪

  1. 使用以下命令启动跟踪。

    xperf -start trace -f myTrace.etl -on *Microsoft.Data.SqlClient.EventSource
    
  2. 运行本机 SNI 跟踪示例以连接到 SQL Server。

  3. 使用以下命令停止跟踪。

    xperf -stop trace
    
  4. 使用 PerfView 打开在步骤 1 中指定的 myTrace.etl 文件。 可以通过 Microsoft.Data.SqlClient.EventSource/SNIScopeMicrosoft.Data.SqlClient.EventSource/SNITrace 事件名称找到 SNI 跟踪日志。

    使用 PerfView 查看 SNI 跟踪文件

使用 PerfView 收集跟踪

  1. 启动 PerfView,并从菜单栏运行 Collect > Collect

  2. 配置跟踪文件名、输出路径和提供程序名称。

    在收集之前配置 Perfview

  3. 开始收集。

  4. 运行本机 SNI 跟踪示例以连接到 SQL Server。

  5. 使用 PerfView 停止收集。 根据步骤 2 中的配置,生成 PerfViewData.etl 文件需要一段时间。

  6. 在 PerfView 中打开 etl 文件。 可以通过 Microsoft.Data.SqlClient.EventSource/SNIScopeMicrosoft.Data.SqlClient.EventSource/SNITrace 事件名称找到 SNI 跟踪日志。

使用 dotnet-trace 收集跟踪

在 Linux、macOS 或 Windows 上,dotnet-trace 可用于捕获跟踪。 donet-trace 工具用于收集 .NET 应用程序的跟踪。 有关 dotnet-trace 的详细信息,请参阅 dotnet-trace 性能分析实用工具。可在 PerfView 中查看 dotnet-trace 创建的跟踪。

  1. 如果尚未安装,请在客户端计算机上安装 .NET SDK

  2. 安装 dotnet-trace

  3. 运行 dotnet-trace。 --providers 参数要求为 Microsoft.Data.SqlClient 中的跟踪指定提供程序名称和关键字。 关键字选项是转换为十六进制的事件关键字表中关键字值的总和。 若要从应用程序开头的详细级别 MyApplication 收集所有事件,关键字的总和为 8191,采用十六进制时为 1FFF。 通过 5 在此命令中指定详细级别。

    dotnet-trace collect --providers Microsoft.Data.SqlClient.EventSource:1FFF:5 -- dotnet MyApplication.dll
    

    输出为:

    
    Provider Name                           Keywords            Level               Enabled By
    Microsoft.Data.SqlClient.EventSource    0x0000000000001FFF  Verbose(5)          --providers
    
    Launching: dotnet MyApplication.dll
    Process        : /usr/lib/dotnet/dotnet
    Output File    : /home/appuser/dotnet_20240927_102506.nettrace
    
    [00:00:00:00]   Recording trace 0.00     (B)
    Press <Enter> or <Ctrl+C> to exit...
    
    Trace completed.
    Process exited with code '1'.
    

    若要在正在运行的应用程序的信息级别收集所有事件,请先查找应用程序的进程 ID。 然后在进程中运行 dotnet-trace。 信息级别由 4 指定。

    dotnet-trace ps
    8734  MyApplication  /home/appuser/MyApplication/MyApplication
    
    dotnet-trace collect -–process-id 8734 --providers Microsoft.Data.SqlClient.EventSource:1FFF:4
    

    单独运行应用程序,直到问题重现。 如果是高 CPU,通常 5 - 10 秒就足够了。

    Provider Name                           Keywords            Level               Enabled By
    Microsoft.Data.SqlClient.EventSource    0x0000000000001FFF  LogAlways(0)        --providers
    
    Process        : /usr/lib/dotnet/dotnet
    Output File    : /home/appuser/dotnet_20240927_104154.nettrace
    
    [00:00:00:10]   Recording trace 4.096    (KB)
    Press <Enter> or <Ctrl+C> to exit...
    Stopping the trace. This may take several minutes depending on the application being traced.
    
    Trace completed.
    

    跟踪文件名称以 .nettrace 结尾。 如果未在 Windows 上跟踪,请将该文件复制到 Windows 系统。 在 PerfView 中查看跟踪文件。

外部资源

有关如何跟踪 Microsoft.Data.SqlClient 跨平台的另一组示例,请参阅 CSS SQL 网络工具 Wiki

有关事件跟踪的详细信息,请参阅以下资源。

资源 说明
EventSource 类 用于创建 ETW 事件。
EventListener 类 提供用于启用和禁用事件源中事件的方法。