共用方式為


ASP.NET Core SignalR 中的記錄和診斷

作者:Andrew Stanton-Nurse

本文提供從 ASP.NET Core SignalR 應用程式收集診斷的指引,以協助針對問題進行疑難排解。

伺服器端記錄

Warning

伺服器端記錄可能包含來自您應用程式的敏感性資訊。 切勿將原始記錄從實際執行應用程式張貼至 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 的詳細日誌,請將下列項目新增至 Debug 檔案中 appsettings.json 的子區段,並將上述兩個前置詞設定至 LogLevel 層級:

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

可以在 SignalR 方法內的程式碼中設定記錄器類別的 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 App Service

在 Azure App Service 入口網站的 [診斷記錄] 區段中啟用 [應用程式記錄 (檔案系統)] 選項,並將 [層級] 設定為 Verbose。 記錄應該可從 [記錄串流] 服務取得,以及在 App Service 檔案系統上的記錄中取得。 如需詳細資訊,請參閱 Azure 記錄串流

其他環境

如需設定適用於不同部署環境之記錄提供者的詳細資訊,例如 Docker、Kubernetes 或 Windows 服務,請參閱 在 .NET 中記錄和 ASP.NET Core

JavaScript 用戶端記錄

Warning

用戶端記錄可能包含來自您應用程式的敏感性資訊。 切勿將原始記錄從實際執行應用程式張貼至 GitHub 等公共論壇。

使用 JavaScript 用戶端時,您可以使用 configureLogging 上的 HubConnectionBuilder 方法來設定記錄選項:

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

指定 signalR.LogLevel.None 在方法configureLogging中停用架構日誌。 請注意,某些記錄是由瀏覽器直接發出,而且無法透過設定記錄層級來停用。

下表顯示 JavaScript 用戶端可用的記錄層級。 將記錄層級設定為下列其中一個值,可在該層級和資料表中高於該層級的所有層級啟用記錄。

Level Description
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 用戶端記錄

Warning

用戶端記錄可能包含來自您應用程式的敏感性資訊。 切勿將原始記錄從實際執行應用程式張貼至 GitHub 等公共論壇。

若要從 .NET 用戶端取得記錄,您可以在 ConfigureLogging 上使用 HubConnectionBuilder 方法。 其運作方式與 ConfigureLoggingWebHostBuilder 上的 HostBuilder 方法相同。 您可以設定您在 ASP.NET Core 中使用的相同記錄提供者。 不過,您必須針對個別記錄提供者手動安裝並啟用 NuGet 套件。

若要將 .NET 用戶端記錄新增至 Blazor WebAssembly 應用程式,請參閱 ASP.NET Core Blazor 記錄

控制台日誌記錄

為了啟用主控台記錄,請新增 Microsoft.Extensions.Logging.Console 套件。 然後,使用 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();

在SignalR中的追蹤

SignalR樞紐伺服器和SignalR用戶端會透過SignalR和DiagnosticSource提供有關連線及訊息的資訊Activity。 SignalR 的 ActivitySource 適用於中樞伺服器和用戶端,從 .NET 9 開始提供。

ActivitySource 是一種元件,用於分散式追蹤,用來建立和管理代表應用程式中作業的活動(或範圍)。 這些活動可用來:

  • 追蹤跨不同元件和服務的要求和作業流程。
  • 提供您應用程式效能和行為的寶貴見解。

.NET SignalR 伺服器活動來源

名為 SignalR 的 Microsoft.AspNetCore.SignalR.Server ActivitySource 會發出中樞方法呼叫事件:

  • 每個方法都是它自己的活動,因此在中樞方法呼叫期間發出活動的任何活動都位於中樞方法活動之下。
  • 中樞方法活動無父系。 這意味著它們不會被包含在已長時間運行的 SignalR 連線中。

下列範例使用 Aspire 儀表板OpenTelemetry 套件:

<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />

將下列啟動程式碼新增至 Program.cs 檔案:

using OpenTelemetry.Trace;
using SignalRChat.Hubs;

// Set OTEL_EXPORTER_OTLP_ENDPOINT environment variable depending on where your OTEL endpoint is.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        if (builder.Environment.IsDevelopment())
        {
            // View all traces only in development environment.
            tracing.SetSampler(new AlwaysOnSampler());
        }

        tracing.AddAspNetCoreInstrumentation();
        tracing.AddSource("Microsoft.AspNetCore.SignalR.Server");
    });

builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());

var app = builder.Build();

以下是來自 Aspire 主控台的範例輸出:

集線器方法呼叫事件的活動清單SignalR

ASP.NET Core 也會在事件來源上 Microsoft.AspNetCore.Hosting 提供自己的度量標準。

.NET SignalR 客戶端 ActivitySource

擁有 SignalRActivitySource 名稱的 Microsoft.AspNetCore.SignalR.Client 為 SignalR 用戶端發出事件:

  • 集線器呼叫會創建客戶端範圍。 其他 SignalR 用戶端,例如 JavaScript 用戶端,不支持追蹤。 在未來版本中,此功能將會新增至更多用戶端。
  • 用戶端與伺服器上的中樞調用支援 上下文傳播。 傳遞追蹤上下文可啟用真正的分散式追蹤。 現在可以看到從用戶端到伺服器的調用流程以及返回的過程。

以下是這些新活動在 Aspire 儀表板上的呈現方式:

SignalR 儀表板中的 Aspire 分散式追蹤

網路追蹤

Warning

網路追蹤包含應用程式所傳送的每則訊息完整內容。 切勿將原始網路追蹤從實際執行應用程式張貼至 GitHub 等公共論壇。

如果您遇到問題,網路追蹤有時會提供寶貴的資訊。 這在提交問題至我們的問題追蹤器時特別有用。

使用 Fiddler 收集網路追蹤 (慣用選項)

這個方法適用於所有檔案。

Fiddler 是收集 HTTP 追蹤的強大工具。 從 telerik.com/fiddler 安裝 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 開發工具網路索引標籤上的 [儲存] 圖示

谷歌瀏覽器

  1. 按 F12 開啟開發人員工具
  2. 選取 [網路] 標籤
  3. 重新整理頁面 (如有需要) 並重現問題
  4. 以滑鼠右鍵按一下要求清單中的任意位置,然後選擇 [另存為含內容的 HAR]:

Google Chrome 開發工具網路索引標籤中的 [內容儲存為 HAR] 選項

Mozilla 火狐瀏覽器

  1. 按 F12 開啟開發人員工具
  2. 選取 [網路] 標籤
  3. 重新整理頁面 (如有需要) 並重現問題
  4. 以滑鼠右鍵按一下要求清單中的任何位置,然後選擇 [全部儲存為 HAR]

Mozilla Firefox 開發工具網路索引標籤中的 [全部儲存為 HAR] 選項

將診斷檔案附加至 GitHub 問題

診斷檔案可以將其重新命名為擁有 .txt 副檔名,然後拖放到 GitHub 的問題頁面上。

Note

請不要將記錄檔或網路追蹤的內容貼入 GitHub 問題中。 這些記錄和追蹤記錄可能很大,而 GitHub 通常會截斷它們。

將記錄檔案拖曳至 GitHub 問題

Metrics

計量是數據量值在時間間隔中的表示法。 例如,每秒要求數。 計量資料允許在高層級觀察應用程式的狀態。 .NET gRPC 計量是使用 EventCounter 發出的。

SignalR 伺服器計量

SignalR 伺服器計量會在 Microsoft.AspNetCore.Http.Connections 事件來源上報告。

Name Description
connections-started 已啟動的連線總數
connections-stopped 已停止的連線總數
connections-timed-out 逾時連線總數
current-connections 目前的連線
connections-duration 平均連線持續時間

觀察指標

dotnet-counters 是效能監控工具,適用於特定的狀況監控和第一層級效能調查。 使用 Microsoft.AspNetCore.Http.Connections 作為提供者名稱來監視 .NET 應用程式。 例如:

> dotnet-counters monitor --process-id 37016 --counters 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

其他資源