ASP.NET Core 指標

度量是隨時間報告的數值測量。 利用它們來監控應用程式的健康狀況並產生警示。 例如,Web 服務可能會追蹤以下計量:

  • 每秒收到的請求數。
  • 回應只需毫秒。
  • 它傳送的回應有誤。

定期向監控系統回報這些指標。 設定儀表板來檢視指標,並建立警示,以便在發生問題時通知相關人員。 如果 Web 服務預期在 400 毫秒內回應要求,但在 600 毫秒內開始回應,則監視系統可以通知作業人員應用程式回應速度比正常慢。

所有工具及其屬性的完整清單,皆在 ASP.NET Core 內建指標中描述。

使用計量

使用計量牽涉到下列事項:

  • 檢測:.NET 程式庫中的程式碼會採用度量,並將這些度量與計量名稱產生關聯。 .NET 和 ASP.NET Core 包含許多內建計量。
  • 收集和儲存:.NET 應用程式會設定要從應用程式傳輸的命名指標,以進行外部儲存和分析。 有些工具可能會透過設定檔或介面工具,在應用程式外進行設定。
  • 可視化: 工具,可顯示人類可讀取格式的計量。 例如 ,GrafanaPrometheus
  • 提醒: 當計量超過閾值時提供通知的工具。 例如,如果 Web 服務的平均響應時間超過 400 毫秒,可以將警示傳送給作業人員。
  • 分析: 一種工具,可以隨時間分析指標。 這個工具通常是基於網頁的儀表板,可以自訂以顯示特定應用程式最重要的指標。

儀器化程式碼可以記錄數值測量,但要建立有用的監控指標,你需要彙整、傳輸並儲存這些測量數據。 匯總、傳輸和儲存數據的程序稱為收集。 本教學課程示範收集及顯示計量的數個範例:

你也可以將測量值與稱為標籤的鍵值對關聯,方便你將資料分類分析。 如需詳細資訊,請參閱多維度計量

建立入門應用程式

使用下列命令來建立新的 ASP.NET Core 應用程式:

dotnet new web -o WebMetric
cd WebMetric
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore --prerelease
dotnet add package OpenTelemetry.Extensions.Hosting

Program.cs 的內容替換為以下代碼:

using OpenTelemetry.Metrics;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry()
    .WithMetrics(builder =>
    {
        builder.AddPrometheusExporter();

        builder.AddMeter("Microsoft.AspNetCore.Hosting",
                         "Microsoft.AspNetCore.Server.Kestrel");
        builder.AddView("http.server.request.duration",
            new ExplicitBucketHistogramConfiguration
            {
                Boundaries = new double[] { 0, 0.005, 0.01, 0.025, 0.05,
                       0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 }
            });
    });
var app = builder.Build();

app.MapPrometheusScrapingEndpoint();

app.MapGet("/", () => "Hello OpenTelemetry! ticks:"
                     + DateTime.Now.Ticks.ToString()[^3..]);

app.Run();

使用 dotnet-counters 來檢視計量指標

dotnet-counters 是命令行工具,可視需要檢視 .NET 應用程式的即時計量。 它不需要設定,因此適合用於臨機作調查,或驗證計量檢測是否正常運作。 它適用於基於 System.Diagnostics.Metrics 的 API 和 EventCounters

如果未安裝 dotnet-counters 工具,請執行下列命令:

dotnet tool update -g dotnet-counters

測試應用程式執行中時,啟動 dotnet-counters。 下列命令顯示的 dotnet-counters 範例會監視來自 Microsoft.AspNetCore.Hosting 計量的所有計量。

dotnet-counters monitor -n WebMetric --counters Microsoft.AspNetCore.Hosting

會顯示類似下列的輸出:

Press p to pause, r to resume, q to quit.
    Status: Running

[Microsoft.AspNetCore.Hosting]
    http-server-current-requests
        host=localhost,method=GET,port=5045,scheme=http                    0
    http-server-request-duration (s)
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0.001
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0
        host=localhost,method=GET,port=5045,protocol=HTTP/1.1,ro           0

如需詳細資訊,請參閱 dotnet-counters

強化 ASP.NET Core 請求計量

ASP.NET Core 有許多內建計量。 http.server.request.duration 計量:

  • 記錄伺服器上的 HTTP 要求持續時間。
  • 擷取標記中的要求資訊,例如相符的路由和回應狀態碼。

http.server.request.duration 指標支援使用 IHttpMetricsTagsFeature 進行標記擴充。 擴充是程式庫或應用程式將自己的標記新增至計量時。 如果應用程式想為以指標建立的儀表板或警示新增自訂分類,此功能非常有用。

using Microsoft.AspNetCore.Http.Features;

var builder = WebApplication.CreateBuilder();
var app = builder.Build();

app.Use(async (context, next) =>
{
    var tagsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (tagsFeature != null)
    {
        var source = context.Request.Query["utm_medium"].ToString() switch
        {
            "" => "none",
            "social" => "social",
            "email" => "email",
            "organic" => "organic",
            _ => "other"
        };
        tagsFeature.Tags.Add(new KeyValuePair<string, object?>("mkt_medium", source));
    }

    await next.Invoke();
});

app.MapGet("/", () => "Hello World!");

app.Run();

上述範例:

  • 新增中介軟體以豐富 ASP.NET Core 請求指標。
  • IHttpMetricsTagsFeature 取得 HttpContext。 這個功能只有在有人在聆聽指標時才會出現在上下文中。 使用前,請先確認 IHttpMetricsTagsFeature 不是 null
  • 將包含要求行銷來源的自訂標記新增至 http.server.request.duration 計量。
    • 標記具有名稱 mkt_medium,其值基於 utm_medium 查詢字串的值。 utm_medium 值會解析為已知的值範圍。
    • 標記會允許依行銷媒體類型分類要求,這在分析 Web 應用程式流量時會很有用。

備註

使用自訂標記擴充時,請遵循多維度計量最佳做法。 太多或具有未系結範圍的標記會建立許多標籤組合,進而產生高維度。 收集工具對計數器支援的維度有限制,並可能過濾結果以防止過度使用記憶體。

針對特定端點和請求停用 HTTP 指標

對於經常被自動化系統呼叫的端點(例如健康檢查),選擇不紀錄計量資料可帶來益處。 通常不需要為這些要求記錄指標。 不必要的遙測會耗用資源來進行收集和儲存,並且可能會扭曲遙測儀錶板中顯示的結果。

你可以加入中繼資料,使用 DisableHttpMetrics 屬性或 DisableHttpMetrics 方法,將傳送至端點的 HTTP 要求排除在計量之外:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();

另外,新增了 IHttpMetricsTagsFeature.MetricsDisabled 屬性,用於:

  • 進階情境中,當請求不對應至任何端點時。
  • 動態停用特定 HTTP 要求的計量集合。
// Middleware that conditionally opts-out HTTP requests.
app.Use(async (context, next) =>
{
    var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (metricsFeature != null &&
        context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        metricsFeature.MetricsDisabled = true;
    }

    await next(context);
});

建立自訂計量

你可以透過在命名空間中使用 API System.Diagnostics.Metrics 來建立指標。 相關資訊請參見 「建立自訂指標」。

使用 IMeterFactory 在 ASP.NET Core 應用程式中建立計量

在 ASP.NET Core 應用程式中建立Meter實例,使用 IMeterFactory

依預設,ASP.NET Core 會在相依性插入 (DI) 中註冊 IMeterFactory。 計量工廠將計量與 DI 整合,使隔離和收集計量變得簡單。 IMeterFactory 特別適合用於測試。 它允許多個測試並排執行,且只收集在測試中記錄的指標值。

若要在應用程式中使用 IMeterFactory,請建立使用 IMeterFactory 來建立應用程式自訂計量的型別:

public class ContosoMetrics
{
    private readonly Counter<int> _productSoldCounter;

    public ContosoMetrics(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("Contoso.Web");
        _productSoldCounter = meter.CreateCounter<int>("contoso.product.sold");
    }

    public void ProductSold(string productName, int quantity)
    {
        _productSoldCounter.Add(quantity,
            new KeyValuePair<string, object?>("contoso.product.name", productName));
    }
}

Program.cs 中向 DI 註冊計量型別:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ContosoMetrics>();

視需要插入計量類型和記錄值。 由於度量型別在 DI 中註冊,因此可用於 MVC 控制器、最小 API,或任何由 DI 建立的類型:

app.MapPost("/complete-sale", (SaleModel model, ContosoMetrics metrics) =>
{
    // ... business logic such as saving the sale to a database ...

    metrics.ProductSold(model.ProductName, model.QuantitySold);
});

若要監視 "Contoso.Web" 計量,請使用下列 dotnet-counters 命令。

dotnet-counters monitor -n WebMetric --counters Contoso.Web

會顯示類似下列的輸出:

Press p to pause, r to resume, q to quit.
    Status: Running

[Contoso.Web]
    contoso.product.sold (Count / 1 sec)
        contoso.product.name=Eggs            12    
        contoso.product.name=Milk            0    

使用 OpenTelemetry 和 Prometheus 檢視 Grafana 中的計量

Overview

OpenTelemetry:

  • 這是 Cloud Native Computing Foundation 所支援的廠商中性開放原始碼專案。
  • 標準化為雲端原生軟體產生和收集遙測資料。
  • 使用 .NET 計量 API 進行操作。
  • Azure 監視器 和許多 APM(應用程式效能管理)廠商支持。

自 ASP.NET Core 11 起,框架內建的 HTTP 伺服器度量與追蹤符符符合 OpenTelemetry HTTP 伺服器語意慣例的必要部分。 HTTP 伺服器請求活動預設會發出這些屬性,與內建的指標相符。 因此, OpenTelemetry.Instrumentation.AspNetCore NuGet 套件在收集 HTTP 伺服器指標與追蹤時是可選的。 本文範例僅使用內建的電表(Microsoft.AspNetCore.HostingMicrosoft.AspNetCore.Server.Kestrel),並未參考儀器套件。 關於內建工具及其屬性的清單,請參見 ASP.NET Core 內建 HTTP 指標

雖然此套件是選配項目,但它並不是內建檢測機制的可直接替換等效項。 內建的儀器僅涵蓋語意慣例 所需的 部分。 在取出包裝前,請考慮以下差異:

  • 某些 推薦 的 HTTP 伺服器屬性並非由內建儀器所產生,例如某些用戶端與網路屬性(例如 client.address)。 對 條件要求url.query 屬性(包括遮蔽)的完整支援仍在進行中。 如果你需要依賴這些屬性,請保留這個套件。 更多資訊請參見 dotnet/aspnetcore#65873
  • 此套件也可讓您輕鬆啟用 HTTP 伺服器以外的遙測,包括 Blazor 和 SignalR。 在追蹤時,它會登錄額外的活動來源(SignalRMicrosoft.AspNetCore.SignalR.Server在 .NET 9 及以後版本)和 Blazor (Microsoft.AspNetCore.ComponentsMicrosoft.AspNetCore.Components.Server.Circuits在 .NET 10 及以後版本)。 對於度量,它啟用了相關的內建計量器(例如 Microsoft.AspNetCore.Components)。 沒有套件的話,將來源 AddSource 和儀表都註冊給 AddMeter 自己,這樣就能收集相同的遙測數據。

當你在只需要 HTTP 伺服器指標和追蹤的應用程式中加入遙測時,你可以依賴內建的儀器,省略這個套件。 當您將已參考該套件的現有應用程式從 .NET 10 升級至 .NET 11 時,如果您相依於前述清單中所述的屬性、來源或計量器,請保留該套件。 移除該套件會在無任何提示的情況下遺失該遙測資料。

重要

當你啟用 OpenTelemetry 追蹤 (除了指標外)而不使用 OpenTelemetry.Instrumentation.AspNetCore 套件時,請註冊框架的 HTTP 伺服器 ActivitySource ,以便記錄請求活動。 ASP.NET Core 的 HTTP 伺服器活動來源名為 Microsoft.AspNetCore,而且該架構會為每個要求建立一個名為 Microsoft.AspNetCore.Hosting.HttpRequestIn 的請求活動,以傳播追蹤上下文。 如果 Microsoft.AspNetCore 來源沒有在 OpenTelemetry SDK 註冊,請求活動就不會被記錄,預設 ParentBased 取樣器會靜默地丟棄請求期間開始的自訂子區段。

在現有的追蹤流程中,明確註冊來源:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Microsoft.AspNetCore")
        .AddSource("MyApp"));

在前述範例中:

  • AddSource("Microsoft.AspNetCore")註冊 ASP.NET Core 的 HTTP 伺服器活動來源,以便記錄請求活動。
  • AddSource("MyApp") 註冊應用程式自己的 ActivitySource。 用你應用程式使用的名稱來取代 MyApp
  • 沒有顯示出口商。 這個例子假設你的追蹤管線中已經設定了匯出器。

或者,從AddAspNetCoreInstrumentation()OpenTelemetry.Instrumentation.AspNetCore套件呼叫,套件會幫你註冊來源。

本教程展示如何使用 OSS PrometheusGrafana 專案來整合 OpenTelemetry 度量。 計量數據流:

  1. ASP.NET Core 計量 API 會記錄來自範例應用程式的度量。

  2. 在應用程式中執行的 OpenTelemetry .NET 程式庫會彙總度量。

  3. Prometheus 匯出工具程式庫會透過 HTTP 計量端點提供經彙總的資料。 'Exporter' 是 OpenTelemetry 中用來將遙測數據傳輸到廠商特定後端的程式庫。

  4. Prometheus 伺服器:

    • 輪詢指標端點。
    • 讀取資料。
    • 將數據儲存在資料庫中以供長期保存。 Prometheus 是指將數據讀取和儲存為 擷取 端點。
    • 可以在不同的電腦上執行。
  5. Grafana 伺服器:

    • 查詢儲存在 Prometheus 中的資料,並將其顯示在 Web 型監視儀表板上。
    • 可以在不同的電腦上執行。

從範例應用程式檢視計量

去試用版應用程式看看。 瀏覽器會顯示Hello OpenTelemetry! ticks:<3digits>目前 DateTime.Ticks 的最後三位數字在哪裡3digits

附加 /metrics 至 URL 以檢視計量端點。 瀏覽器會顯示正在收集的計量:

計量指標 2

設置和配置 Prometheus

遵循 Prometheus first steps (英文) 來設定 Prometheus 伺服器,並確認其正常運作。

修改 prometheus.yml 設定檔,讓 Prometheus 抓取範例應用程式所暴露的指標端點。 在 scrape_configs 區段中新增下列反白顯示的文字:

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  - job_name: 'MyASPNETApp'
    scrape_interval: 5s # Poll every 5 seconds for a more responsive demo.
    static_configs:
      - targets: ["localhost:5045"]  ## Enter the HTTP port number of the demo app.

在前面反白顯示的 YAML 中,請將 5045 替換為範例應用程式所使用的埠號。

啟動 Prometheus

  1. 重載設定或重新啟動 Prometheus 伺服器。
  2. 確認 OpenTelemetryTest 在 Prometheus 入口網站的 [ 狀態>目標 ] 頁面中處於 UP 狀態。

Prometheus 狀態

選取 [開啟計量總管] 圖示以查看可用的計量:

普羅米修斯open_metric_exp

運算式 輸入方塊中輸入計數器類別,例如 http_,即可查看可用的計量:

可用指標

或者,在 運算式 輸入框中輸入計數器類別(例如 kestrel),以查看可用的指標:

普羅米修斯紅隼

在 Grafana 儀錶板上顯示計量

dashboard-screenshot2

在 ASP.NET Core 應用程式中測試指標

你可以在 ASP.NET Core 應用程式中測試指標。 其中一種方法是在 ASP.NET Core 整合測試中收集並斷言度量值,方法是使用 MetricCollector<T>

public class BasicTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;
    public BasicTests(WebApplicationFactory<Program> factory) => _factory = factory;

    [Fact]
    public async Task Get_RequestCounterIncreased()
    {
        // Arrange
        var client = _factory.CreateClient();
        var meterFactory = _factory.Services.GetRequiredService<IMeterFactory>();
        var collector = new MetricCollector<double>(meterFactory,
            "Microsoft.AspNetCore.Hosting", "http.server.request.duration");

        // Act
        var response = await client.GetAsync("/");

        // Assert
        Assert.Contains("Hello OpenTelemetry!", await response.Content.ReadAsStringAsync());

        await collector.WaitForMeasurementsAsync(minCount: 1).WaitAsync(TimeSpan.FromSeconds(5));
        Assert.Collection(collector.GetMeasurementSnapshot(),
            measurement =>
            {
                Assert.Equal("http", measurement.Tags["url.scheme"]);
                Assert.Equal("GET", measurement.Tags["http.request.method"]);
                Assert.Equal("/", measurement.Tags["http.route"]);
            });
    }
}

前述測試:

  • 使用 WebApplicationFactory<TEntryPoint> 啟動記憶體中的 Web 應用程式。 處理站泛型引數中的 Program 會指定 Web 應用程式。
  • 使用 MetricCollector<T> 收集計量值
    • 需要一個套件參照 Microsoft.Extensions.Diagnostics.Testing
    • MetricCollector<T> 是使用 Web 應用程式的 IMeterFactory 建立。 這讓收集器僅報告測試記錄的計量值。
    • 包含要收集的計量名稱 Microsoft.AspNetCore.Hosting 和計數器名稱 http.server.request.duration
  • 對 Web 應用程式提出 HTTP 要求。
  • 使用指標收集器的結果來驗證測試。

ASP.NET Core Identity 指標

ASP.NET Core Identity 的可觀察性幫助你監控使用者管理活動與認證流程。

度量以 Microsoft.AspNetCore.Identity 公尺為單位,並在下列各節中說明。

使用者管理指標

  • aspnetcore.identity.user.create.duration 測量使用者建立作業的持續時間。
  • aspnetcore.identity.user.update.duration 測量使用者更新作業的持續時間。
  • aspnetcore.identity.user.delete.duration 衡量使用者刪除操作的持續時間。
  • aspnetcore.identity.user.check_password_attempts 計算密碼驗證嘗試次數。
  • aspnetcore.identity.user.generated_tokens 計算為使用者產生的令牌,例如密碼重設令牌。
  • aspnetcore.identity.user.verify_token_attempts 計算令牌驗證嘗試。

驗證指標

  • aspnetcore.identity.sign_in.authenticate.duration 測量身份驗證操作的持續時間。
  • aspnetcore.identity.sign_in.check_password_attempts 計算登入期間的密碼檢查嘗試次數。
  • aspnetcore.identity.sign_in.sign_ins 計算成功的登入次數。
  • aspnetcore.identity.sign_in.sign_outs 計算登出次數。
  • aspnetcore.identity.sign_in.two_factor_clients_remembered 計算記住的雙因素身份驗證用戶端。
  • aspnetcore.identity.sign_in.two_factor_clients_forgotten 計算被遺忘的雙重驗證客戶端。

利用這些指標來:

  • 監控使用者註冊和管理。
  • 追蹤身份驗證模式和潛在的安全問題。
  • 衡量營運績效 Identity 。
  • 觀察雙因素身份驗證的使用情況。

檢視 Identity 指標

使用 dotnet-counters 查看這些指標並即時監控它們。 或者,將它們匯出到 Prometheus,並利用本文前述的技術在 Grafana 中視覺化。

例如,若要監控所有Identity 指標 以使用 dotnet-counters

dotnet-counters monitor -n YourAppName --counters Microsoft.AspNetCore.Identity

ASP.NET Core 計量和計數器

關於 ASP.NET Core 的計量器與計數器列表,請參見 ASP.NET Core 指標。 在 ASP.NET Core 11 及之後版本中,內建的 HTTP 伺服器計量器(例如 Microsoft.AspNetCore.HostingMicrosoft.AspNetCore.Server.Kestrel)會輸出符合 OpenTelemetry HTTP 伺服器語意慣例所需部分的資料。 你無須使用 OpenTelemetry.Instrumentation.AspNetCore 套件,也可以透過 OpenTelemetry SDK 取用這些儀表。