如何通过ETW事件捕获SQL命令文本?EtwStream库使用问题求助
如何通过ETW捕获SQL Server命令文本
我之前也踩过这个坑!用EtwStream监听SQL ETW事件却拿不到命令文本,核心问题一般是没选对目标ETW提供程序、没配置正确的事件关键字/级别,或者权限不够。下面是一步步解决的方案:
1. 选对ETW提供程序与目标事件
SQL Server的ETW事件分布在几个核心提供程序里,要捕获命令文本,重点关注这些:
- Microsoft-SQLServer-DatabaseEngine:包含批量SQL执行和RPC调用的核心事件
- (可选)Microsoft-SQLServer-BatchSQL / Microsoft-SQLServer-RPC:更细分的批量SQL、RPC专用提供程序
关键事件类型:
SQLBatchCompleted/SQLBatchStarting:捕获执行的T-SQL批量语句RPC:Completed/RPC:Starting:捕获存储过程调用、参数化查询的命令文本
2. 用EtwStream配置正确的监听参数
光启用提供程序还不够,必须指定对应的事件级别和关键字(Keywords),这些参数决定了你能拿到哪些事件数据。以下是C#示例代码:
using EtwStream; using System.Diagnostics.Tracing; // 创建自定义ETW会话名称(避免和系统会话冲突) var sqlCaptureSession = EtwSession.Create("SQLCommandCaptureSession"); // 启用DatabaseEngine提供程序,指定级别和关键字 // 关键字0x40000000对应SQL Batch事件,0x20000000对应RPC事件,合并用0x60000000 sqlCaptureSession.EnableProvider( providerName: "Microsoft-SQLServer-DatabaseEngine", level: EventLevel.Informational, // 至少要Informational级别才能拿到命令文本 keywords: (EventKeywords)0x60000000 ); // 监听事件并提取命令文本 sqlCaptureSession.OnEvent += (sender, eventArgs) => { // 过滤我们关心的事件类型 if (eventArgs.EventName is "SQLBatchCompleted" or "RPC:Completed") { // 从Payload中提取"Text"字段,这就是SQL命令文本 var sqlCommand = eventArgs.Payload["Text"] as string; if (!string.IsNullOrWhiteSpace(sqlCommand)) { Console.WriteLine($"[Captured] {eventArgs.EventName}: {sqlCommand}"); } } }; // 启动会话 sqlCaptureSession.Start(); Console.WriteLine("正在监听SQL命令...按回车停止"); Console.ReadLine(); // 停止并清理会话 sqlCaptureSession.Stop();
3. 必须注意的权限问题
创建ETW会话需要管理员权限,所以你的程序必须以管理员身份运行,否则会抛出权限不足的异常,根本无法监听事件。
4. 额外注意事项
- 如果是参数化查询,
RPC:Completed事件的Text字段会是带占位符的SQL模板,要获取实际参数值,需要监听RPC:Starting事件并提取Parameterspayload字段。 - 确保你的SQL Server版本支持这些ETW事件:SQL Server 2008及以上版本都支持,旧版本可能没有这些事件。
- 避免和其他ETW工具(比如SQL Server Profiler、Extended Events)冲突,不过ETW本身是低开销的,一般不会有问题。
内容的提问来源于stack exchange,提问作者Bent Rasmussen
相关产品推荐
相关产品推荐

