Mastra 可观测性实战:从 CHANGELOG 读懂 @mastra/braintrust 的演进、核心机制与升级迁移
2026/9/15 1:14:19 网站建设 项目流程

Mastra 可观测性实战:从 CHANGELOG 读懂 @mastra/braintrust 的演进、核心机制与升级迁移

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

Mastra 是面向 AI 应用与 Agent 的现代 TypeScript 框架,其可观测性体系通过独立的@mastra/observability抽象与各类后端对接,@mastra/braintrust即是其中用于将 Mastra 全链路 trace 导出到 Braintrust(用于 LLM 评估与监控)的官方集成包。本文以该包的 CHANGELOG.md 为骨架,逐层拆解它从 0.1.0 到 1.3.13-alpha.1 的能力演进:包括零配置接入、TrackingExporter缓冲与乱序处理机制、Thread 视图重建、评估分数回传、服务端 flush 等关键能力,并结合 tracing.ts、metrics.ts 等源码与仓库内示例,给出可直接落地的接入与升级方案。

一、包定位与最小接入

@mastra/braintrust是 Mastra 的 Braintrust 可观测性提供方(observability provider),官方描述为 “Braintrust observability provider for Mastra - includes tracing and future observability features”。它通过零配置环境变量或显式项目配置,将 Mastra 的 trace 导出到 Braintrust 用于 LLM 评估与监控(见 README.md)。

安装

npm install @mastra/braintrust

当前包的依赖与运行前提(见 package.json):

  • 运行时依赖@mastra/observability(workspace 内联)、braintrust@^3.24.0(v1.3.4 起从^3.22.0升级而来);
  • peerDependencies@mastra/core>=1.16.0-0 <2.0.0-0)、zod^3.25.34 || ^4.0.0);
  • 引擎要求node >= 22.13.0(该门槛由 1.0.0 版本确立)。

最小接入示例

在 Mastra 实例上挂载Observability,并在configs.braintrust中配置serviceNameexporters(源自 README.md 的 Usage 示例):

import { Mastra } from '@mastra/core/mastra'; import { Observability } from '@mastra/observability'; import { BraintrustExporter } from '@mastra/braintrust'; export const mastra = new Mastra({ observability: new Observability({ configs: { braintrust: { serviceName: 'my-service', exporters: [new BraintrustExporter()], }, }, }), });

注意:从 1.0.0 起,可观测性配置要求显式导入并实例化Observability(传入实例而非纯对象),这是早期版本的破坏性变更之一,详见下文“稳定版 1.0.0 的重大变更”。

二、零配置:环境变量驱动

CHANGELOG 在 1.0.0 版本中引入了 “zero-config environment variable support for all exporters” 能力(PR #11686):所有可观测性导出器都支持通过环境变量零配置启动,实例化导出器时无需任何参数。对 Braintrust 而言,涉及两个环境变量:

  • BRAINTRUST_API_KEY:Braintrust API Key;
  • BRAINTRUST_ENDPOINT:自定义端点地址。

在 tracing.ts 的构造函数中可以看到这一机制的实际落地——配置解析发生在调用父类构造函数之前

constructor(config: BraintrustExporterConfig = {}) { // Resolve env vars BEFORE calling super (config is readonly in base class) const resolvedApiKey = config.apiKey ?? process.env.BRAINTRUST_API_KEY; const resolvedEndpoint = config.endpoint ?? process.env.BRAINTRUST_ENDPOINT; super({ ...config, apiKey: resolvedApiKey, endpoint: resolvedEndpoint, }); // ... }

因此可以直接这样写:

// 零配置:从环境变量读取 BRAINTRUST_API_KEY / BRAINTRUST_ENDPOINT new BraintrustExporter();

优先级规则:显式配置优先于环境变量;若两者都未提供 API Key,导出器会通过setDisabled()进入禁用态,并输出提示信息(“SetBRAINTRUST_API_KEYenvironment variable or pass apiKey in config”),见 tracing.ts。

三、BraintrustExporterConfig配置项全景

结合 tracing.ts 与 CHANGELOG,BraintrustExporterConfig除继承TrackingExporterConfig外,还包含:

配置项类型说明
braintrustLoggerBraintrustLogger可选的 Braintrust logger 实例。提供后可启用上下文集成:Agent 的 trace 可自动嵌套进Eval()/logger.traced()/ 外部父 span
currentSpan() => BraintrustSpan \| undefined当前活跃 span 解析器。当应用与 Mastra 各自解析到不同副本的braintrust包时,传入同一包实例的currentSpan可保证评估 trace 正确嵌套(1.1.0 新增)
apiKeystringBraintrust API Key,未提供 logger 时必填
endpointstring可选自定义端点
projectNamestringBraintrust 项目名,默认mastra-tracing
tuningParametersRecord<string, any>传给 Braintrust logger 的调优参数

继承自TrackingExporterConfig的内存管理参数

1.0.0 版本引入了TrackingExporter基类(PR #11870),改进了三类问题:

  • 乱序 span 处理:先于父 span 到达的 span 会被排队,待依赖可用后再处理;
  • 延迟清理:span 结束后 trace 数据保留一小段时间,以处理迟到更新;
  • 内存管理:对 pending 与 total trace 设置可配置上限,防止内存泄漏。

TrackingExporterConfig新增的配置项及默认值(在 CHANGELOG 中明确给出):

配置项默认值作用
earlyQueueMaxAttempts5排队事件的最大重试次数
earlyQueueTTLMs30000排队事件的 TTL(毫秒)
traceCleanupDelayMs30000完成 trace 的清理延迟(毫秒)
maxPendingCleanupTraces100等待清理 trace 的软上限
maxTotalTraces500trace 总数的硬上限

@mastra/braintrust@mastra/langfuse@mastra/langsmith@mastra/posthog均改用该基类。

四、核心机制:从 span 到 Braintrust trace 的映射

1. Span 类型映射

Braintrust 接受'llm' | 'score' | 'function' | 'eval' | 'task' | 'tool'六种 span 类型。默认映射为task,例外见 tracing.ts:

MastraSpanTypeBraintrust 类型
MODEL_GENERATIONllm
TOOL_CALL/MCP_TOOL_CALL/PROVIDER_TOOL_CALLtool
WORKFLOW_CONDITIONAL_EVAL/WORKFLOW_WAIT_EVENTfunction
其他task

1.2.4 版本还专门为PROVIDER_TOOL_CALL补充了导出器 span 类型映射与时长指标(PR #19261),使由 provider 执行工具产生的 span 在所有可观测平台上都被归类为工具 span。

2. 指标映射与 TTFT

tracing.ts 中,MODEL_GENERATIONspan 的 usage 指标通过 metrics.ts 的formatUsageMetrics()转换。Braintrust 期望的规范指标键与 MastraUsageStats的对应关系如下:

Braintrust 指标键来源(UsageStats
prompt_tokensinputTokens
completion_tokensoutputTokens
tokens两者之和(自动计算)
completion_reasoning_tokensoutputDetails.reasoning
prompt_cached_tokensinputDetails.cacheRead
prompt_cache_creation_tokensinputDetails.cacheWrite

Time-to-first-token(TTFT):1.0.0 版本引入time_to_first_token指标(PR #10840),由流式首个 chunk 到达时捕获的completionStartTime填充,单位为

if (modelAttr.completionStartTime) { payload.metrics.time_to_first_token = (modelAttr.completionStartTime.getTime() - span.startTime.getTime()) / 1000; }

流式调用无需额外代码即可自动上报:

const result = await agent.stream('Hello'); // time_to_first_token 作为 span metrics 自动发送到 Braintrust

此外,1.0.0 中同时修复了 CachedToken 跟踪(PR #11029):缓存 token 计数在所有可观测性导出器中统一修正,Braintrust 的 TTFT 也被纳入修复范围。

3. 消息格式转换与 Thread 视图

Braintrust 的 Thread 视图要求输入/输出遵循其期望的消息格式,Mastra 的 span 数据需要做多层转换:

  • 输入转换transformInput,tracing.ts):将{ messages: [...] }解包为直接数组,并把 AI SDK(v4/v5)消息转换为 OpenAI Chat Completion 格式(修复 #11023);
  • 输出转换transformOutput):将{ content: '...' }解包为{ role: 'assistant', content: text }字符串形式;
  • 工具调用重构thread-reconstruction.ts+buildModelGenerationPayload):当 LLM 生成包含工具调用时,导出器通过检查子MODEL_STEPTOOL_CALLspan,以 OpenAI Chat Completion 格式重建完整对话流,使 Thread 视图正确展示包含工具调用与结果的完整会话(1.0.0,PR #11984);
  • AI SDK 消息转换增强(1.0.0,PR #11673):支持非文本内容类型(图片、文件、reasoning),用信息占位符展示;同时兼容 AI SDK v4 的result与 v5 的output字段,并优雅处理空内容数组与未知内容类型。

4. 工具结果配对:toolCallId 解析

1.3.2 版本修复了可观测性导出器对toolCallId的读取(PR #19405):从 span attributes 读取(含 metadata 回退),Braintrust Thread 视图通过真实工具调用 ID 配对工具结果。resolveToolCallId()的解析优先级见 tracing.ts:attributes.toolCallIdmetadata.toolCallIdinput.toolCallIdspan.id

5. 反馈与评估分数:logFeedback

1.0.0 版本修复了logFeedback()失效的问题(PR #11927)。根因是startSpan()调用传入了spanId: span.id但遗漏了event: { id: span.id },导致 Braintrust 为 rowid字段自动生成不同的 UUID,用户反馈因此成为独立行而非挂到原始生成记录上。修复方案是让 Mastra span ID 同时充当 Braintrust 的span_id与 rowid(见 tracing.ts)。

评估分数通过onScoreEvent()上报(tracing.ts):score 事件被转换为logger.logFeedback({ id: rowId, scores, comment, metadata, source: 'external' }),其中rowIdscore.spanId ?? score.traceId,scorer 名称/ID 作为分数键。1.1.0 版本还实现了Mastra Eval 结果转发到 Braintrust(PR #16185),并新增current span 解析器选项,解决应用与 Mastra 解析不同 Braintrust SDK 副本时评估 trace 无法正确嵌套的问题。

五、服务端与长生命周期运行:flush()

1.0.0 版本为所有可观测性导出器与实例新增flush()方法(PR #12003),专为 serverless 环境设计(例如 Vercel fluid compute 中运行时实例可跨请求复用):flush 缓冲区中的 span 但不关闭导出器,区别于shutdown()(后者释放资源且阻止后续导出)。

// 通过 observability 实例刷新所有导出器 const observability = mastra.getObservability(); await observability.flush(); // 或刷新单个导出器 const exporters = observability.getExporters(); await exporters[0].flush();

在 serverless 环境中,应在运行时实例终止前调用 flush,同时保持导出器对后续请求可用。

六、工作流挂起/恢复与 trace 分组(1.3.6)

1.3.6 版本修复了挂起(suspended)与恢复(resumed)的工作流运行在 Braintrust 中显示为两条断裂 trace 的问题(修复 #20771,PR #21047):

  • 挂起并恢复的工作流运行现在出现在一条Braintrust trace 中,恢复的运行嵌套在其被挂起时所在的 span 之下;
  • Braintrust trace 改为按Mastra trace ID分组(而非随机 ID),因此多个共享显式 trace ID 的运行会显示为一条 Braintrust trace。

其实现位于rootParentSpanIds()(tracing.ts):把rootSpanId固定为 Mastra trace ID,使共享 trace 的每个 root 落入同一条 Braintrust trace;仅当 span 携带 core 标记的resumedFromSpanId(恢复的续段)时才链接到其持久化父 span,其余 root 保持空的span_parents

升级注意事项(CHANGELOG 原文要点):在升级挂起、升级恢复的运行仍会显示为两条 trace——旧半段按随机 ID 分组,新版本无法恢复;且恢复半段可能缺少根 span。只有跨越升级的在途运行受影响,同一版本内挂起并恢复的运行不受影响。如果在意这条数据,请在升级前排空挂起的运行。

七、稳定版 1.0.0 的重大变更

1.0.0 标志着该包进入稳定阶段,伴随多项破坏性变更:

  1. Node.js 最低版本提升至 22.13.0(PR #9706);

  2. 可观测性配置 API 变更(PR #9709):必须显式导入并实例化Observability

    import { Mastra } from '@mastra/core'; import { Observability } from '@mastra/observability'; // 显式导入 const mastra = new Mastra({ ...other_config, observability: new Observability({ default: { enabled: true }, }), // 传入实例 });

    替代旧写法(import '@mastra/observability/init'+ 传入纯对象);

  3. 命名统一Tracing相关命名改为Observability,去掉AI-前缀;ai-tracing 代码整体迁入@mastra/observability(PR #9661);

  4. span 类型重命名(PR #9105):LLM前缀改为Model前缀,以反映其适用于所有 AI 模型而非仅大语言模型,例如AISpanType.LLM_GENERATIONAISpanType.MODEL_GENERATIONLLMGenerationAttributesModelGenerationAttributesInternalSpans.LLMInternalSpans.MODEL

  5. 新增TrackingExporter基类(PR #11870),前述乱序处理、延迟清理与内存上限参数均在此版本引入;

  6. trace 标签支持(PR #10765):Braintrust 与 Langfuse 导出器新增 trace tagging;

  7. 嵌入文档支持(PR #11472):发布包在dist/docs/下附带SKILL.mdSOURCE_MAP.json与主题文档,供编码 Agent 直接阅读node_modules中的说明。

八、1.3.0:Braintrust SDK v2 → v3 迁移

1.3.0 是紧随稳定版之后的又一次关键升级(PR #19507,Breaking change):

  • 内置 Braintrust SDK 从 v2 升级到 v3,并将 SDK 专属的 logger 与 span 类型替换为稳定的 Mastra 接口/垫片(shims);兼容的 Braintrust v2 与 v3 logger、span 对象仍受支持;
  • v3 使用独立的 W3C trace ID 作为root_span_id;Mastra 返回的spanId仍作为 Braintrust 的 row ID 与 span ID,用于 feedback 与查找;
  • BraintrustExporterConfig接口发生变更:若使用braintrustLogger字段或getCurrentSpan()方法,其类型已收窄、不再与 Braintrust SDK 绑定(官方评估“通常不会影响你”,但属于技术上破坏性变更);
  • 独立升级 Braintrust 且使用 Nunjucks 提示词模板的应用,应遵循 Braintrust 官方 v2→v3 迁移指南。

与此呼应,依赖版本的演进轨迹(来自 CHANGELOG)为:braintrust^0.3.6^0.3.8(0.1.4)→^0.4.9(1.0.0-beta.1)→^1.1.0(1.0.0-beta.8)→^2.2.0(1.0.3)→^3.22.0(1.3.4-alpha.0)→^3.24.0(1.3.4)。

九、实战:上下文感知接入(Eval 与 logger.traced)

braintrustLogger配置为外部 logger 后,_buildRoot()(tracing.ts)会按以下顺序寻找挂载点:① 配置的currentSpan()解析结果 → ② Braintrust 自身的currentSpan()→ ③ 回退到提供的 logger。这使得 Mastra 的 Agent trace 能自动嵌套进外层 Braintrust span。

场景一:Mastra 与 Braintrust Eval 结合

仓库示例 observability/braintrust/examples/with-eval.ts 展示了 Agent trace 自动嵌套进Eval()任务 span:

const logger = initLogger({ projectName: 'mastra-demo', apiKey: process.env.BRAINTRUST_API_KEY, appUrl: process.env.BRAINTRUST_API_URL, }); const exporter = new BraintrustExporter({ braintrustLogger: logger }); const mastra = new Mastra({ agents: { assistant: new Agent({ name: 'Assistant', instructions: 'Be concise.', model: 'openai/gpt-4o-mini' }) }, observability: new Observability({ configs: { braintrust: { serviceName: 'demo', exporters: [exporter] } }, }), }); await Eval('mastra-demo', { data: () => [ { input: 'What is the capital of France?', expected: 'Paris' }, { input: 'What is 2+2?', expected: '4' }, ], task: async (input: string) => { const agent = mastra.getAgent('assistant'); return (await agent.generate(input)).text; }, scores: [ (args: any) => ({ name: 'contains_answer', score: String(args.output).toLowerCase().includes(String(args.expected).toLowerCase()) ? 1 : 0, }), ], });

运行后在 Braintrust 项目mastra-demo中即可看到带分数的评估结果、嵌套在每个评估任务内的 Mastra Agent trace,以及完整的模型调用与工具使用轨迹。

场景二:logger.traced()手动包裹

仓库示例 observability/braintrust/examples/with-logger-traced.ts 展示为不同环境建立带标签的父 span:

for (const env of ['production', 'staging', 'development']) { await logger.traced(async span => { span.log({ tags: [`environment:${env}`], metadata: { environment: env }, }); const agent = mastra.getAgent('demo'); const response = await agent.generate('Say hi'); console.log(`${env}: ${response.text}`); }); }

对应配置的currentSpan传参方式为:new BraintrustExporter({ braintrustLogger: logger, currentSpan }),其中currentSpan应来自与应用创建Eval()/logger.traced()span 相同的包实例,以保证在存在多副本 Braintrust SDK 时 trace 仍正确嵌套。

此外,包内还提供 examples/basic.ts 基础示例,package.json 中预置了可直接运行的脚本:pnpm example:basicpnpm example:tracedpnpm example:eval

十、版本演进中的关键修复时间线

以下是 CHANGELOG 中可核验的重要修复,按版本梳理:

版本关键变更
0.1.0BraintrustExporter初始发布(用于 ai-observability)
0.1.4修复 braintrust 导出器乱序 span;依赖升至^0.3.8
0.1.7traceId 作为 root_span_id;保留 Mastra span ID 导出
1.0.0稳定版:Node 22.13.0、Observability API、TrackingExporter、TTFT、flush()、零配置环境变量、Thread 视图系列修复、logFeedback 修复
1.1.0current span 解析器选项;Mastra Eval 结果转发至 Braintrust
1.2.4工具调用不再显示为unknown_tool(真实工具名 + 配对结果);PROVIDER_TOOL_CALL纳入工具类型映射
1.3.0Braintrust SDK v2→v3;BraintrustExporterConfig接口变更
1.3.2导出器统一从 span attributes(含 metadata 回退)读取toolCallId
1.3.6挂起/恢复工作流运行合并为单条 Braintrust trace(按 Mastra trace ID 分组)
1.3.10更新 README;从 npm 分发文件中移除 CHANGELOG 以减小包体积(PR #22737)

十一、升级与排障速查

  1. API Key 缺失:导出器会进入禁用态,优先检查BRAINTRUST_API_KEY环境变量或apiKey配置;
  2. 升级 1.3.0 前:若独立升级 Braintrust 且使用 Nunjucks 模板,先完成 Braintrust v2→v3 迁移;braintrustLogger/getCurrentSpan()的类型已收窄,确认兼容;
  3. 跨越 1.3.6 升级:若存在在途的挂起工作流运行,先排空再升级,避免产生无法合并的历史 trace 半段;
  4. serverless 掉 trace:在运行时实例被回收前调用observability.flush(),而非shutdown(),以保留后续请求的导出能力;
  5. Thread 视图显示异常:确认版本 ≥1.0.0(覆盖消息格式转换、工具调用重构与 AI SDK v4/v5 兼容);工具结果配对依赖toolCallId,若仍异常可检查 span attributes 中的toolCallId是否被正确写入(1.3.2 起统一读取)。

总体而言,@mastra/braintrust的演进主线清晰:从早期的“能导出”逐步走向“导出得准确、可嵌套、可评估、可运维”——span 类型映射与指标格式标准化、Thread 视图消息重建、trace 分组语义(Mastra trace ID)以及 serverless flush 机制,都是把通用 observability 语义无损翻译为 Braintrust 原生结构的关键设计,值得在接入或移植到其他可观测平台时对照参考。

附:进一步阅读的仓库入口

  • 包说明与最小示例:observability/braintrust/README.md
  • 完整版本历史:observability/braintrust/CHANGELOG.md
  • 导出器核心实现:observability/braintrust/src/tracing.ts
  • 指标映射:observability/braintrust/src/metrics.ts
  • 消息格式转换:observability/braintrust/src/formatter.ts
  • Thread 视图重建:observability/braintrust/src/thread-reconstruction.ts
  • 嵌套场景测试:observability/braintrust/src/braintrust-nesting.test.ts
  • 实战示例:observability/braintrust/examples/basic.ts、observability/braintrust/examples/with-eval.ts、observability/braintrust/examples/with-logger-traced.ts

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询