在.NET 6中通过OpenTelemetry向Prometheus添加追踪与异常监控
现有配置与问题
已在Startup.cs中完成OpenTelemetry指标配置,成功将运行时、ASP.NET Core、HttpClient指标导出至Prometheus,代码如下:
public void ConfigureServices(IServiceCollection services) { services.AddOpenTelemetry() .WithMetrics(b => b .AddRuntimeInstrumentation() .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddPrometheusExporter()); }
当前存在两个需求与对应问题:
- 异常监控:希望将异常日志记录到Prometheus,但未找到类似
WithMetrics的WithExceptions方法,无直接实现路径。 - 自定义追踪导出:已通过
WithTraces配置自定义追踪,但未找到对应Prometheus导出器,仅能使用ConsoleExporter,无法将追踪数据导出至Prometheus。
尝试添加追踪支持后的修改代码:
public void ConfigureServices(IServiceCollection services) { services.AddOpenTelemetry() .WithMetrics(b => b .AddRuntimeInstrumentation() .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddPrometheusExporter()) .WithTracing(b => b .AddSource("MySource") .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddConsoleExporter()); }
使用的NuGet包及版本:
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.6.0" /> <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.6.0" /> <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.5.1-beta.1" /> <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.6.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.6.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.6.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.RunTime" Version="1.5.1" />
解决方案
1. 异常监控:将异常转为Prometheus指标
Prometheus是基于指标的监控系统,不直接存储日志/异常事件,需将异常转换为计数器类指标实现监控。可通过以下方式实现:
步骤1:定义自定义指标Meter
在项目中创建静态Meter实例用于自定义异常计数器:
public static class AppMetrics { public static readonly Meter ExceptionMeter = new Meter("MyApp.Exceptions", "1.0.0"); }
步骤2:在AspNetCoreInstrumentation中捕捉异常并递增计数器
修改Metrics配置,通过EnrichWithException回调捕获异常,更新计数器:
services.AddOpenTelemetry() .WithMetrics(b => b .AddRuntimeInstrumentation() .AddAspNetCoreInstrumentation(opt => { // 捕获ASP.NET Core请求中的异常 opt.EnrichWithException = (activity, exception) => { var exceptionCounter = AppMetrics.ExceptionMeter.CreateCounter<long>( "aspnetcore.unhandled_exceptions.total", description: "Total number of unhandled exceptions in ASP.NET Core requests", unit: "exceptions"); // 添加异常类型标签,便于Prometheus过滤查询 exceptionCounter.Add(1, new KeyValuePair<string, object>("exception_type", exception.GetType().FullName)); }; }) .AddHttpClientInstrumentation() .AddPrometheusExporter()) // 保持原有追踪配置,开启异常记录 .WithTracing(b => b .AddSource("MySource") .AddAspNetCoreInstrumentation(opt => { opt.RecordException = true; // 将异常信息记录到追踪链路中 }) .AddHttpClientInstrumentation() .AddConsoleExporter());
配置完成后,Prometheus即可采集到aspnetcore_unhandled_exceptions_total指标,可通过标签筛选不同类型的异常。
2. 追踪数据处理:Prometheus不原生支持Trace存储
Prometheus的设计定位是指标存储与查询,不适合存储完整的分布式追踪链路数据(Trace)。若需持久化追踪数据,建议采用以下方案:
方案:使用OpenTelemetry Collector转发数据
通过OpenTelemetry Collector作为中间层,统一接收Trace、Metrics数据,再分别转发至:
- Prometheus:处理指标数据
- Jaeger/Zipkin:处理追踪链路数据
修改追踪配置,替换ConsoleExporter为OTLP Exporter,将数据发送至Collector:
.WithTracing(b => b .AddSource("MySource") .AddAspNetCoreInstrumentation(opt => opt.RecordException = true) .AddHttpClientInstrumentation() .AddOtlpExporter(opt => { // 配置Collector的OTLP gRPC端点(默认端口4317) opt.Endpoint = new Uri("http://your-collector-host:4317"); opt.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc; }));
随后在OpenTelemetry Collector中配置对应导出器,实现指标到Prometheus、追踪到Jaeger的分流处理。
版本适配建议
当前使用的OpenTelemetry.Exporter.Prometheus.AspNetCore为1.5.1-beta.1版本,与其他1.6.0版本的包存在版本差异,建议升级至同版本的稳定版(若已发布),避免潜在的兼容性问题。
内容的提问来源于stack exchange,提问作者Ammar

