.NET中如何用OpenTelemetry Prometheus导出器导出多版本指标
在.NET项目中配置多版本OpenTelemetry Prometheus指标端点
直接添加多个AddPrometheusExporter会覆盖之前的配置,因为默认注册的是单例实例。要实现多路径多版本指标,推荐以下两种方案:
方法一:使用命名的Prometheus导出器实例
OpenTelemetry支持注册命名的导出器实例,每个实例独立配置路径和指标规则,完全隔离。
配置代码
services.AddOpenTelemetry() .WithMetrics(opts => opts .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("rrfc")) // 注册v1版本导出器,指定名称、路径和专属指标规则 .AddPrometheusExporter("v1", exporterOpts => { exporterOpts.ScrapeEndpointPath = "/v1/metrics"; }, metricOpts => { // 仅收集v1版本的指标(比如指定旧版Meter) metricOpts.AddMeter(TelemetryUnit.CALL_TELEMETRY_METER_V1); }) // 注册v2版本导出器 .AddPrometheusExporter("v2", exporterOpts => { exporterOpts.ScrapeEndpointPath = "/v2/metrics"; }, metricOpts => { // 仅收集v2版本的指标(指定新版Meter) metricOpts.AddMeter(TelemetryUnit.CALL_TELEMETRY_METER_V2); })); // 为每个命名导出器单独挂载scraping端点 app.UseOpenTelemetryPrometheusScrapingEndpoint("v1"); app.UseOpenTelemetryPrometheusScrapingEndpoint("v2");
关键说明
- 每个命名导出器是独立的单例,配置不会互相覆盖
- 可以为不同版本的导出器指定不同的
Meter、指标过滤规则,彻底隔离不同版本的指标集
方法二:自定义中间件实现路径过滤
如果不同版本的指标只是需要简单的名称过滤,不想维护多个导出器实例,可以通过自定义中间件动态筛选指标。
配置代码
// 先注册一个全局的Prometheus导出器(包含所有版本的指标) services.AddOpenTelemetry() .WithMetrics(opts => opts .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("rrfc")) .AddMeter(TelemetryUnit.CALL_TELEMETRY_METER) .AddPrometheusExporter()); // 为v1路径配置指标过滤 app.Map("/v1/metrics", appBuilder => { appBuilder.Use(async (context, next) => { var exporter = context.RequestServices.GetRequiredService<PrometheusExporter>(); // 收集所有指标 var metrics = await exporter.CollectAsync(context.RequestAborted); // 过滤出v1版本的指标(比如按名称前缀) var filteredMetrics = metrics.Where(m => m.Name.StartsWith("v1_")); // 返回格式化后的指标文本 context.Response.ContentType = "text/plain"; await using var writer = new StreamWriter(context.Response.Body); await PrometheusTextFormatter.FormatAsync(filteredMetrics, writer, context.RequestAborted); }); }); // 为v2路径配置指标过滤 app.Map("/v2/metrics", appBuilder => { appBuilder.Use(async (context, next) => { var exporter = context.RequestServices.GetRequiredService<PrometheusExporter>(); var metrics = await exporter.CollectAsync(context.RequestAborted); var filteredMetrics = metrics.Where(m => m.Name.StartsWith("v2_")); context.Response.ContentType = "text/plain"; await using var writer = new StreamWriter(context.Response.Body); await PrometheusTextFormatter.FormatAsync(filteredMetrics, writer, context.RequestAborted); }); });
适用场景
- 不同版本的指标差异较小,仅需简单的名称过滤
- 不想维护多个导出器实例,减少配置复杂度
内容的提问来源于stack exchange,提问作者SepanD
相关产品推荐
相关产品推荐

