在微服务架构普及的当下,单个业务请求往往会经过多个不同的服务节点,传统的日志排查方式很难快速定位跨服务的性能瓶颈或报错根因,分布式追踪就是解决这类问题的核心技术。OpenTelemetry作为云原生领域统一的观测性标准,提供了完整的追踪能力支持,C#开发者可以借助其官方SDK快速实现分布式追踪功能。

环境准备与依赖引入
首先需要准备.NET 6及以上版本的项目环境,本文以ASP.NET Core Web API项目为例进行演示。在项目文件中添加OpenTelemetry相关的NuGet包依赖,具体需要引入的核心包如下:
- OpenTelemetry
- OpenTelemetry.Extensions.Hosting
- OpenTelemetry.Instrumentation.AspNetCore
- OpenTelemetry.Instrumentation.Http
- OpenTelemetry.Exporter.Console(用于本地调试输出追踪数据)
- OpenTelemetry.Exporter.OpenTelemetryProtocol(用于导出数据到后端存储)
如果是.NET CLI添加依赖,可以执行以下命令:
dotnet add package OpenTelemetry dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package OpenTelemetry.Instrumentation.AspNetCore dotnet add package OpenTelemetry.Instrumentation.Http dotnet add package OpenTelemetry.Exporter.Console dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
基础Tracing配置
在Program.cs文件中,通过依赖注入的方式配置OpenTelemetry Tracing服务,基础配置代码如下:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// 配置OpenTelemetry Tracing
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
{
tracerProviderBuilder
// 设置服务资源信息,标识当前服务的名称、版本等
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(serviceName: "OrderService", serviceVersion: "1.0.0"))
// 添加ASP.NET Core自动埋点,自动采集HTTP请求相关的追踪信息
.AddAspNetCoreInstrumentation()
// 添加HttpClient自动埋点,自动采集服务间HTTP调用的追踪信息
.AddHttpClientInstrumentation()
// 添加控制台导出器,本地调试时可以在控制台看到追踪数据
.AddConsoleExporter();
});
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
高级配置:采样策略与自定义跨度
自定义采样策略
生产环境中不需要采集所有的请求追踪数据,可以通过配置采样策略来降低性能开销,OpenTelemetry提供了多种内置采样器,也可以自定义采样逻辑:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// 自定义采样器:只采样请求路径包含/api/order的请求
var customSampler = new CustomSampler();
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
{
tracerProviderBuilder
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(serviceName: "OrderService", serviceVersion: "1.0.0"))
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
// 配置自定义采样器
.SetSampler(customSampler)
.AddConsoleExporter();
});
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
// 自定义采样器实现
public class CustomSampler : Sampler
{
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
{
// 获取当前请求的URL路径
var requestPath = samplingParameters.Tags.GetTagValue("http.url") as string;
if (!string.IsNullOrEmpty(requestPath) && requestPath.Contains("/api/order"))
{
return new SamplingResult(SamplingDecision.RecordAndSample);
}
return new SamplingResult(SamplingDecision.Drop);
}
}
添加自定义追踪跨度
除了自动埋点采集的信息,还可以在业务代码中手动添加自定义跨度,补充业务维度的追踪信息:
using Microsoft.AspNetCore.Mvc;
using OpenTelemetry.Trace;
namespace OrderService.Controllers;
[ApiController]
[Route("api/order")]
public class OrderController : ControllerBase
{
private readonly Tracer _tracer;
public OrderController(TracerProvider tracerProvider)
{
// 获取当前服务的Tracer实例
_tracer = tracerProvider.GetTracer("OrderService", "1.0.0");
}
[HttpGet("{orderId}")]
public async Task<IActionResult> GetOrderById(string orderId)
{
// 创建自定义跨度,记录查询订单的业务逻辑
using var span = _tracer.StartActiveSpan("QueryOrderFromDb");
try
{
// 添加跨度属性,记录订单ID信息
span.SetAttribute("order.id", orderId);
// 模拟数据库查询逻辑
await Task.Delay(100);
// 模拟查询成功
span.SetAttribute("order.query.success", true);
return Ok(new { OrderId = orderId, OrderName = "测试订单" });
}
catch (Exception ex)
{
// 标记跨度为异常状态,记录异常信息
span.SetStatus(Status.Error.WithDescription(ex.Message));
span.RecordException(ex);
return StatusCode(500, "查询订单失败");
}
}
}
上下文传播与跨服务调用
分布式追踪的核心是上下文传播,OpenTelemetry会自动处理HTTP调用时的上下文传递,只要在发起HTTP调用时使用注入的HttpClient实例即可:
using Microsoft.AspNetCore.Mvc;
using OpenTelemetry.Trace;
namespace OrderService.Controllers;
[ApiController]
[Route("api/order")]
public class OrderController : ControllerBase
{
private readonly HttpClient _httpClient;
private readonly Tracer _tracer;
public OrderController(HttpClient httpClient, TracerProvider tracerProvider)
{
_httpClient = httpClient;
_tracer = tracerProvider.GetTracer("OrderService", "1.0.0");
}
[HttpPost]
public async Task<IActionResult> CreateOrder()
{
using var span = _tracer.StartActiveSpan("CreateOrder");
// 调用库存服务扣减库存,上下文会自动传递到库存服务
var response = await _httpClient.PostAsync("http://inventory-service/api/inventory/deduct", null);
if (response.IsSuccessStatusCode)
{
span.SetAttribute("inventory.deduct.success", true);
return Ok("订单创建成功");
}
else
{
span.SetAttribute("inventory.deduct.success", false);
return StatusCode(500, "库存扣减失败");
}
}
}
数据导出到后端存储
本地控制台导出只适合调试,生产环境需要将追踪数据导出到Jaeger、Zipkin等后端存储系统,以导出到支持OTLP协议的存储为例,配置代码如下:
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// 从配置文件读取OTLP导出地址
var otlpEndpoint = builder.Configuration.GetValue<string>("Otlp:Endpoint") ?? "http://localhost:4317";
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
{
tracerProviderBuilder
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(serviceName: "OrderService", serviceVersion: "1.0.0"))
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
// 配置OTLP导出器,导出数据到后端存储
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(otlpEndpoint);
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
注意事项
- 自动埋点组件会自动采集大量信息,生产环境可以根据需要过滤不必要的采集内容,避免数据冗余
- 采样策略需要根据业务场景合理配置,高并发场景下建议采用概率采样降低开销
- 自定义跨度要及时释放,避免跨度未关闭导致追踪数据不完整
- 上下文传播依赖HTTP头的正确传递,如果使用自定义的HTTP客户端调用,需要手动处理上下文注入逻辑
C#OpenTelemetry_Tracing分布式追踪ASP.NET_Core修改时间:2026-06-30 04:48:46