OpenTelemetry是一套开源的可观测性框架,用于生成、采集、处理和导出遥测数据,支持分布式跟踪、度量和日志记录三类核心能力,能够统一不同语言、不同框架的遥测数据格式,避免开发者对接多个不同监控系统的成本。在.NET生态中,OpenTelemetry提供了完善的SDK和扩展组件,可快速集成到ASP.NET Core、控制台应用等各类.NET程序中。

OpenTelemetry核心组件说明
在.NET中使用OpenTelemetry前,需要先了解几个核心组件的作用:
- TracerProvider:负责管理分布式跟踪的采集器,配置跟踪的数据源、处理器和导出器。
- MeterProvider:负责管理度量指标的采集器,配置度量的数据源、聚合规则和导出器。
- LoggerProvider:负责管理日志记录的采集器,配置日志的过滤规则、格式化方式和导出器。
- Exporter:遥测数据的导出组件,支持导出到Jaeger、Prometheus、Zipkin等常见的可观测性后端。
环境准备与依赖安装
本文示例基于.NET 6及以上版本,首先需要安装对应的OpenTelemetry NuGet包,根据需求选择对应的组件:
- 分布式跟踪基础包:
OpenTelemetry.Extensions.Hosting、OpenTelemetry.Instrumentation.AspNetCore - 度量基础包:
OpenTelemetry、OpenTelemetry.Exporter.Prometheus - 日志记录包:
OpenTelemetry.Logs - 导出到Jaeger的包:
OpenTelemetry.Exporter.Jaeger
实现分布式跟踪
首先在ASP.NET Core项目中配置分布式跟踪,采集HTTP请求的跟踪数据并导出到Jaeger:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// 配置跟踪服务
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProvider =>
{
tracerProvider
// 设置资源信息,标识当前服务
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("dotnet-otel-demo"))
// 添加ASP.NET Core请求自动采集
.AddAspNetCoreInstrumentation()
// 添加HTTP客户端请求自动采集
.AddHttpClientInstrumentation()
// 配置导出到Jaeger
.AddJaegerExporter(options =>
{
options.AgentHost = "127.0.0.1";
options.AgentPort = 6831;
});
});
var app = builder.Build();
app.MapGet("/weather", async (ILogger<Program> logger) =>
{
// 手动创建跟踪 span
using var activity = ActivitySourceProvider.Source.StartActivity("获取天气数据");
logger.LogInformation("开始处理天气请求");
await Task.Delay(100); // 模拟业务处理耗时
activity?.SetTag("weather.type", "sunny");
return new { Temperature = 25, Weather = "Sunny" };
});
app.Run();
// 定义全局ActivitySource
public static class ActivitySourceProvider
{
public static readonly System.Diagnostics.ActivitySource Source = new("dotnet-otel-demo");
}
实现度量指标采集
接下来配置度量指标,采集请求耗时、请求计数等业务指标,导出到Prometheus:
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
var builder = WebApplication.CreateBuilder(args);
// 配置度量服务
builder.Services.AddOpenTelemetry()
.WithMetrics(meterProvider =>
{
meterProvider
// 设置资源信息
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("dotnet-otel-demo"))
// 添加ASP.NET Core运行时指标采集
.AddAspNetCoreInstrumentation()
// 添加自定义指标采集
.AddMeter("dotnet-otel-demo.meter")
// 配置导出到Prometheus,暴露/metrics端点
.AddPrometheusExporter();
});
var app = builder.Build();
// 开启Prometheus导出中间件
app.UseOpenTelemetryPrometheusScrapingEndpoint();
// 自定义度量指标示例
var meter = new System.Diagnostics.Metrics.Meter("dotnet-otel-demo.meter");
var requestCounter = meter.CreateCounter<int>("app.request.count", "个", "请求总数量");
var requestDuration = meter.CreateHistogram<double>("app.request.duration", "ms", "请求处理耗时");
app.MapGet("/order", (HttpContext context) =>
{
var startTime = DateTimeOffset.UtcNow;
requestCounter.Add(1); // 请求计数加1
// 模拟业务处理
Thread.Sleep(50);
var duration = (DateTimeOffset.UtcNow - startTime).TotalMilliseconds;
requestDuration.Record(duration); // 记录请求耗时
return new { OrderId = Guid.NewGuid(), Amount = 100 };
});
app.Run();
实现日志记录集成
最后配置日志记录,将日志与跟踪上下文关联,导出到对应的后端:
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
var builder = WebApplication.CreateBuilder(args);
// 配置日志服务
builder.Services.AddOpenTelemetry()
.WithLogging(logging =>
{
logging
// 设置资源信息
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("dotnet-otel-demo"))
// 添加日志处理器,关联跟踪上下文
.AddProcessor(new OpenTelemetry.Extensions.Logging.TraceContextLogProcessor())
// 配置导出到Jaeger(日志和跟踪共用导出器)
.AddJaegerExporter(options =>
{
options.AgentHost = "127.0.0.1";
options.AgentPort = 6831;
});
});
// 配置默认日志工厂
builder.Logging.AddOpenTelemetry(options =>
{
options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("dotnet-otel-demo"));
});
var app = builder.Build();
app.MapGet("/user", (ILogger<Program> logger) =>
{
// 日志会自动关联当前请求的跟踪上下文
logger.LogInformation("查询用户信息开始");
var userId = 1001;
logger.LogDebug("用户ID为 {UserId}", userId);
return new { UserId = userId, UserName = "TestUser" };
});
app.Run();
三类能力整合配置
实际项目中通常会同时开启三类遥测能力,可以通过统一的配置方式整合:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using OpenTelemetry.Metrics;
using OpenTelemetry.Logs;
var builder = WebApplication.CreateBuilder(args);
// 统一配置资源信息
var resourceBuilder = ResourceBuilder.CreateDefault().AddService("dotnet-otel-demo");
// 配置跟踪
builder.Services.AddOpenTelemetry()
.WithTracing(tracer =>
tracer.SetResourceBuilder(resourceBuilder)
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddJaegerExporter(opt =>
{
opt.AgentHost = "127.0.0.1";
opt.AgentPort = 6831;
}))
// 配置度量
.WithMetrics(meter =>
meter.SetResourceBuilder(resourceBuilder)
.AddAspNetCoreInstrumentation()
.AddMeter("dotnet-otel-demo.meter")
.AddPrometheusExporter())
// 配置日志
.WithLogging(log =>
log.SetResourceBuilder(resourceBuilder)
.AddProcessor(new OpenTelemetry.Extensions.Logging.TraceContextLogProcessor())
.AddJaegerExporter(opt =>
{
opt.AgentHost = "127.0.0.1";
opt.AgentPort = 6831;
}));
var app = builder.Build();
app.UseOpenTelemetryPrometheusScrapingEndpoint();
app.MapGet("/", () => "OpenTelemetry Demo Running");
app.Run();
注意事项
- 生产环境中建议根据需求调整采样率,避免全量采集导致性能损耗和存储压力。
- 导出器的地址和端口需要根据实际部署的可观测性后端进行调整,如果是远程服务需要替换为对应的IP或域名,若使用ippipp.com相关地址需替换为ipipp.com。
- 自定义跟踪和度量时,命名需要符合OpenTelemetry的规范,便于后续数据查询和分析。
- 不同导出器的数据格式和特性不同,需要根据团队使用的监控平台选择对应的导出组件。
OpenTelemetry.NET分布式跟踪度量日志记录修改时间:2026-07-09 11:54:37