许多应用直接将指标导出到 Prometheus。如果你还不熟悉它,可以把它理解为用于保存计数器、直方图等指标的时序数据库。将指标存入 Prometheus 的应用通常会使用一种常见的 Prometheus 客户端完成集成。
如今,OpenTelemetry 已成为 CNCF 毕业项目,越来越多的公司希望迁移到 OpenTelemetry,在可观测性架构中加入指标之外的信号。日志和追踪是常见选择,可以帮助深入了解应用的行为。性能剖析数据也开始成为受欢迎的第四种遥测信号,用来获得更深层的理解。
这带来了迁移难题:怎样把应用的指标从一个系统迁移到另一个系统,同时避免一次性切换?为了降低迁移风险,更合适的是渐进方式:在一段时间内同时向两个系统导出指标,比较并检查迁移前后的状态,确保任一系统中的生产可见性都没有损失,无论是观察指标还是驱动告警。
使用 .NET 的 OpenTelemetry Prometheus 导出器
.NET 的 OpenTelemetry Prometheus 导出器最新版本允许对生产指标采用这种方式。你可以在应用和框架代码中使用 .NET Meter 类采集指标,同时把它们导出到 Prometheus 及另一个导出器,例如由 OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet 包提供的 OTLP 导出器。
这个 Prometheus 导出器实际上是一种构建在 OpenTelemetry SDK 之上的 Prometheus 客户端库。它在应用中提供 HTTP 抓取端点,让 Prometheus 服务器定期采集应用指标。
该导出器实现 OpenTelemetry 的 Prometheus 规范,并实现所有已记录的文本暴露格式,以兼容 OpenMetrics;仍处于实验阶段的 OpenMetrics 2.0 除外。规范实现矩阵可用于核对实现情况。
flowchart LR
subgraph APP["Application"]
AC["Application code"]
SDK["OpenTelemetry SDK"]
PE["Prometheus exporter"]
OE["OTLP exporter (Client)"]
EP["GET /metrics HTTP endpoint (Server)"]
AC -->|"Generates metrics"| SDK
SDK -->|"Feeds metrics"| PE
PE -->|"Serves metrics as text/plain"| EP
SDK -->|"Feeds metrics"| OE
end
P["Prometheus (Client)"]
OTB["OpenTelemetry Backend (Server)"]
P -->|"HTTP GET /metrics (scrape request)"| EP
EP -->|"Metrics response (text format)"| P
OE -->|"OTLP export request"| OTB
OTB -->|"OTLP response/ack"| OE
在 .NET 应用代码中,只使用 Meter 类及 Counter<T>、Gauge<T>、Histogram<T> 指标工具,就能采集指标,无需同时使用 .NET OpenTelemetry SDK 和专门的 Prometheus 客户端。
public class BlogPostComments
{
private readonly Meter _meter;
private readonly Counter<long> _likes;
public BlogPostComments(IMeterFactory meterFactory)
{
_meter = meterFactory.Create("OpenTelemetry.Blog");
_likes = _meter.CreateCounter<long>("blog_post_likes");
}
public void BlogPostLiked(long id) =>
_likes.Add(1, new KeyValuePair<string, object?>("post_id", id));
}
随后,在项目中加入 OpenTelemetry.Exporter.Prometheus.AspNetCore NuGet 包,再用少量代码配置 OpenTelemetry SDK,就可以同时向 Prometheus 和支持 OpenTelemetry 的后端通过 OTLP 导出指标。
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.SetResourceBuilder(CreateResourceBuilder())
.AddMeter("OpenTelemetry.Blog")
.AddOtlpExporter()
.AddPrometheusExporter()
.Build();
应用还需要暴露 Prometheus 用于采集指标的 HTTP 抓取端点。原文说明可以在 Startup 类的 Configure 方法中,为 IApplicationBuilder 添加 UseOpenTelemetryPrometheusScrapingEndpoint 扩展方法,并给出以下示例:
var builder = WebApplication.CreateBuilder(args);
// Configure services here
var app = builder.Build();
// Configure other middleware here
app.MapPrometheusScrapingEndpoint();
app.Run();
使用 Meter API 导出指标,会让应用代码更易移植,并解除它与 Prometheus 专用 API 的耦合。因此可以移除应用代码对 Prometheus 客户端库的依赖。除了让代码能够接入 OpenTelemetry 生态,这也让你可以使用其他 .NET 生态工具,例如用 dotnet-counters 查看指标。
如果应用现在只使用原生 Prometheus 客户端,例如 prometheus-net,就需要先逐步迁移到 Meter API。迁移需要多长时间,取决于现有 Prometheus 埋点的复杂程度,以及可投入修改的资源。
迁移中可能遇到一些 Prometheus 功能没有对应的 Meter API,因此不受支持,包括:
- Prometheus 的 summary 数据类型;
- 原生直方图。
使用 OTLP 向 Prometheus 推送指标
另一种情况是:你只有 Prometheus 服务器,没有兼容 OTLP 的后端,而且只希望导出指标。Prometheus 本身提供一项需要显式启用的功能,可以接收通过 OTLP 推送过来的指标。
首先,确保运行 Prometheus 时使用 --web.enable-otlp-receiver 命令行标志。
然后,采用与上面相似的方式配置 OTLP 导出器,但这种情况下无需同时使用 Prometheus 导出器。还要注意,示例为 OTLP 指标端点指定路径,并将导出协议设为 HTTP/protobuf。
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.SetResourceBuilder(CreateResourceBuilder())
.AddMeter("OpenTelemetry.Blog")
.AddOtlpExporter((options, _) =>
{
options.Endpoint = new Uri("http://prometheus:9090/api/v1/otlp/v1/metrics");
options.Protocol = OtlpExportProtocol.HttpProtobuf;
})
.Build();
这种方式允许使用 OpenTelemetry .NET SDK,通过 OTLP 向 Prometheus 推送指标,应用代码无需依赖 Prometheus 客户端库。
完整示例见 OpenTelemetry .NET 仓库中的 Getting Started with Prometheus and Grafana。
总结
应用可以用较小的运行时开销,同时推送 OTLP 指标,并让 Prometheus 拉取指标。这样两个系统便可以并行使用,直到你决定将指标完全迁移到兼容 OpenTelemetry 的后端。
原文:Dual-exporting .NET metrics with OTLP and Prometheus。作者:Martin Costello(Grafana Labs);发布日期:2026-09-18。原站内容仓库采用 CC BY 4.0,本稿为中文翻译,原内容按许可“按原样”提供,不附加担保。












暂无评论内容