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

Blazor Server应用如何记录WebSocket Circuit消息为JSON格式到服务端控制台

实现Blazor Server Circuit消息JSON格式日志的方案

可以实现,不需要自定义WebSocket中间件,直接通过Blazor内置的CircuitHandler钩子 + 调整SignalR序列化配置即可完成需求。


步骤1:调整配置(可选,按需选择)

Blazor Server底层基于SignalR实现通信,默认使用MessagePack序列化传输消息,如果你不需要修改实际传输格式,仅需要日志输出为JSON,可以跳过这一步,直接在日志逻辑里做一次MessagePack转JSON即可。
如果希望传输本身也使用JSON格式,直接在Program.cs中修改SignalR配置:

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        // 替换默认MessagePack序列化器为JSON序列化器
        options.Serializer = new JsonHubProtocol();
    });

步骤2:实现自定义CircuitHandler拦截消息

Blazor官方提供了CircuitHandler抽象类,专门用于监听Circuit生命周期、消息收发事件,无需手动hook底层WebSocket连接:

public class LoggingCircuitHandler : CircuitHandler
{
    private readonly ILogger<LoggingCircuitHandler> _logger;

    public LoggingCircuitHandler(ILogger<LoggingCircuitHandler> logger)
    {
        _logger = logger;
        // 设置最高优先级,确保消息先被当前处理器拦截
        Order = int.MaxValue;
    }

    // 记录服务端发往客户端的消息
    public override Task OnSendMessageAsync(Circuit circuit, string messageId, string messageType, object[] args, CancellationToken cancellationToken)
    {
        var logContent = JsonSerializer.Serialize(new
        {
            CircuitId = circuit.Id,
            Direction = "Server->Client",
            MessageId = messageId,
            MessageType = messageType,
            Payload = args
        }, new JsonSerializerOptions { WriteIndented = true });
        _logger.LogInformation("Circuit消息:\n{LogContent}", logContent);
        return base.OnSendMessageAsync(circuit, messageId, messageType, args, cancellationToken);
    }

    // 记录客户端发往服务端的消息
    public override Task OnInvokeAsync(Circuit circuit, string invocationId, string methodName, object[] args, CancellationToken cancellationToken)
    {
        var logContent = JsonSerializer.Serialize(new
        {
            CircuitId = circuit.Id,
            Direction = "Client->Server",
            InvocationId = invocationId,
            MethodName = methodName,
            Payload = args
        }, new JsonSerializerOptions { WriteIndented = true });
        _logger.LogInformation("Circuit消息:\n{LogContent}", logContent);
        return base.OnInvokeAsync(circuit, invocationId, methodName, args, cancellationToken);
    }

    // 可选:记录Circuit连接/断开事件
    public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Circuit {CircuitId} 已建立连接", circuit.Id);
        return base.OnConnectionUpAsync(circuit, cancellationToken);
    }

    public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Circuit {CircuitId} 已断开连接", circuit.Id);
        return base.OnConnectionDownAsync(circuit, cancellationToken);
    }
}

步骤3:注册服务到依赖注入容器

在Program.cs中添加自定义处理器的注册即可生效:

builder.Services.AddSingleton<CircuitHandler, LoggingCircuitHandler>();

注意事项

  • 生产环境建议关闭全量消息日志,避免占用过多IO资源、泄露用户敏感操作信息
  • 保留msgpack传输仅日志转JSON的场景下,直接在日志方法中添加MessagePack反序列化为对象再转JSON的逻辑即可,不影响传输性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:15:04