当前位置: 首页 > news >正文

ABP VNext + OpenTelemetry + Jaeger:分布式追踪与调用链可视化

ABP VNext + OpenTelemetry + Jaeger:分布式追踪与调用链可视化 🚀


📚 目录

  • ABP VNext + OpenTelemetry + Jaeger:分布式追踪与调用链可视化 🚀
    • 背景与动机 🌟
    • 环境与依赖 📦
      • 必装 NuGet 包
    • 系统架构概览 🖥️
    • 跑通示例 🚀
      • `Program.cs`
      • `docker-compose.yml` 🐳
    • 自动 + 手动埋点 🔍
      • 自动埋点
      • 自定义业务 Span
    • 异常与状态码标记 ⚠️
    • 日志与 Metrics 关联 📑
    • Jaeger 部署与高可用 🏗️
    • 采样策略与性能优化 🛡️
    • 扩展:OTel Collector & Grafana Tempo 🔗


版本说明:本文基于 OpenTelemetry.Extensions.Hosting >=1.4.0 编写,推荐使用统一的 .AddOpenTelemetry().WithTracing(...).WithMetrics(...) API。

TL;DR

  1. 提供完整 Program.cs + docker-compose.yml 示例 🏃‍♂️
  2. 自动 + 手动埋点:支持 HTTP/gRPC、数据库、外部调用与自定义 Span 🔍
  3. 高性能采样:Parent-Based + TraceIdRatioBasedSampler,动态可配 ⚙️
  4. 生产级部署:Batch 模式、OTel Collector、日志/Metrics 关联、异常标记 🚀

背景与动机 🌟

在分布式微服务架构中,调用链横跨多个进程与网络节点,“谁调用了谁”、“哪些环节慢”成为痛点。
OpenTelemetry(OTel)与 Jaeger 提供了开源、无侵入的端到端分布式追踪解决方案,帮助我们:

  • 自动化采集:入站 HTTP/gRPC、数据库、外部 HTTP 等一键埋点 📡
  • 自定义业务 Span:灵活埋点关键业务逻辑 🛠️
  • 统一可视化:Jaeger UI 或 Grafana Tempo 展示完整调用链 📈

本文基于 ABP VNext 6.x + .NET 6+,演示从零搭建到生产级优化,涵盖自动/手动埋点、采样策略、异常与日志关联等最佳实践。


环境与依赖 📦

  • .NET SDK:6.0+
  • ABP Framework:vNext 6.x
  • OpenTelemetry.Extensions.Hosting:>=1.4.0
  • Jaeger:all-in-one(测试);独立 Agent/Collector/Storage(生产)
  • 可选:OpenTelemetry Collector、Grafana Tempo、Prometheus/Grafana

必装 NuGet 包

dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
dotnet add package OpenTelemetry.Instrumentation.SqlClient
dotnet add package OpenTelemetry.Instrumentation.GrpcNetClient
dotnet add package OpenTelemetry.Instrumentation.GrpcAspNetCore
dotnet add package OpenTelemetry.Exporter.Jaeger
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol

系统架构概览 🖥️

HTTP/gRPC
DB
HTTP
Metrics
Logs
Client
ABP Service A
SQL Server
ABP Service B
Jaeger Collector
Jaeger UI
Prometheus
Grafana Dashboard
OTel Collector
日志后端
Grafana Tempo
  • 采集:入站 HTTP/gRPC、EF Core/SqlClient、HttpClient、gRPC 客户端、日志、Metrics
  • 导出:Trace → Jaeger;Metrics → Prometheus;Logs → OTLP → 日志后端;(可选)Trace → Tempo

跑通示例 🚀

启动 Jaeger (docker-compose)
运行微服务 (dotnet run)
访问业务 API
生成 Trace/Metric/Log 数据
在 Jaeger UI 查看调用链
在 Prometheus 查看 Metrics
在日志后端查看日志

Program.cs

using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Volo.Abp;var builder = WebApplication.CreateBuilder(args);// 1. ABP 模块注册
builder.Services.AddApplication<MyProjectHttpApiHostModule>();// 2. OpenTelemetry 注册(Tracing + Metrics)
builder.Services.AddOpenTelemetry()// Tracing.WithTracing(tracing => tracing.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("OrderService", serviceVersion: "1.0.0")).AddAspNetCoreInstrumentation().AddHttpClientInstrumentation().AddSqlClientInstrumentation().AddGrpcAspNetCoreInstrumentation().AddGrpcClientInstrumentation().AddSource("MyCompany.MyProduct").AddJaegerExporter(opts =>{opts.AgentHost = builder.Configuration["Jaeger:Host"];opts.AgentPort = int.Parse(builder.Configuration["Jaeger:Port"]!);}, exportProcessorType: ExportProcessorType.Batch).SetSampler(new ParentBasedSampler(new TraceIdRatioBasedSampler(0.1))))// Metrics.WithMetrics(metrics => metrics.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation().AddPrometheusExporter());// 3. 日志关联 TraceContext
builder.Logging.AddOpenTelemetry(logging =>
{logging.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("OrderService"));logging.IncludeFormattedMessage = true;logging.IncludeScopes = true;logging.ParseStateValues = true;logging.AddOtlpExporter(); // 需要 OpenTelemetry.Exporter.OpenTelemetryProtocol
});var app = builder.Build();// 4. Prometheus 默认抓取端点(/metrics),无需额外配置
app.MapPrometheusScrapingEndpoint();// 5. 启动 ABP 应用
app.InitializeApplication();
app.Run();

docker-compose.yml 🐳

version: '3.8'
services:jaeger:image: jaegertracing/all-in-one:1.45ports:- "6831:6831/udp"- "16686:16686"- "14250:14250"

快速启动

  1. docker-compose up -d
  2. dotnet run --project src/MyProject.HttpApi.Host
  3. 访问 API & http://localhost:16686

自动 + 手动埋点 🔍

自动埋点

  • HTTP/gRPC.AddAspNetCoreInstrumentation().AddGrpcAspNetCoreInstrumentation()
  • 外部调用.AddHttpClientInstrumentation().AddGrpcClientInstrumentation()
  • 数据库.AddSqlClientInstrumentation()
ClientABP APISQL Server外部服务HTTP 请求SQL 查询HTTP 调用响应ClientABP APISQL Server外部服务

自定义业务 Span

public class OrderAppService : ApplicationService
{private static readonly ActivitySource Source = new("MyCompany.MyProduct");public async Task ProcessOrderAsync(Guid orderId){using var activity = Source.StartActivity("ProcessOrder");activity?.SetTag("order.id", orderId);try{await _orderManager.HandleOrderAsync(orderId);}catch (Exception ex){activity?.SetStatus(ActivityStatusCode.Error, ex.Message);activity?.RecordException(ex);throw;}}
}

💡 Tip:通过 ABP 拦截器统一埋点:

public class TraceInterceptor : IInterceptor
{private static readonly ActivitySource Source = new("MyCompany.MyProduct");public void Intercept(IInvocation invocation){using var activity = Source.StartActivity(invocation.Method.Name);activity?.SetTag("abp.service", invocation.TargetType.Name);try{invocation.Proceed();}catch (Exception ex){activity?.SetStatus(ActivityStatusCode.Error, ex.Message);activity?.RecordException(ex);throw;}}
}// 注册拦截器
Configure<AbpInterceptorsOptions>(opts =>opts.Interceptors.Add<TraceInterceptor>()
);

异常与状态码标记 ⚠️

  • activity?.SetStatus(ActivityStatusCode.Error, message) 标记失败 Span
  • activity?.RecordException(ex) 记录异常详情

在 Jaeger UI 中直观区分成功/失败调用链。


日志与 Metrics 关联 📑

TraceContext
OTLP
Metrics
ILogger
OpenTelemetryLogProvider
OTelCollector
LogStore
API
Prometheus
Grafana
  1. 日志

    builder.Logging.AddOpenTelemetry(logging =>logging.AddOtlpExporter());
    
  2. Metrics

    • 自动采集请求计数与时延
    • 自定义 Meter 导出 Prometheus

Jaeger 部署与高可用 🏗️

  • 测试:All-in-One 镜像,一键启动

  • 生产

    • 组件拆分:Agent/Collector/Query/UI 分离部署
    • 后端存储:Cassandra / Elasticsearch / Kafka
    • 安全:启用 TLS、鉴权(mTLS、Token),或通过 OTel Collector 做统一接入与流量控制
    • 多副本:水平扩展与高可用

采样策略与性能优化 🛡️

收到请求
父 Span 有采样?
遵从父决策
随机 < 0.1?
采样
丢弃
  • ParentBasedSampler:跨服务一致决策
  • Batch 模式:减少网络与 CPU 开销
  • 动态调整:环境变量 OTEL_TRACES_SAMPLER / OTEL_TRACES_SAMPLER_ARG
  • 环境差异:开发环境 AlwaysOnSampler;生产环境 5–10%

扩展:OTel Collector & Grafana Tempo 🔗

  • Collector:统一接入、Filter、Auth、转发至 Jaeger/Tempo/Prometheus
  • Grafana Tempo:专注 Trace 存储,结合 Prometheus、Loki 构建全栈 Observability

http://www.dtcms.com/a/275710.html

相关文章:

  • AI 基础概念一:芯片类型和软硬件框架
  • [爬虫知识] 深入理解多进程/多线程/协程的异步逻辑
  • 下载 | Win11 24H2 正式版更新!(ISO映像、年度更新版本、26100.4652、Windows 11)
  • STL——vector的底层实现C++
  • 安全初级作业1
  • 深入理解 QSettings:Qt 中的应用程序配置管理
  • PID控制算法理论学习基础——单级PID控制
  • 手机识别数据集,2628张原始图片,支持yolo,coco json,pasical voc xml等格式的标注
  • Web安全-Linux基础-02-系统基础命令
  • 这个Pandas函数可以自动爬取Web图表
  • Android下一个简单的定时器,每隔一秒输出一个数字
  • 【JVM|类加载】第三天
  • monorepo 发布库 --- 打包文件
  • 多线程的区别和联系
  • 使用sqlmap的SQL Injection注入
  • CSS分层渲染与微前端2.0:解锁前端性能优化的新维度
  • Linux之Zabbix分布式监控篇(一)
  • 电商广告市场惊现“合规黑洞”,企业如何避免亿元罚单
  • phpstudy搭建pikachu靶场
  • 单链表的题目,咕咕咕
  • 区块链平台之以太坊深入解读:技术、经济与生态的全面解析
  • 从OpenMV到执行器:当PID算法开始“调教”舵机
  • 计算机视觉与深度学习 | 基于Matlab的多特征融合可视化指纹识别系统(附完整代码)
  • 迅为RK3588开发板Android13系统super.img的解包和重新组包
  • 【C++】封装红黑树模拟实现set和map
  • GESP2025年6月认证C++三级( 第三部分编程题(2)分糖果)
  • MIG_IP核的时钟系统
  • 《硬件产品经理》第七章:产品开发流程之验证
  • 【6.1.3 漫画分布式锁】
  • 【web站点安全开发】任务1:html基础表单和表格