[AppMetrics] 如何在 ASP.NET Core 3.1 使用 AppMetrics 收集應用程式中的性能指標

AppMetrics 是一款 Open Source 跨平台的 .NET 的 Library,支援了 .NET Core 和 .NET 4.5.2,前面幾篇提到用 Telegraf 收集作業系統的性能指標,涵蓋整個作業系統,粒度大;當指標粒度要更精準則可以考慮用 AppMetrics 收集更細微的資訊。

範例提供了 ASP.NET Core 3.1、ASP.NET Core 2.2 | .NET4.8、Console Application 4.8、ASP.NET Web API 4.5.2 OWIN、Console Application 4.5.2

.NET Core 文件
https://www.app-metrics.io/


.NET 4.5.2 文件
https://alhardy.github.io/app-metrics-docs/

簡介

以下片段擷取自 https://www.app-metrics.io/ 

App Metrics提供了各種度量標準類型來度量事物,例如請求率,計算一段時間內的用戶登錄數,度量執行數據庫查詢所花費的時間,度量可用內存的數量等等。支持的度量標準類型包括Apdex,儀表,計數器,儀表,直方圖和計時器。

App Metrics還提供了運行狀況檢查系統,使您可以通過用戶定義的檢查來監視應用程序的運行狀況。

使用App Metrics,您可以:

  • 捕獲任何類型的.NET應用程序中的應用程序指標,例如Windows Service,MVC網站,Web API等
  • 自動測量MVC或Web API項目中每個端點的性能和錯誤
  • 使用OAuth2保護API時,自動衡量每個客戶端的請求率和錯誤率
  • 選擇保存捕獲的指標的位置以及希望用於可視化這些指標的儀表板
  • 通過特定於TSDB的報告擴展支持基於推和拉的指標收集,並通過HTTP以要求的格式公開指標
  • 支持以所需格式將指標推送到自定義HTTP端點
  • 支持以所需格式將指標寫入文件以供指標代理收集

開發環境

  • Windows 10
  • ASP.NET Core 3.1
  • AppMertics 4.0.0-preview1.0.3,相依 .NET FX 4.6.1、NETStandard 2
  • Telegraf 1.13.4
  • Granfana 6.6.2
  • InfluDB 1.7.10

快速打造一個收集站台性能指標

開一個 ASP.NET Core 3.1 API 專案

 

安裝套件

Install-Package App.Metrics -version 4.0.0-preview1.0.3
Install-Package App.Metrics.AspNetCore.Mvc -version 4.0.0-preview1.0.3
Install-Package App.Metrics.Reporting.Console -version 4.0.0-preview1.0.3
Install-Package App.Metrics.Reporting.InfluxDB -version 4.0.0-preview1.0.3
Install-Package App.Metrics.Health
Install-Package App.Metrics.Health.Reporting.Metrics
Install-Package App.Metrics.Health.Checks.Process
Install-Package App.Metrics.Health.Checks.Http
Install-Package App.Metrics.Health.Checks.Network
Install-Package App.Metrics.AspNetCore.Health.Endpoints
Install-Package App.Metrics.AspNetCore.Health.Hosting
Install-Package App.Metrics.AspNetCore.Health

 

InfluxDB

開始之前,如果你不知道怎麼配置 InfluxDB,先參考這篇 [InfluxDB] 如何安裝及配置 InfluxDB

建立一個資料庫,名為:AppMetricsAspCore31

> Create Database AppMetricsAspCore31

 

Program.cs

Hosting Config

ConfigureMetricsWithDefaults:是 App.Metrics.AspnetCore.Hosting preview 功能,配置 Report。

Report:指標收集後的儲存位置,這裡我用了 Console、InfluxDB

UseMetricsWebTracking:使用追蹤 Web 指標的 Middleware
參考:https://www.app-metrics.io/web-monitoring/aspnet-core/tracking-middleware

Health:健康指標,註冊這兩個方法 webBuilder.UseHealthEndpoints()、webBuilder.UseHealth(),這兩個是 IWebHostBuilder 的擴充方法,這還不會開始收集資料
參考:https://www.app-metrics.io/web-monitoring/aspnet-core/health/
Endpoint: https://www.app-metrics.io/web-monitoring/aspnet-core/health/#endpoints-provided

public class Program
{
    public const string InfluxDbUrl  = "http://127.0.0.1:8086";
    public const string InfluxDbName = "AppMetricsAspCore31";
 
    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var thresholdBytes = 200;
        var filter         = new MetricsFilter();
 
        return Host.CreateDefaultBuilder(args)
                   .ConfigureWebHostDefaults(webBuilder =>
                                             {
                                                 //webBuilder.ConfigureHealthWithDefaults((context, healthBuilder) =>
                                                 //                                       {
                                                 //                                       });
                                                 webBuilder.UseHealthEndpoints();
                                                 webBuilder.UseHealth();
                                                 webBuilder.UseStartup<Startup>();
                                             })
                   .ConfigureMetricsWithDefaults(builder =>
                                                 {
                                                     builder.Filter.With(filter);
                                                     builder.Report.ToInfluxDb(InfluxDbUrl, InfluxDbName,
                                                                               TimeSpan.FromSeconds(5));
                                                     builder.Report.ToConsole(TimeSpan.FromSeconds(5));
                                                     builder.Configuration
                                                            .Configure(p =>
                                                                       {
                                                                           p.Enabled          = true;
                                                                           p.ReportingEnabled = true;
                                                                       })
                                                         ;
                                                 })
                   .UseMetrics()
                   .UseMetricsWebTracking()
            ;
    }
 
 
    public static void Main(string[] args)
    {
        var build = CreateHostBuilder(args).Build();
        build.Run();
    }
}

 

Startup.cs

app.UseMetricsAllMiddleware():使用所有指標的 Middleware。
參考:https://www.app-metrics.io/web-monitoring/aspnet-core/tracking-middleware/

services.GetService<IMetricsRoot>():從 DI Container 取出 IMetricsRoot 執行個體,再設定 Health。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
 
    app.UseHttpsRedirection();
 
    app.UseRouting();
 
    app.UseAuthorization();
 
    app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
 
 
    var services       = app.ApplicationServices;
    var metricsRoot    = services.GetService<IMetricsRoot>();
    SetupHealth(metricsRoot);
 
    app.UseMetricsAllMiddleware();
    app.UseHealthAllEndpoints();
}

 

設定Health

HealthBuilder:健康指標執行個體,跟 Metric 用相同的 Report (InfluxDB、Console),接收 DI Container ontainer 傳過來的 IMetricsRoot 執行個體。
參考:https://www.app-metrics.io/health-checks/

HealthChecks:基本環境檢查,資料庫、網路(DN、Ping)、記憶體,threshold = 1,當記憶體大於 1 MB 時表不健康
參考:https://www.app-metrics.io/health-checks/pre-defined-checks/

AppMetricsTaskScheduler:App Metrics 提供的定期執行物件,定期收集健康指標

public static void SetupHealth(IMetricsRoot metricsRoot)
{
    long threshold = 1;
 
    //var healthBuilder = serviceProvider.GetService<IHealthBuilder>();
    var healthBuilder = new HealthBuilder();
 
    var health = healthBuilder.Configuration
                              .Configure(p =>
                                         {
                                             p.Enabled          = true;
                                             p.ReportingEnabled = true;
                                         })
                              .Report
                              .ToMetrics(metricsRoot)
                              .HealthChecks.AddProcessPrivateMemorySizeCheck("Private Memory Size", threshold)
                              .HealthChecks.AddProcessVirtualMemorySizeCheck("Virtual Memory Size", threshold)
                              .HealthChecks.AddProcessPhysicalMemoryCheck("Working Set", threshold)
                              .HealthChecks.AddPingCheck("google ping", "google.com", TimeSpan.FromSeconds(10))
                              .HealthChecks.AddHttpGetCheck("github", new Uri("https://github.com/"), TimeSpan.FromSeconds(10))
                              .Build();
 
 
    var scheduler =
        new AppMetricsTaskScheduler(TimeSpan.FromSeconds(5),
                                    async () =>
                                    {
                                        //await Task.WhenAll(metricsRoot.ReportRunner.RunAllAsync());
                                        var healthStatus =
                                            await health.HealthCheckRunner.ReadAsync();
 
                                        //using (var stream = new MemoryStream())
                                        //{
                                        //    await health.DefaultOutputHealthFormatter
                                        //                .WriteAsync(stream, healthStatus);
                                        //    var result = Encoding.UTF8.GetString(stream.ToArray());
                                        //    Console.WriteLine(result);
                                        //}
 
                                        foreach (var reporter in health.Reporters)
                                        {
                                            await reporter.ReportAsync(health.Options,
                                                                       healthStatus);
                                        }
                                    });
    scheduler.Start();
}

 

Health 收集到不健康的指標,Grafana rafana 儀表板如下圖:

注入 Controller

services.AddMvc().AddMetrics():對 Controller 注入 IMetrics,更精準的量測 Action 性能指標

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddMvc().AddMetrics();
}

 

這樣就完成了服務的指標收集,觀察一下 InfluDB 是不是有新的 name 產生

如果你不知道怎麼配置 InfluxDB,先參考這篇 [InfluxDB] 如何安裝及配置 InfluxDB

 

Grafana

最後 Grafana 讀取 InfluDB 呈現資料,開始之前,如果你不知道怎麼配置 Grafana,先參考這篇 [Grafana] 如何安裝及配置 GrafaraDashboard

選定番號 2125, https://grafana.com/grafana/dashboards/2125

 

執行結果如下圖:

 

簡單幾個步驟,便完成收集一個站台的性能指標,然後通過 Grafana 儀表板呈現。

參考來源

https://www.app-metrics.io/

範例程式

https://github.com/yaochangyu/sample.dotblog/tree/master/AppMetrics/Lab.AppMetricToInfluxDB

ASP.NET Core 2.2/.NET 4.6.1(Up):WebApi.Core22.NET48

ASP.NET Core 3.1:WebApiCore31

Console Application:ConsoleApp.NET48

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo