news 2026/9/13 14:19:02

Mastra 与 Hono 多服务分布式链路追踪实战:基于 OtelBridge 与 Arize Phoenix 打通三服务调用链

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mastra 与 Hono 多服务分布式链路追踪实战:基于 OtelBridge 与 Arize Phoenix 打通三服务调用链

Mastra 与 Hono 多服务分布式链路追踪实战:基于 OtelBridge 与 Arize Phoenix 打通三服务调用链

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

本指南以 Mastra 仓库中的hono-multi示例为蓝本,讲解如何用 Mastra 的OtelBridge将 Agent 产生的内部 Span 无缝接入 OpenTelemetry(OTEL)生态,让跨三个 Hono 服务的 HTTP 调用、Mastra Agent 运行与 LLM 调用共享同一条 trace ID,并在 Arize Phoenix 中可视化。读完本文,你将掌握 OtelBridge 的工作原理、共享 OTEL 插桩的搭建方式,以及一套可复制、可验证的多服务分布式追踪落地流程。

示例概览:一条贯穿三个服务的调用链

示例位于 observability/_examples/otel-bridge/hono-multi,包含三个独立服务与一个共享插桩包,整体调用拓扑如下:

service-one (port 3000) ↓ HTTP request service-two (port 3001) ↓ HTTP request service-mastra (port 4000) → Mastra agent with OtelBridge

注意:README 中标注 service-mastra 端口为 4000,但实际源码(service-mastra/src/index.ts)中监听端口为3002,集成测试(src/integration.test.ts)也按 3000/3001/3002 三端口验证。部署时以实际源码为准。

所有服务统一使用 OpenTelemetry 插桩,trace 数据最终汇入 Arize Phoenix 可视化。其核心价值在于演示trace context 的正确传播:如果没有 OtelBridge,Mastra 会为 Agent 运行创建新的 trace ID,导致与其他服务的 trace 断链;接入后,Mastra 的 Span 与上游 HTTP Span 共享同一个 trace ID,形成完整的链路。

OtelBridge 原理:Mastra 可观测性与 OTEL 的桥梁

OtelBridge 是@mastra/otel-bridge包导出的核心类,其实现位于 observability/otel-bridge/src/bridge.ts。从源码结构看,它通过三种机制完成双向打通:

  1. 读取 trace context:从传入 HTTP 请求的traceparent头中解析 W3C 上下文,让 Mastra 的根 Span 挂接到外部链路之下;
  2. 创建真实 OTEL Span:当 Mastra 创建内部 Span(createSpan)时,同步调用全局 TracerProvider 的startSpan,生成真正的 OTEL Span,而非 Mastra 内部私有的 Span;
  3. 维护层级关系:通过otelSpanMap缓存「Mastra spanId ↔ OTEL span/context」的映射,在 Span 结束时用 SpanConverter(来自@mastra/otel-exporter)将 Mastra 属性转换为符合 OTEL 语义约定的属性并end()该 Span。

值得注意的两个细节:

  • 若当前进程没有注册 OTEL SDK,全局 Tracer 返回的 non-recording span 上下文无效(全零 ID),createSpan会提前返回undefined,让 Mastra 回退到自有的 ID 生成逻辑,避免 ID 碰撞(见 bridge.ts#L229-L238);
  • executeInContext/executeInContextSync会把函数放进已存储的 OTEL context 中执行,从而让 Mastra Span 内部的任何 OTEL 插桩代码(HTTP 客户端、数据库驱动等)都能以正确的父子关系挂到当前 Span 下。

在 service-mastra 中接入方式非常简洁(service-mastra/src/index.ts):

import { Mastra } from '@mastra/core'; import { Observability, SensitiveDataFilter } from '@mastra/observability'; import { OtelBridge } from '@mastra/otel-bridge'; export const mastra: Mastra = new Mastra({ observability: new Observability({ configs: { default: { serviceName: 'tracing-exp', spanOutputProcessors: [new SensitiveDataFilter()], bridge: new OtelBridge(), }, }, }), agents: { 'test-agent': testAgent }, });

其中serviceName用于标识服务;SensitiveDataFilter会在 Span 输出前过滤敏感数据;bridge: new OtelBridge()即打通 OTEL 的关键配置。

环境准备与三步搭建

运行本示例需要以下环境:

  • Docker:用于启动 Arize Phoenix(本地开源、免费的可观测性后端)
  • Node.js 22.13.0 及以上
  • pnpm >= 10(Monorepo 包管理)
  • OpenAI API Key:service-mastra 通过openai/gpt-4o-mini调用大模型

第一步:启动 Arize Phoenix

在示例根目录执行:

pnpm docker:up

该命令读取 docker-compose.yml,拉起arizephoenix/phoenix:latest镜像:

  • UI 地址:http://localhost:6006
  • OTLP 接收端点:http://localhost:6006/v1/traces
  • 同时暴露 4317 端口(可选的 gRPC OTLP 接收器)

第二步:配置 OpenAI API Key

在示例根目录创建.env文件:

echo "OPENAI_API_KEY=your-key-here" > .env

第三步:安装依赖并构建

pnpm install pnpm build

pnpm build会依次构建共享插桩包@mastra/hono-multi-instrumentationservice-mastra(见根 package.json)。必须先构建再启动,因为 service-mastra 以 workspace 依赖引用共享插桩包。

启动三个服务

需要开启三个终端窗口分别启动服务:

终端 1 - service-one(端口 3000)

cd observability/_examples/otel-bridge/hono-multi/service-one pnpm start

终端 2 - service-two(端口 3001)

cd observability/_examples/otel-bridge/hono-multi/service-two pnpm start

终端 3 - service-mastra(端口 3002)

cd observability/_examples/otel-bridge/hono-multi/service-mastra pnpm start

每个服务的start脚本都会先通过--import=./src/instrumentation.ts预加载遥测初始化(以 service-mastra 为例,见 service-mastra/package.json),确保telemetry 在任何 HTTP 请求处理之前完成初始化——这是 trace context 正确传播的前提之一。

验证链路:发一次请求看全链路

向入口服务发请求:

curl http://localhost:3000/service-one

期望返回:

{ "message": "service-one → service-two → service-mastra (agent: Hello there friend!)" }

调用链实际流向(对应各服务源码):service-one 的/service-one路由通过 service-two-client.ts 用fetch请求http://localhost:3001/service-two;service-two 再通过 service-mastra-client.ts 请求http://localhost:3002/service-mastra;最终 service-mastra 路由调用mastra.getAgent('test-agent')执行生成(见 service-mastra/src/index.ts#L42-L47),并把traceId一并返回。

在 Phoenix 中查看 Trace

  1. 打开 http://localhost:6006
  2. 应能看到一条包含三个服务全部 Span 的 trace,包含:
    • service-one、service-two 的 HTTP Span
    • service-mastra 的 Agent 运行 Span
    • LLM generation Span
    • 所有 Span 共享同一个 trace ID

架构细节与源码剖析

service-one:入口服务

  • 使用 Hono +@hono/otelhttpInstrumentationMiddleware做自动插桩(service-one/src/index.ts);
  • 通过fetch调用下游(UndiciInstrumentation自动捕获该调用产生的 client span);
  • 响应中包含从下游逐层透传的traceId

service-two:中间服务

  • 接收 service-one 请求并转发给 service-mastra,是验证HTTP trace context 传播的关键一跳;
  • 同样使用httpInstrumentationMiddleware插桩,中间不加任何额外处理,依靠 W3Ctraceparent头完成上下文延续(service-two/src/index.ts)。

service-mastra:Mastra + OtelBridge

  • 通过MastraServer@mastra/hono的 HonoServerAdapter)注册 Agent 路由,并附加openapi.json、Swagger UI(service-mastra/src/index.ts#L33-L50);
  • Agent 定义见 service-mastra/src/agent.ts,使用openai/gpt-4o-mini
  • 关键点:httpInstrumentationMiddleware()在 Mastra 路由注册之前通过app.use('*', ...)挂载,确保每个入站请求先进入 OTEL 上下文,再进入 Mastra 逻辑。

共享插桩包:统一的 OTEL 配置

所有服务共用@mastra/hono-multi-instrumentation(源码在 instrumentation/src/index.ts),它负责:

  1. NodeSDK配置 resource(服务名默认tracing-exp,可用环境变量ARIZE_PROJECT_NAME覆盖);
  2. 注册HttpInstrumentationUndiciInstrumentation自动插桩 HTTP 服务端与fetch客户端;
  3. 使用W3CTraceContextPropagator作为传播器(解析/注入traceparent头);
  4. 通过BatchSpanProcessor+ArizeOpenInferenceOTLPTraceExporter批量导出 trace 到 Phoenix(端点默认http://localhost:6006/v1/traces,可用OTEL_EXPORTER_OTLP_ENDPOINT覆盖)。

导出器源码在 instrumentation/src/arize-exporter.ts,它基于 OTLP proto exporter 扩展,额外做了两项工作:

  • 将 Mastra 的gen_ai.prompt/gen_ai.completion属性转换为 OpenInference 的gen_ai.input.messages/gen_ai.output.messages结构(convertMastraMessagesToGenAIMessages,best-effort 转换,失败时原样返回);
  • 将属性转为gen_ai语义约定,供 Phoenix 以 AI 应用视图渲染;
  • 支持 Arize AX(云端)与 Phoenix(本地)两种模式:传入spaceId时走 Arize AX 头与https://otlp.arize.com/v1/traces端点;只传apiKey时走标准Authorization: Bearer头。

用集成测试自动验证传播正确性

示例还提供了完整的集成测试(src/integration.test.ts),可自动化验证「三服务 + Phoenix」整条链路。其运行前提与 README 中的说明一致:

  1. Phoenix 已在运行:pnpm docker:up
  2. 已配置 OpenAI API Key(两种方式任选):
    • 推荐:在示例根目录创建.env文件;
    • 或运行测试前设置环境变量。
  3. 已完成构建:pnpm build
# 使用 .env 文件(推荐) pnpm test # 或使用内联环境变量 OPENAI_API_KEY=your-key pnpm test

测试的行为(从源码可以确认):

  • 模块加载时先探测 Phoenix 的/graphql端点可用性,以及OPENAI_API_KEY是否存在;任一不满足则整组测试标记为 skip 并打印原因(integration.test.ts#L38-L47);
  • beforeAll依次以子进程启动三个服务,等待日志中出现 "Server listening" 判定就绪;
  • 通过http://localhost:3000/service-one发起请求,用正则"traceId":"([a-f0-9]{32})"从响应中提取 32 位 hex trace ID;
  • 通过 Phoenix 的 GraphQLgetTraceByOtelId查询该 trace,轮询等待(最长 15 秒);
  • 断言要点:
    • 存在mastra.span.type = agent_run的 Span;
    • 存在model_generation的 LLM Span;
    • 所有 Span 共享唯一 trace ID(traceIds.length === 1);
    • agent_runSpan 有父 Span 且父 Span 存在于同一 trace 中;
    • LLM Span 的parentId等于 Agent Span 的spanId(父子关系正确);
  • afterAll按逆序优雅停止三个服务(SIGTERM,5 秒超时后强制 SIGKILL)。

常见问题排查

出现断链(trace ID 不一致)

这通常说明 trace context 传播失败,按顺序检查:

  1. 三个服务是否都使用了共享插桩包——检查各自instrumentation.ts是否调用了startTelemetry()
  2. service-mastra 是否配置了 OtelBridge——缺失bridge: new OtelBridge()时 Mastra 会生成新的 trace ID;
  3. telemetry 是否在创建 Hono app 之前初始化——注意start脚本中的--import=./src/instrumentation.ts预加载顺序,这是插桩能够捕获 HTTP 请求的前提。

Agent 调用报错

  1. 确认.env(示例根目录)中存在OPENAI_API_KEY
  2. 确认 OpenAI API 网络可达;
  3. 确认账号余额/额度充足。

清理与关闭

# 停止 Phoenix pnpm docker:down # 停止三个服务:在每个终端按 Ctrl+C

三个服务都实现了SIGTERM/SIGINT优雅退出:先关闭 HTTP server,再调用stopTelemetry()触发 SDKshutdown()冲刷剩余 Span,确保进程退出前数据完整导出(参考 service-one/src/index.ts#L37-L57 等实现)。

与上游示例的对比与启示

该示例基于社区的 Hono tracing 示例改造而来,核心改进有四方面:改用本地开源的 Arize Phoenix(替代云端 Arize);引入 OtelBridge 修复 trace 传播断链问题;通过 workspace 依赖融入 Mastra Monorepo 直接复用最新包;并最终用集成测试证明了「trace 能正确贯穿所有服务」这一修复成果。

对于在生产环境接入 Mastra 可观测性的开发者,本示例给出了一条清晰的落地路径:共享插桩包统一 OTEL 配置 → 中间服务靠 W3C 传播器自然透传 → 末端服务用 OtelBridge 把 Mastra 内部 Span 变为真实 OTEL Span → 集成测试保障链路不回归。这套模式同样适用于任何基于 OTEL 的后端(如 Jaeger、Tempo、OTLP Collector 等),只需替换导出器端点即可。

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 14:13:09

Sa-Token 踢人下线详解:强制注销、踢人下线与顶人下线的原理与实践

Sa-Token 踢人下线详解:强制注销、踢人下线与顶人下线的原理与实践 【免费下载链接】Sa-Token ✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录…

作者头像 李华
网站建设 2026/9/13 14:13:00

论文降重与文本改写:如何避开不靠谱服务,守住查重底线

一、为什么降重这件事,越来越让人头疼? 每到毕业季,论文查重就成了悬在无数同学头上的“达摩克利斯之剑”。学校对重复率的要求越来越严格,知网、维普、格子达等查重系统的算法也在不断升级,单纯靠“换几个词”已经很…

作者头像 李华
网站建设 2026/9/13 14:12:07

GenOffice如何重构现代办公工作流

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

作者头像 李华
网站建设 2026/9/13 14:11:57

YOLOv8-obb+TensorRT实现芯片引脚高精度实时检测

简介:本资源是一套基于YOLOv8-OBB(旋转框检测)的芯片引脚缺陷检测完整项目,面向人工智能、电子信息、自动化等专业的在校学生、教师及企业研发人员,解决高精度工业微小目标定位与缺陷识别难题,适用于毕业设…

作者头像 李华