You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSMS程序集存储过程日志添加与查看问题求助

SQL CLR存储过程日志排查方案

一、适合SQL CLR的日志方法及查看方式

1. 直接通过SqlContext.Pipe输出到SSMS查询窗口

这是最直接的实时排查方式,和你在StoredProcedures里用的方式逻辑一致,能在SSMS查询窗口实时看到日志。

  • 注意:异步方法runWSClient中也可使用,你的代码通过GetAwaiter().GetResult()同步调用,完全兼容该方式。
  • 查看位置:执行存储过程的SSMS窗口切换到消息标签页(输出文本日志)或结果标签页(输出SqlDataRecord格式日志)。

2. 写入SQL Server错误日志

适合记录关键错误或核心运行状态,可通过系统存储过程将日志写入SQL Server自带的错误日志。

  • 查看方式:
    • SSMS中展开服务器 → 管理 → SQL Server日志 → 双击当前日志查看
    • 执行T-SQL查询:EXEC xp_readerrorlog

3. 写入自定义日志表

创建专属日志表存储日志,适合长期留存和后续分析,需给CLR程序集授予EXTERNAL_ACCESS权限。

  • 步骤:
    1. 先创建日志表:
      CREATE TABLE dbo.CLRProcedureLogs (
          LogID INT IDENTITY(1,1) PRIMARY KEY,
          LogTime DATETIME DEFAULT GETDATE(),
          LogLevel VARCHAR(20),
          Message NVARCHAR(MAX),
          ProcedureName NVARCHAR(128)
      )
      
    2. 在CLR代码中通过SqlConnection插入日志记录。

4. 写入本地文件(临时排查用)

用System.IO.File类写入本地文件,需确保SQL Server服务账号拥有目标目录的写入权限,仅推荐临时排查使用。


二、针对你的代码的具体修改示例

修改WSClient类,添加多节点日志输出

public class WSClient
{
    public static async Task runWSClient(String value)
    {
        using (ClientWebSocket client = new ClientWebSocket())
        {
            Uri servicesUri = new Uri("wss://websocket.kawczynski.eu");
            var cTs = new CancellationTokenSource();
            cTs.CancelAfter(TimeSpan.FromSeconds(120));
            try
            {
                // 连接前状态日志
                SqlContext.Pipe.Send($"[{DateTime.Now}] 准备连接WebSocket服务器: {servicesUri}");
                
                await client.ConnectAsync(servicesUri, cTs.Token);
                
                // 连接状态日志
                SqlContext.Pipe.Send($"[{DateTime.Now}] WebSocket当前状态: {client.State}");

                if (client.State == WebSocketState.Open)
                {
                    string message = value;
                    SqlContext.Pipe.Send($"[{DateTime.Now}] 待发送消息内容: {message}");
                    
                    if (!string.IsNullOrEmpty(message))
                    {
                        ArraySegment<byte> byteToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message));
                        await client.SendAsync(byteToSend, WebSocketMessageType.Text, true, cTs.Token);
                        
                        // 发送完成日志
                        SqlContext.Pipe.Send($"[{DateTime.Now}] 消息发送成功");
                    }
                }
            }
            catch (WebSocketException e)
            {
                // 输出错误到SSMS消息窗口
                SqlContext.Pipe.Send($"[{DateTime.Now}] WebSocket异常: {e.Message}");
                // 同时写入SQL错误日志
                using (SqlConnection conn = new SqlConnection("context connection=true"))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(
                        $"RAISERROR(N'CLR WSClient错误: {e.Message}', 10, 1) WITH LOG;", 
                        conn);
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                // 捕获所有未预料异常
                SqlContext.Pipe.Send($"[{DateTime.Now}] 未知异常: {ex.Message}");
            }
        }
    }
}

修改StoredProcedures类,添加调用前后日志

[Microsoft.SqlServer.Server.SqlProcedure]
public static void HelloWorld(String value)
{
    Microsoft.SqlServer.Server.SqlMetaData columnInfo
= new Microsoft.SqlServer.Server.SqlMetaData("VALUE", SqlDbType.NVarChar, Max);
    SqlDataRecord greetingRecord
        = new SqlDataRecord(new Microsoft.SqlServer.Server.SqlMetaData[] { columnInfo });

    greetingRecord.SetString(0, value);
    SqlContext.Pipe.Send(greetingRecord);
    
    // WSClient调用前日志
    SqlContext.Pipe.Send($"[{DateTime.Now}] 开始执行WSClient调用,传入参数: {value}");
    
    var ws = new WSClient();
    WSClient.runWSClient(value).GetAwaiter().GetResult();
    
    // WSClient调用完成日志
    SqlContext.Pipe.Send($"[{DateTime.Now}] WSClient调用执行完毕");
}

三、日志查看方式说明

  1. SSMS消息窗口:执行存储过程后,切换到「消息」标签页,即可查看所有SqlContext.Pipe.Send输出的文本日志。
  2. SQL Server错误日志:在SSMS中进入「服务器 → 管理 → SQL Server日志」,双击当前日志就能找到通过RAISERROR WITH LOG写入的错误信息。
  3. 自定义日志表:直接执行SELECT * FROM dbo.CLRProcedureLogs即可查询所有留存的日志记录。

内容的提问来源于stack exchange,提问作者Eva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:16:10