指标是一段时间内报告的数字度量值。 使用它们监视应用的运行状况并生成警报。 例如,Web 服务可能会跟踪以下数量:
- 每秒接收的请求数。
- 响应所需的毫秒数。
- 发送的响应含有错误。
定期将这些指标报告给监视系统。 设置仪表板以查看指标并创建警报,以通知人员出现问题。 如果 Web 服务打算在 400 毫秒内响应请求,并在 600 毫秒后开始响应,则监视系统可以通知操作人员应用响应速度比平时慢。
ASP.NET Core内置指标中介绍了所有工具及其属性的综合列表。
使用指标
使用指标涉及以下内容:
- 检测:.NET 库中的代码采用度量值,并将这些度量值与指标名称关联起来。 .NET 和 ASP.NET Core 包括许多内置指标。
- 收集和存储:由一个 .NET 应用来配置要从应用传输的命名指标以用于外部存储和分析。 某些工具可能通过使用配置文件或 UI 工具在应用外部执行配置。
- 可视化:一种可以以人类可读的格式显示指标的工具。 例如 Grafana 和 Prometheus。
- 警报:一个当指标超过阈值时提供通知的工具。 例如,如果 Web 服务的平均响应时间超过 400 毫秒,则可以向操作人员发送警报。
- 分析:一个可以分析一段时间内的指标的工具。 此工具通常是一个基于 Web 的仪表板,可以自定义以显示特定应用最重要的指标。
检测的代码可以记录数值度量值,但需要聚合、传输和存储度量值,才能创建用于监视的有用指标。 聚合、传输和存储数据的过程称为集合。 本教程展示了收集和显示指标的几个示例:
- 使用 OpenTelemetry 和 Prometheus 在 Grafana 中填充指标。
- 使用
dotnet-counters实时查看指标
还可以将度量值与称为标记的键值对相关联,以便对数据进行分类进行分析。 有关详细信息,请参阅多维指标。
创建初学者应用
使用以下命令创建新的 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 核心请求指标
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 核心请求指标。
- 从IHttpMetricsTagsFeature中获取
HttpContext。 仅当有人正在侦听指标时,此功能才会出现在上下文中。 使用前,请确认null不是IHttpMetricsTagsFeature。 - 将包含请求的营销源的自定义标记添加到
http.server.request.duration指标。- 该标记具有名称
mkt_medium和基于utm_medium查询字符串值的值。utm_medium值解析为已知值范围。 - 该标记允许按营销媒体类型对请求进行分类,这在分析 Web 应用流量时可能很有用。
- 该标记具有名称
注意
使用自定义标记进行扩充时,请遵循多维指标最佳做法。 如果标记数量过多或范围不受限制,则会产生许多标记组合,从而导致维度过高。 集合工具对计数器支持的维度有限制,可能会筛选结果以防止内存过多使用。
在某些端点和请求上禁用 HTTP 指标
选择不记录指标对自动化系统(例如运行状况检查)经常调用的端点有好处。 通常不需要记录这些请求的指标。 不必要的遥测数据会占用资源来进行收集和存储,并且会扭曲遥测仪表板上显示的结果。
可以通过添加元数据,使用 DisableHttpMetrics 特性或 DisableHttpMetrics 方法,将发往某个终结点的 HTTP 请求排除在指标收集之外:
- 将 DisableHttpMetrics 属性添加到 Web API 控制器、 SignalR 中心或 gRPC 服务。
- 在应用启动过程中映射终结点时调用 DisableHttpMetrics:
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
- 是一个由云原生计算基金会支持的供应商中立开源项目。
- 标准化云原生软件的遥测数据生成和收集。
- 使用 .NET 指标 API 与 .NET 配合使用。
- 得到 Azure Monitor 和许多 APM 供应商的认可。
从 ASP.NET Core 11 开始,框架的内置 HTTP 服务器指标和跟踪符合 OpenTelemetry HTTP 服务器语义约定所需的部分。 HTTP 服务器请求活动默认发出这些属性,与内置指标匹配。 因此, OpenTelemetry.Instrumentation.AspNetCore NuGet 包是可选的,用于收集 HTTP 服务器指标和跟踪。 本文中的示例仅使用内置计量(Microsoft.AspNetCore.Hosting 和 Microsoft.AspNetCore.Server.Kestrel),并且不引用检测包。 有关内置工具及其属性的列表,请参阅 ASP.NET Core内置 HTTP 指标。
虽然该包是可选的,但不能直接替代内置检测。 内置检测仅涵盖语义约定的必需部分。 在删除包之前,请考虑以下差异:
- 内置检测不会生成某些推荐的 HTTP 服务器属性,例如某些客户端和网络属性(如
client.address)。 对 有条件要求url.query的属性(包括修订)的完全支持仍在进行中。 如果依赖这些属性,请保留该软件包。 有关详细信息,请参阅 dotnet/aspnetcore#65873。 - 此包也为在 HTTP 服务器之外启用遥测(包括 Blazor 和 SignalR)提供了便利。 在跟踪方面,它会为 SignalR 注册额外的活动源(在 .NET 9 及更高版本中为
Microsoft.AspNetCore.SignalR.Server),并为 Blazor 注册额外的活动源(在 .NET 10 及更高版本中为Microsoft.AspNetCore.Components和Microsoft.AspNetCore.Components.Server.Circuits)。 对于指标而言,它会启用相应的内置指标采集器(例如Microsoft.AspNetCore.Components)。 如果不使用该软件包,请自行使用AddMeter注册源,并使用AddSource注册计量器,以收集相同的遥测数据。
将遥测添加到仅需要 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采样器会静默丢弃在请求期间启动的任何自定义子 span。
在现有跟踪流水线中,显式注册源:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource("Microsoft.AspNetCore")
.AddSource("MyApp"));
在前面的示例中:
-
AddSource("Microsoft.AspNetCore")注册 ASP.NET Core的 HTTP 服务器活动源,以便记录请求活动。 -
AddSource("MyApp")注册应用自身的 ActivitySource。 将MyApp替换为您的应用所使用的名称。 - 未显示导出程序。 此示例假定已在跟踪管道中配置了导出程序。
或者,从OpenTelemetry.Instrumentation.AspNetCore包调用AddAspNetCoreInstrumentation(),该包会为你注册源。
本教程使用 OSS Prometheus 和 Grafana 项目展示了可用于 OpenTelemetry 指标的集成之一。 指标数据流:
ASP.NET Core 指标 API 记录示例应用中的度量值。
在应用中运行的 OpenTelemetry .NET 库将聚合这些度量值。
Prometheus 导出程序库通过 HTTP 指标终结点提供聚合数据。 “导出程序”指的是 OpenTelemetry 调用库来将遥测数据传输到供应商特定的后端。
Prometheus 服务器:
- 轮询指标终结点。
- 读取数据。
- 将数据存储在数据库中以实现长期持久存储。 Prometheus 将读取和存储数据称为抓取终结点。
- 可以在其他计算机上运行。
Grafana 服务器:
- 查询 Prometheus 中存储的数据并将其显示在基于 Web 的监控仪表板上。
- 可以在其他计算机上运行。
查看示例应用中的指标
转到示例应用。 浏览器显示 Hello OpenTelemetry! ticks:<3digits>,其中 3digits 是当前 DateTime.Ticks 的最后三位数字。
将 /metrics 追加到 URL 以查看指标终结点。 浏览器显示正在收集的指标:
设置和配置 Prometheus
按照 Prometheus 起始步骤设置 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
- 重新加载配置或重启 Prometheus 服务器。
- 确认 OpenTelemetryTest 在 Prometheus Web 门户的状态>目标页中处于 UP 状态。
选择“打开指标资源管理器”图标以查看可用的指标:
输入计数器类别,例如 http_ 在 表达式 输入框中查看可用的指标:
或者,在表达式输入框中输入计数器类别kestrel以查看可用的指标:
在 Grafana 仪表板上显示指标
按照安装说明安装 Grafana,并将其连接到 Prometheus 数据源。
按照创建 Prometheus 图进行操作。 或者,可在 .NET 团队仪表板 @ grafana.com 下载适用于 .NET 指标的预生成仪表板。 下载的仪表板 JSON 可以导入到 Grafana 中。
在 ASP.NET Core 应用中测试指标
可以在 ASP.NET Core应用中测试指标。 执行此操作的一种方法是使用 MetricCollector<T>ASP.NET Core 集成测试来收集和断言指标值。
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 核心 Identity 指标
Identity ASP.NET Core可观测性有助于监视用户管理活动和身份验证过程。
指标单位为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.Hosting,和Microsoft.AspNetCore.Server.Kestrel)发出符合 OpenTelemetry HTTP 服务器语义约定所需部分的数据。 无需 OpenTelemetry.Instrumentation.AspNetCore 包,即可通过 OpenTelemetry SDK 使用这些度量值。