ASP.NET Core 实战:用 OTel Baggage 经 HttpClient 自动传递跨服务上下文
示例工程【免费下载链接】practical-aspnetcorePractical samples of ASP.NET Core 11, 10, 9, 8.0, 7.0, 6.0, 5.0, 3.1, 2.2, and 2.1,projects you can use. Readme contains explanations on all projects.项目地址https://gitcode.com/gh_mirrors/pr/practical-aspnetcore点击查看免费下载本指南基于 practical-aspnetcore 仓库中的 open-telemetry-4 示例讲解如何在 ASP.NET Core 应用中记录 OpenTelemetryOTelBaggage并借助 HttpClient 探针自动以baggageHTTP 头把用户自定义属性传给下游 HTTP 请求。读完本文你将掌握Activity.AddBaggage的写入方式、Baggage 与 Span Attribute 的区别、baggage头的自动注入与手动注入两种路径以及如何在接收端读取并验证传递结果。一、什么是 OTel Baggage在 OpenTelemetry 中Baggage是随请求一起在服务之间传播的一组键值对key/value pairs由 W3CBaggage 规范定义。与 Trace 中的 Span 不同Span Attribute属性只属于当前 Span记录在当前服务的某个 trace 段上不会随请求传递给下游服务见仓库中的 open-telemetry-3 示例它演示了如何用SetTag记录project、location属性。Baggage绑定在请求上下文中可以跨越进程边界通过标准的baggageHTTP 请求头传递给下一个服务。典型使用场景包括把用户 ID、租户 ID、请求来源、A/B 实验分组等业务上下文从入口服务一路带到链路下游供各服务做路由、限流或观测过滤而无需在每个服务里重复解析业务参数。在 .NET 的System.Diagnostics.Activity模型中当前请求的上下文就是Activity.Current我们可以直接在它上面附加 Baggage。二、项目结构与依赖配置示例位于仓库 projects/open-telemetry/open-telemetry-4 目录只有三个文件open-telemetry-4/ ├── Program.cs # 全部逻辑 ├── Readme.md # 示例说明 └── open-telemetry-4.csproj # 项目文件open-telemetry-4.csproj 目标框架为net10.0仓库根目录的 global.json 将 SDK 锁定为 10.0.0 并允许rollForward: major引用的 OTel 相关包均为1.17.0Project SdkMicrosoft.NET.Sdk.Web PropertyGroup TargetFrameworknet10.0/TargetFramework ImplicitUsingstrue/ImplicitUsings /PropertyGroup ItemGroup PackageReference IncludeOpenTelemetry.Exporter.Console Version1.17.0 / PackageReference IncludeOpenTelemetry.Extensions.Hosting Version1.17.0 / PackageReference IncludeOpenTelemetry.Instrumentation.AspNetCore Version1.17.0 / PackageReference IncludeOpenTelemetry.Instrumentation.http Version1.17.0 / /ItemGroup /Project与仓库中前三个 OTel 示例open-telemetry-1、open-telemetry-2、open-telemetry-3相比本示例的关键差异是引入了OpenTelemetry.Instrumentation.HttpHTTP 客户端探针——正是它负责在出站请求上自动注入baggage头。注意 NuGet 包名大小写不敏感源码中写成的http与官方包名Http等价。三、核心实现拆解Program.cs 全部代码如下using System.Diagnostics; using OpenTelemetry.Trace; using OpenTelemetry.Resources; var builder WebApplication.CreateBuilder(); builder.Services.AddOpenTelemetry().WithTracing(b { b.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(builder.Environment.ApplicationName)) .AddHttpClientInstrumentation(); }); builder.Services.AddHttpClient(); builder.Logging.SetMinimumLevel(LogLevel.Information); WebApplication app builder.Build(); app.MapGet(/, async (HttpRequest request, IHttpClientFactory clientFactory) { Activity.Current?.AddBaggage (project, practical-aspnetcore); Activity.Current?.AddBaggage (location, Cairo); var baggage string.Join(,, Activity.Current.Baggage.ToDictionary(b b.Key, b b.Value).Select(x x.Key x.Value)); var client clientFactory.CreateClient(); //client.DefaultRequestHeaders.Add(baggage, baggage); var url request.Scheme :// request.Host /baggage; app.Logger.LogInformation(REQUEST URL url); var response await client.GetAsync(url); return Results.Text(Check the log, text/plain); }); app.MapGet(/baggage, (HttpRequest request) { var baggage request.Headers[baggage]; app.Logger.LogInformation($BAGGAGE VALUES {baggage}); return Results.Ok(); }); app.Run();3.1 启动阶段注册 OpenTelemetry 与 HTTP 客户端builder.Services.AddOpenTelemetry().WithTracing(b { b.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(builder.Environment.ApplicationName)) .AddHttpClientInstrumentation(); }); builder.Services.AddHttpClient();ResourceBuilder.CreateDefault().AddService(builder.Environment.ApplicationName)给 trace 资源打上service.name值为当前应用名与 open-telemetry-1 的用法一致。AddHttpClientInstrumentation()启用 HTTP 客户端探针监听出站请求并完成上下文含 Baggage注入。builder.Services.AddHttpClient()注册IHttpClientFactory后面通过工厂创建HttpClient。builder.Logging.SetMinimumLevel(LogLevel.Information)把日志级别调到 Information确保关键日志能在控制台看到本示例没有配置AddConsoleExporter因此观察点全部在应用日志上。3.2 写入 BaggageAddBaggage在根路由处理函数中通过两行代码把用户自定义属性写入当前 Activity 的 BaggageActivity.Current?.AddBaggage (project, practical-aspnetcore); Activity.Current?.AddBaggage (location, Cairo);这里Activity.Current是当前 HTTP 请求对应的 ActivityASP.NET Core 内建的Microsoft.AspNetCoreActivitySource 提供从 .NET 11 起该 Source 会原生填充 OTel 语义属性早期版本则依赖OpenTelemetry.Instrumentation.AspNetCore补充参见 net11/native-otel-tracing 说明。AddBaggage(key, value)以键值对形式把业务上下文挂到当前请求上下文上。紧随其后的这行代码展示了如何把 Baggage 序列化成标准的keyvalue列表var baggage string.Join(,, Activity.Current.Baggage.ToDictionary(b b.Key, b b.Value).Select(x x.Key x.Value));它先把Activity.Current.BaggageIEnumerableKeyValuePairstring, string转成字典再拼接为projectpractical-aspnetcore,locationCairo这样的 W3C Baggage 字符串——这正是手动注入方案下一节需要的头值。3.3 自动注入与手动注入两条路径示例中真正发起下游请求的代码是var client clientFactory.CreateClient(); //client.DefaultRequestHeaders.Add(baggage, baggage); var url request.Scheme :// request.Host /baggage; app.Logger.LogInformation(REQUEST URL url); var response await client.GetAsync(url);这里有两条传递路径值得重点区分自动路径示例实际采用AddHttpClientInstrumentation()启用后OpenTelemetry .NET SDK 会使用默认的传播器组合CompositeTextMapPropagator内含TraceContextPropagator与BaggagePropagator在出站请求上自动注入baggage头。因此上面被注释掉的手动加头代码不需要启用下游端点也能收到 Baggage。手动路径被注释的备选方案client.DefaultRequestHeaders.Add(baggage, baggage);直接复用上一节拼接好的 Baggage 字符串把baggage头手动写到HttpClient的默认请求头上。这一行注释在源码中Program.cs说明在开启 HTTP 客户端探针后自动注入已足够当你不想依赖探针、或需要精细控制头值时可取消注释并移除探针作为降级方案。3.4 接收端读取/baggage 端点app.MapGet(/baggage, (HttpRequest request) { var baggage request.Headers[baggage]; app.Logger.LogInformation($BAGGAGE VALUES {baggage}); return Results.Ok(); });下游端点直接从请求头request.Headers[baggage]取出 Baggage 值并写日志。整个示例形成一条完整回路GET /写入 Baggage → 借助 HttpClient 以baggage头发给GET /baggage→ 接收端读取头并输出BAGGAGE VALUES ...。四、运行与验证在仓库中进入示例目录并启动仓库根 global.json 指定 SDK 10.0.0dotnet run --project projects/open-telemetry/open-telemetry-4应用默认监听本地端口参考同仓库 open-telemetry-2 的运行输出地址为http://localhost:5000。随后访问入口端点curl http://localhost:5000/浏览器/curl 会得到Check the log文本真正的结果要看应用控制台日志。预期会依次出现两类日志推断自 Program.cs 的逻辑info: ... REQUEST URL http://localhost:5000/baggage info: ... BAGGAGE VALUES projectpractical-aspnetcore,locationCairoBAGGAGE VALUES一行即为验证结果GET /中通过AddBaggage写入的project与location两个键值已经以 W3Cbaggage头的形式传递到了/baggage端点并被成功解析。五、Baggage 与 Span Attribute 的取舍仓库中的 OTel 系列示例正好给出了同一组业务数据的两种记录方式open-telemetry-3用Activity.Current?.SetTag(project, practical-aspnetcore)写入Span Attribute控制台导出的 Span 中出现project、location标签但属性只留在本服务的当前 Span 内。open-telemetry-4本文用AddBaggage写入Baggage属性跟随baggage头跨服务传递。实际选型建议需要在本服务 trace 中检索/过滤、且不希望泄漏给下游 → 用 Span Attribute。需要随请求传给下游服务做决策或观测如租户隔离、灰度标记→ 用 Baggage。Baggage 会随每个出站请求传播应避免放入敏感信息如令牌、个人数据并注意控制键值数量与大小防止头膨胀影响链路性能。若想在 Baggage 之外同时让下游能按业务维度聚合 trace可结合 Attribute 一起记录二者并不互斥。六、小结通过本示例可以确认一条完整链路Activity.Current.AddBaggage写入业务上下文 →AddHttpClientInstrumentation按 W3C Baggage 规范自动注入baggage头 → 下游服务从请求头读取。这为 ASP.NET Core 分布式应用中用户属性 / 租户信息等轻量上下文跨服务透传提供了一个开箱即用的标准化方案也为后续把 Baggage 与 OTel 的 trace、metrics 打通留出了空间。赞分享示例工程【免费下载链接】practical-aspnetcorePractical samples of ASP.NET Core 11, 10, 9, 8.0, 7.0, 6.0, 5.0, 3.1, 2.2, and 2.1,projects you can use. Readme contains explanations on all projects.项目地址https://gitcode.com/gh_mirrors/pr/practical-aspnetcore点击查看免费下载相关推荐whichllm跨平台支持Windows、Linux与macOS硬件检测差异解析whichllm跨平台支持Windows、Linux与macOS硬件检测差异解析 whichllm是一款能够帮助用户找到在本地硬件上实际运行并表现最佳的LLM人工智能大模型本地部署CLImirrord 会话上下文如何穿越对象存储S3/GCS 签名上传链路的 baggage 传递实战mirrord 会话上下文如何穿越对象存储S3/GCS 签名上传链路的 baggage 传递实战 本文基于 mirrord Header Propagatio开发工具云原生CLIOpenCOOD中的压缩技术如何在有限带宽下实现高效协同感知OpenCOOD中的压缩技术如何在有限带宽下实现高效协同感知 OpenCOOD作为开源协同感知框架通过先进的压缩技术解决了车辆间通信的带宽瓶颈问题实现了在自动驾驶人工智能计算机视觉上一篇Micro框架GraphQL订阅重连机制客户端自动恢复连接下一篇Cream项目完全指南微软NAS与ViT技术大集合创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Swift 错误处理实战指南:从 Guard、Throw、try/catch 到断言与 Result 的完整体系(Awesome-Swift-Education 专题解读)

Swift 错误处理实战指南:从 Guard、Throw、try/catch 到断言与 Result 的完整体系(Awesome-Swift-Education 专题解读)

教程文档 【免费下载链接】Awesome-Swift-Education :fire: Learn some Swift 项目地址: https://gitcode.com/gh_mirrors/aw/Awesome-Swift-Education 点击查看 免费下载 本指南以开源仓库 Awesome-Swift-Education 中 Swift /Error Handling/ErrorHandling.md 学…

2026/10/15 2:20:19 阅读更多 →
运维实习第一阶段:从零建立生产环境认知与最小技能集

运维实习第一阶段:从零建立生产环境认知与最小技能集

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 2:20:19 阅读更多 →
降本增效利器:数据治理在大型企业精细化管理中的核心价值

降本增效利器:数据治理在大型企业精细化管理中的核心价值

一、大型企业的数据治理“成本困局”过去五年,大量大型企业完成了数据中台的基础搭建,打通了ERP、CRM、MES等核心业务系统。然而,一个普遍困境随之浮现:平台建好了,数据接进来了,业务部门却依然感受不到变化…

2026/10/15 2:20:19 阅读更多 →

最新新闻

WinPython 3.4.3.1 变更历史深度解读:从包清单到 changelog 生成机制

WinPython 3.4.3.1 变更历史深度解读:从包清单到 changelog 生成机制

开发工具构建工具CLI包管理器 【免费下载链接】winpython A free Python-distribution for Windows platform, including prebuilt packages for Scientific Python. 项目地址: https://gitcode.com/gh_mirrors/wi/winpython 点击查看 免费下载 本篇技术指南以 Win…

2026/10/15 2:55:30 阅读更多 →
Qt 6 CMake 项目配置与命令行构建实战指南:从定位 qt-cmake 到 Ninja 增量构建(QGroundControl 实践)

Qt 6 CMake 项目配置与命令行构建实战指南:从定位 qt-cmake 到 Ninja 增量构建(QGroundControl 实践)

无人机智能硬件 【免费下载链接】qgroundcontrol Cross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows) 项目地址: https://gitcode.com/gh_mirrors/qg/qgroundcontrol 点击查看 免费下载 本篇技术指南围绕 tools/skills/qt-…

2026/10/15 2:55:30 阅读更多 →
LLM-WIKI 测试 demo1

LLM-WIKI 测试 demo1

请在 D:\workspace\llm-wiki 初始化/补齐一个基于 Karpathy LLM Wiki 思路的个人知识库系统。 当前目录可能已有文件,请只创建缺失项;已有文件先读取、对比并汇报差异,未经我确认,不要覆盖、移动、删除或重命名。 重要约束&#x…

2026/10/15 2:55:30 阅读更多 →
巧用 Nginx Map 指令:通过请求头动态代理到不同后端服务

巧用 Nginx Map 指令:通过请求头动态代理到不同后端服务

巧用 Nginx Map 指令:通过请求头动态代理到不同后端服务 1. 引言 在现代微服务架构或灰度发布场景中,我们常常需要根据请求的某些特征(如用户身份、设备类型、版本号等)将流量动态路由到不同的后端服务。Nginx 作为高性能的反向代…

2026/10/15 2:55:30 阅读更多 →
员工生日关怀方案落地指南:从图书定制到聚会执行的全流程避坑

员工生日关怀方案落地指南:从图书定制到聚会执行的全流程避坑

简介:员工生日关怀方案.doc是一份面向企业人力资源从业者、行政管理者及团队文化建设负责人的实操型文档,围绕如何用生日关怀提升员工归属感与组织凝聚力展开。方案从策划目的与目标切入,系统梳理了生日图书赠送、定制书签、经理亲笔寄语、分…

2026/10/15 2:55:30 阅读更多 →
液冷技术:数据中心高效散热与节能新方案

液冷技术:数据中心高效散热与节能新方案

1. 液冷技术为何成为算力中心的新宠?最近两年,数据中心行业最火的话题莫过于液冷技术。传统风冷系统在应对高密度计算时已经捉襟见肘——一台8卡GPU服务器的散热需求就高达3-4kW,整个机柜动辄需要30kW以上的散热能力。而液体的比热容是空气的…

2026/10/15 2:54:29 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →