Nguon: Microsoft Learn · .NET 8.0

Metrics (Số liệu đo lường) trong ASP.NET Core

Nguồn: ASP.NET Core metrics

Metrics (số liệu đo lường) là các phép đo số được báo cáo theo thời gian. Chúng thường được sử dụng để theo dõi tình trạng của ứng dụng và tạo cảnh báo. Ví dụ, một web service (dịch vụ web) có thể theo dõi:

Các metrics này có thể được báo cáo cho hệ thống giám sát theo khoảng thời gian đều đặn. Dashboard (bảng điều khiển) có thể được thiết lập để xem metrics và tạo cảnh báo để thông báo cho người vận hành khi có sự cố. Nếu web service dự kiến phản hồi trong vòng 400 ms nhưng bắt đầu phản hồi trong 600 ms, hệ thống giám sát có thể thông báo cho nhân viên vận hành rằng thời gian phản hồi của ứng dụng chậm hơn bình thường.

Xem ASP.NET Core metrics tích hợp sẵn để có danh sách đầy đủ tất cả các instrument (công cụ đo) cùng với thuộc tính của chúng.

Sử dụng Metrics

Việc sử dụng metrics bao gồm các bước sau:

Code đã được instrument có thể ghi lại các phép đo số, nhưng các phép đo cần được tổng hợp, truyền và lưu trữ để tạo ra metrics hữu ích cho việc giám sát. Quá trình tổng hợp, truyền và lưu trữ dữ liệu được gọi là collection (thu thập). Hướng dẫn này trình bày một số ví dụ về thu thập và hiển thị metrics:

Các phép đo cũng có thể được liên kết với các cặp key-value được gọi là tags (thẻ) cho phép dữ liệu được phân loại để phân tích. Để biết thêm thông tin, xem Multi-dimensional metrics.

Tạo ứng dụng mẫu

Tạo một ứng dụng ASP.NET Core mới với lệnh sau:

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

Thay thế nội dung của Program.cs bằng đoạn code sau:

csharp
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();

Xem metrics với dotnet-counters

dotnet-counters là công cụ dòng lệnh có thể xem metrics trực tiếp cho các ứng dụng .NET theo yêu cầu. Nó không yêu cầu thiết lập, giúp nó hữu ích cho các cuộc điều tra ad-hoc hoặc xác minh rằng việc instrument metrics đang hoạt động. Nó hoạt động với cả API dựa trên System.Diagnostics.MetricsEventCounters.

Nếu công cụ dotnet-counters chưa được cài đặt, chạy lệnh sau:

dotnetcli
dotnet tool update -g dotnet-counters

Trong khi ứng dụng test đang chạy, khởi chạy dotnet-counters. Lệnh sau hiển thị ví dụ về dotnet-counters giám sát tất cả metrics từ meter Microsoft.AspNetCore.Hosting:

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

Đầu ra tương tự như sau sẽ được hiển thị:

dotnetcli
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

Làm phong phú metric request của ASP.NET Core

ASP.NET Core có nhiều metrics tích hợp sẵn. Metric http.server.request.duration:

Metric http.server.request.duration hỗ trợ tag enrichment (làm phong phú tag) bằng cách sử dụng IHttpMetricsTagsFeature. Enrichment là khi một thư viện hoặc ứng dụng thêm các tag của riêng mình vào metric. Điều này hữu ích nếu ứng dụng muốn thêm phân loại tùy chỉnh vào dashboard hoặc cảnh báo được xây dựng với metrics.

csharp
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();

Ví dụ trên:

Lưu ý: Tuân theo các best practices về multi-dimensional metrics khi làm phong phú bằng các tag tùy chỉnh. Các tag quá nhiều hoặc có phạm vi không giới hạn tạo ra nhiều tổ hợp tag, dẫn đến số chiều lớn. Các công cụ thu thập có giới hạn về số chiều được hỗ trợ cho một counter và có thể lọc kết quả để ngăn việc sử dụng bộ nhớ quá mức.

Tạo metrics tùy chỉnh

Metrics được tạo bằng cách sử dụng API trong namespace System.Diagnostics.Metrics. Xem Create custom metrics để biết thông tin về cách tạo metrics tùy chỉnh.

Tạo metrics trong ứng dụng ASP.NET Core với IMeterFactory

Nên tạo các instance Meter trong ứng dụng ASP.NET Core với IMeterFactory.

ASP.NET Core đăng ký IMeterFactory trong dependency injection (DI) theo mặc định. Meter factory tích hợp metrics với DI, giúp việc cô lập và thu thập metrics dễ dàng. IMeterFactory đặc biệt hữu ích cho testing (kiểm thử). Nó cho phép nhiều test chạy song song và chỉ thu thập các giá trị metrics được ghi lại trong một test.

Để sử dụng IMeterFactory trong ứng dụng, tạo một kiểu sử dụng IMeterFactory để tạo các metrics tùy chỉnh của ứng dụng:

csharp
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));
    }
}

Đăng ký kiểu metrics với DI trong Program.cs:

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

Inject kiểu metrics và ghi lại giá trị khi cần. Vì kiểu metrics được đăng ký trong DI, nó có thể được sử dụng với MVC controllers, Minimal APIs, hoặc bất kỳ kiểu nào được tạo bởi DI:

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

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

Để giám sát meter "Contoso.Web", sử dụng lệnh dotnet-counters sau:

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

Đầu ra tương tự như sau sẽ được hiển thị:

dotnetcli
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

Xem metrics trong Grafana với OpenTelemetry và Prometheus

Tổng quan

OpenTelemetry:

Hướng dẫn này trình bày một trong các tích hợp có sẵn cho OpenTelemetry metrics sử dụng các dự án OSS PrometheusGrafana. Luồng dữ liệu metrics:

  1. API metric ASP.NET Core ghi lại các phép đo từ ứng dụng mẫu.
  2. Thư viện OpenTelemetry .NET chạy trong ứng dụng tổng hợp các phép đo.
  3. Thư viện Prometheus exporter làm cho dữ liệu tổng hợp có thể truy cập thông qua HTTP metrics endpoint. 'Exporter' là tên OpenTelemetry gọi các thư viện truyền telemetry đến các backend cụ thể của nhà cung cấp.
  4. Prometheus server:
  5. Polling (thăm dò) metrics endpoint
  6. Đọc dữ liệu
  7. Lưu trữ dữ liệu trong database để lưu trữ lâu dài. Prometheus gọi việc đọc và lưu trữ dữ liệu là scraping một endpoint.
  8. Có thể chạy trên một máy khác
  9. Grafana server:
  10. Truy vấn dữ liệu được lưu trữ trong Prometheus và hiển thị nó trên dashboard giám sát dựa trên web.
  11. Có thể chạy trên một máy khác.

Thiết lập và cấu hình Prometheus

Làm theo Prometheus first steps để thiết lập Prometheus server và xác nhận nó đang hoạt động.

Sửa đổi file cấu hình prometheus.yml để Prometheus scrape metrics endpoint mà ứng dụng mẫu đang expose. Thêm đoạn YAML sau vào phần scrape_configs:

yaml
scrape_configs:
  - job_name: "prometheus"
    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.

Trong YAML được đánh dấu trên, thay thế 5045 bằng số port mà ứng dụng mẫu đang chạy.

Kiểm thử metrics trong ứng dụng ASP.NET Core

Có thể kiểm thử metrics trong ứng dụng ASP.NET Core. Một cách để làm điều đó là thu thập và assert giá trị metrics trong ASP.NET Core integration tests sử dụng MetricCollector<T>.

csharp
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"]);
            });
    }
}

Test trên:

ASP.NET Core meters và counters

Xem ASP.NET Core metrics để có danh sách các ASP.NET Core meters và counters.