ASP.NET Core SignalR 中的日志记录和诊断信息

作者:Andrew Stanton-Nurse

本文提供从 ASP.NET Core SignalR 应用收集诊断信息以帮助解决问题的指南。

服务器端日志记录

警告

服务器端日志可能包含来自应用的敏感信息。 切勿将来自生产应用的原始日志发布到 GitHub 等公共论坛。

SignalR 是 ASP.NET Core 的一部分,因此它使用 ASP.NET Core 日志记录系统。 在默认配置中,SignalR 只记录很少的信息,但这可以进行配置。 有关配置 ASP.NET Core 日志记录的详细信息,请参阅 ASP.NET Core 日志记录上的文档。

SignalR 使用两个记录器类别:

  • Microsoft.AspNetCore.SignalR:用于与中心协议、激活中心、调用方法和其他与中心相关活动的日志。
  • Microsoft.AspNetCore.Http.Connections:用于与传输相关的日志,例如 WebSocket、长轮询、服务器发送的事件以及低级 SignalR 基础结构。

若要启用来自 SignalR 的详细日志,请通过在 LoggingLogLevel 子节中添加以下项目,在 appsettings.json 文件中将上述的两个前缀配置为 Debug 级别:

{
    "Logging": {
        "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information",
            "Microsoft.AspNetCore.SignalR": "Debug",
            "Microsoft.AspNetCore.Http.Connections": "Debug"
        }
    }
}

还可以在 CreateWebHostBuilder 方法中通过代码配置此项:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
            logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
        })
        .UseStartup<Startup>();

如果未使用基于 JSON 的配置,请在配置系统中设置以下配置值:

  • Logging:LogLevel:Microsoft.AspNetCore.SignalR = Debug
  • Logging:LogLevel:Microsoft.AspNetCore.Http.Connections = Debug

查看配置系统的文档以确定如何指定嵌套的配置值。 例如,使用环境变量时,使用两个 _ 而不是 : 字符(例如 Logging__LogLevel__Microsoft.AspNetCore.SignalR)。

建议在为应用收集更详细的诊断时使用 Debug 级别。 Trace 级别产生的诊断级别很低,且很少需要它来诊断应用中的问题。

访问服务器端日志

访问服务器端日志的方式取决于在其中运行的环境。

作为 IIS 外部的控制台应用

如果在控制台应用中运行,则默认情况下应启用控制台记录器。 SignalR 日志将显示在控制台中。

在 Visual Studio 的 IIS Express 中

Visual Studio 在“输出”窗口中显示日志输出。 选择“ASP.NET Core Web 服务器”下拉选项。

Azure 应用服务

在 Azure 应用服务门户的“诊断日志”部分中启用“应用程序日志记录(Filesystem)”选项,并将级别配置为 Verbose。 日志应可从日志流式处理服务和应用服务文件系统的日志中获取。 有关详细信息,请参阅 Azure 日志流式处理

其他环境

如果将应用部署到另一个环境(例如 Docker、Kubernetes 或 Windows 服务),请参阅 .NET Core 和 ASP.NET Core 中的日志记录,了解有关如何配置适用于环境的日志记录提供程序的详细信息。

JavaScript 客户端日志记录

警告

客户端日志可能包含来自应用的敏感信息。 切勿将来自生产应用的原始日志发布到 GitHub 等公共论坛。

使用 JavaScript 客户端时,可以使用 HubConnectionBuilder 上的 configureLogging 方法配置日志记录选项:

let connection = new signalR.HubConnectionBuilder()
    .withUrl("/my/hub/url")
    .configureLogging(signalR.LogLevel.Debug)
    .build();

若要禁用框架日志记录,请在 configureLogging 方法中指定 signalR.LogLevel.None。 请注意,某些日志记录由浏览器直接发出,无法通过设置日志级别禁用。

下表显示了可用于 JavaScript 客户端的日志级别。 将日志级别设置为其中一个值,便可以在该表的该级别及其以上所有级别进行日志记录。

Level 说明
None 不记录任何消息。
Critical 指示整个应用失败的消息。
Error 指示当前操作失败的消息。
Warning 指示非严重问题的消息。
Information 信息性消息。
Debug 对调试有帮助的诊断消息。
Trace 用于诊断特定问题的非常详细的诊断消息。

配置详细程度后,日志将写入浏览器控制台(或 NodeJS 应用中的标准输出)。

如果要将日志发送到自定义日志记录系统,可以提供实现 ILogger 接口的 JavaScript 对象。 唯一需要实现的方法是 log,它采用事件的级别和与事件关联的消息。 例如:

import { ILogger, LogLevel, HubConnectionBuilder } from "@microsoft/signalr";

export class MyLogger implements ILogger {
    log(logLevel: LogLevel, message: string) {
        // Use `message` and `logLevel` to record the log message to your own system
    }
}

// later on, when configuring your connection...

let connection = new HubConnectionBuilder()
    .withUrl("/my/hub/url")
    .configureLogging(new MyLogger())
    .build();
import { ILogger, LogLevel, HubConnectionBuilder } from "@aspnet/signalr";

export class MyLogger implements ILogger {
    log(logLevel: LogLevel, message: string) {
        // Use `message` and `logLevel` to record the log message to your own system
    }
}

// later on, when configuring your connection...

let connection = new HubConnectionBuilder()
    .withUrl("/my/hub/url")
    .configureLogging(new MyLogger())
    .build();

.NET 客户端日志记录

警告

客户端日志可能包含来自应用的敏感信息。 切勿将来自生产应用的原始日志发布到 GitHub 等公共论坛。

若要从 .NET 客户端获取日志,可以对 HubConnectionBuilder 使用 ConfigureLogging 方法。 其工作方式与对 WebHostBuilderHostBuilder 使用 ConfigureLogging 方法相同。 可以配置与在 ASP.NET Core 中使用的相同日志记录提供程序。 但是,必须为单个日志记录提供程序手动安装和启用 NuGet 包。

若要将 .NET 客户端日志记录添加到 Blazor WebAssembly 应用,请参阅 ASP.NET Core Blazor 日志记录

控制台日志记录

若要启用控制台日志记录,请添加 包。 然后,使用 AddConsole 方法配置控制台记录器:

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/my/hub/url")
    .ConfigureLogging(logging =>
    {
        // Log to the Console
        logging.AddConsole();

        // This will set ALL logging to Debug level
        logging.SetMinimumLevel(LogLevel.Debug);
    })
    .Build();

调试输出窗口日志记录

还可以将日志配置为转到 Visual Studio 中的“输出”窗口。 安装 Microsoft.Extensions.Logging.Debug 包并使用 AddDebug 方法:

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/my/hub/url")
    .ConfigureLogging(logging =>
    {
        // Log to the Output Window
        logging.AddDebug();

        // This will set ALL logging to Debug level
        logging.SetMinimumLevel(LogLevel.Debug)
    })
    .Build();

其他日志记录提供程序

SignalR 支持其他日志记录提供程序,例如 Serilog、Seq、NLog 或与 Microsoft.Extensions.Logging 集成的任何其他日志记录系统。 如果日志记录系统提供 ILoggerProvider,可以使用 AddProvider 注册它:

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/my/hub/url")
    .ConfigureLogging(logging =>
    {
        // Log to your custom provider
        logging.AddProvider(new MyCustomLoggingProvider());

        // This will set ALL logging to Debug level
        logging.SetMinimumLevel(LogLevel.Debug)
    })
    .Build();

控制详细程度

如果从应用的其他位置进行日志记录,将默认级别更改为 Debug 可能过于详细。 可以使用筛选器来配置 SignalR 日志的日志记录级别。 这可以通过代码完成,其方式与在服务器上相同:

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/my/hub/url")
    .ConfigureLogging(logging =>
    {
        // Register your providers

        // Set the default log level to Information, but to Debug for SignalR-related loggers.
        logging.SetMinimumLevel(LogLevel.Information);
        logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
        logging.AddFilter("Microsoft.AspNetCore.Http.Connections", LogLevel.Debug);
    })
    .Build();

网络跟踪

警告

网络跟踪包含应用发送的每条消息的全部内容。 切勿将来自生产应用的原始网络跟踪发布到 GitHub 等公共论坛。

如果遇到问题,网络跟踪有时可以提供大量有用的信息。 如果要在问题跟踪器上提交问题,这非常有用。

使用 Fiddler 收集网络跟踪(首选选项)

此方法适用于所有应用程序。

Fiddler 是一种功能强大的工具,用于收集 HTTP 跟踪。 从 telerik.com/fiddler 安装并启动该工具,然后运行你的应用程序,重现此问题。 Fiddler 适用于 Windows,并且提供适用于 macOS 和 Linux 的 beta 版本。

如果使用 HTTPS 进行连接,则需执行一些额外的步骤来确保 Fiddler 可以解密 HTTPS 流量。 有关详细信息,请参阅 Fiddler 文档

收集了跟踪后,可以通过从菜单栏中选择“文件”>“保存”>“所有会话”来导出跟踪。

从 Fiddler 导出所有会话

使用 tcpdump 收集网络跟踪(仅限 macOS 和 Linux)

此方法适用于所有应用程序。

可以使用 tcpdump 收集原始 TCP 跟踪,具体方法是在命令行界面中运行以下命令。 如果出现权限错误,你可能需要 root 权限或为命令添加前缀 sudo

tcpdump -i [interface] -w trace.pcap

[interface] 替换为要捕获的网络接口。 通常,这类似于 /dev/eth0(对于标准以太网接口)或 /dev/lo0(对于 localhost 流量)。 有关详细信息,请参阅主机系统上的 tcpdump 手册页。

在浏览器中收集网络跟踪

此方法仅适用于基于浏览器的应用。

大多数浏览器开发人员工具控制台都有一个“网络”选项卡,可用于捕获浏览器和服务器之间的网络活动。 但是,这些跟踪不包括 WebSocket 和服务器发送的事件消息。 如果使用这些传输方式,使用 Fiddler 或 TcpDump(下文所述)等工具是一种更好的方法。

Microsoft Edge 和 Internet Explorer

(适用于 Microsoft Edge 和 Internet Explorer 的说明是相同的)

  1. 按 F12 打开开发工具
  2. 单击“网络”选项卡
  3. 如果需要,请刷新页面,并重现此问题
  4. 单击工具栏中的“保存”图标,将跟踪导出为“HAR”文件:

Microsoft Edge 开发人员工具“网络”选项卡上的“保存”图标

Google Chrome

  1. 按 F12 打开开发工具
  2. 单击“网络”选项卡
  3. 如果需要,请刷新页面,并重现此问题
  4. 右键单击请求列表中的任意位置,然后选择“另存为带内容的 HAR”:

Google Chrome 开发人员工具“网络”选项卡上的“另存为包含内容的 HAR”选项

Mozilla Firefox

  1. 按 F12 打开开发工具
  2. 单击“网络”选项卡
  3. 如果需要,请刷新页面,并重现此问题
  4. 右键单击请求列表中的任意位置,然后选择“全部保存为 HAR”

Mozilla Firefox 开发人员工具“网络”选项卡上的“全部另存为 HAR”选项

将诊断文件附加到 GitHub 问题

可以通过重命名诊断文件来将其附加到 GitHub 问题,以便它们具有 .txt 扩展名,然后将它们拖放到问题上。

注意

请不要将日志文件或网络跟踪的内容粘贴到 GitHub 问题。 这些日志和跟踪可能非常大,并且 GitHub 通常会截断它们。

将日志文件拖放到 GitHub 问题上

指标

指标是一段时间的数据度量值的表示形式。 例如每秒的请求数。 使用指标数据可以在高级别观察应用的状态。 .NET gRPC 指标是使用 EventCounter 发出的。

SignalR 服务器指标

SignalR 服务器指标在 Microsoft.AspNetCore.Http.Connections 事件源上报告。

名称 说明
connections-started 已启动的连接总数
connections-stopped 已停止的连接总数
connections-timed-out 已超时的连接总数
current-connections 当前连接数
connections-duration 平均连接持续时间

观察指标

dotnet-counters 是一个性能监视工具,用于临时运行状况监视和初级性能调查。 使用 Microsoft.AspNetCore.Http.Connections 作为提供程序名称监视 .NET 应用。 例如:

> dotnet-counters monitor --process-id 37016 Microsoft.AspNetCore.Http.Connections

Press p to pause, r to resume, q to quit.
    Status: Running
[Microsoft.AspNetCore.Http.Connections]
    Average Connection Duration (ms)       16,040.56
    Current Connections                         1
    Total Connections Started                   8
    Total Connections Stopped                   7
    Total Connections Timed Out                 0

其他资源