Mastra × PostHog 可观测性集成实战:从事件化追踪到 LLM 成本分析 Mastra × PostHog 可观测性集成实战从事件化追踪到 LLM 成本分析【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra本篇技术指南聚焦 Mastra 官方 PostHog 可观测性导出器mastra/posthog深入讲解它如何把 Mastra 应用中的 Agent、模型生成Generation、工作流等 Span 转换为 PostHog LLM Analytics 平台可识别的结构化事件覆盖零配置接入、隐私模式、Serverless 批处理、Token 成本核算、用户反馈回传等完整能力。读完本文你将掌握如何用几行代码把 Mastra 的可观测数据无缝对接到 PostHog并理解其底层事件模型与数据转换原理。从 1.0.0 说起PostHog 事件化追踪架构的引入mastra/posthog包诞生于 Mastra 1.0.0 时代的 [PR #10393]核心思路与传统的 OpenTelemetry 导出器不同它采用事件化追踪架构Event-based tracing将 Mastra 的追踪数据以 PostHog LLM Analytics 原生消费的结构化事件形态发送主要包含两类事件$ai_generation模型生成MODEL_GENERATION类 Span 对应的事件携带模型名、Provider、输入输出、Token 用量、采样参数等 LLM Analytics 所需字段$ai_span其余非生成类 Span 对应的事件用于描述工作流、工具调用、重试等过程性节点。除这两类事件外当前源码还会为根 Span 显式发送$ai_trace事件见 tracing.ts 中的buildRootEventMessage以便精确控制 trace 级别的名称、会话与标签元数据而非依赖 PostHog 的伪 trace 自动创建逻辑。官方在引入该导出器时明确列出的一组核心能力正是理解整个包的关键事件化追踪架构面向 PostHog 的 AI 分析优化隐私模式privacy mode剔除敏感的输入/输出数据Serverless 优化自动配置批处理参数Token 用量归一化兼容 AI SDK v4 与 v5 两种格式消息格式转换满足 PostHog 严格的 API 属性要求4 级 distinct ID 解析用于用户识别MODEL_CHUNK 流式事件支持区域部署支持US / EU / 自托管。这些能力在 tracing.ts 中均有对应实现后文逐一展开。快速开始安装与三种配置方式安装npm install mastra/posthog按 package.json 的声明该包以posthog-node当前^5.46.1为运行时依赖并依赖mastra/observability提供TrackingExporter基类mastra/core作为 peerDependency要求1.16.0-0 2.0.0-0Node.js 版本要求22.13.0。方式一零配置推荐从 1.0.0 起所有可观测性导出器都支持零配置接入只需在环境变量中设置凭据即可直接实例化导出器无需传入任何参数import { Mastra } from mastra/core/mastra; import { Observability } from mastra/observability; import { PosthogExporter } from mastra/posthog; // 先设置环境变量POSTHOG_API_KEY必填、POSTHOG_HOST可选 export const mastra new Mastra({ observability: new Observability({ configs: { posthog: { serviceName: my-service, exporters: [new PosthogExporter()], }, }, }), });零配置对应的环境变量是POSTHOG_API_KEY与POSTHOG_HOST。显式传入的配置优先级高于环境变量源码 tracing.ts 中先解析环境变量再透传构造。方式二显式配置1.0.0 官方文档给出的经典写法是显式传入apiKey并自定义服务名import { Mastra } from mastra/core; import { Observability } from mastra/observability; import { PosthogExporter } from mastra/posthog; const posthogExporter new PosthogExporter({ apiKey: process.env.POSTHOG_API_KEY!, }); const mastra new Mastra({ observability: new Observability({ configs: { posthog: { serviceName: my-app, exporters: [posthogExporter], }, }, }), });方式三自定义 Host 支持多区域PostHog 的 SaaS 与自托管部署使用不同的 ingest 端点。host的解析优先级为显式host配置 POSTHOG_HOST环境变量 默认值https://us.i.posthog.com。EU 区域用户应显式指定https://eu.i.posthog.com自托管用户则传入自建实例 URLnew PosthogExporter({ apiKey: process.env.POSTHOG_API_KEY!, host: https://eu.i.posthog.com, // 或自托管地址 });当既未传host也无环境变量时源码会输出一条 info 日志提示当前使用 US 默认端点tracing.ts。核心配置参数详解PosthogExporterConfig继承自TrackingExporterConfig完整参数如下以 tracing.ts 与官方变更记录为准参数类型默认值说明apiKeystringPOSTHOG_API_KEY环境变量PostHog 项目 API Key缺失时导出器自动禁用并告警hoststringPOSTHOG_HOST环境变量否则https://us.i.posthog.comPostHog ingest 地址支持 US/EU/自托管serverlessbooleanfalse开启 Serverless 模式自动切换批处理参数flushAtnumber普通 20 / Serverless 10攒够多少条事件触发一次批量上报flushIntervalnumber普通 10000ms / Serverless 2000ms距上次上报的最大时间间隔defaultDistinctIdstringanonymous兜底的用户 distinct IDenablePrivacyModebooleanfalse开启 PostHog 隐私模式排除敏感输入输出earlyQueueMaxAttemptsnumber5乱序事件入队后的最大重试次数earlyQueueTTLMsnumber30000入队事件的有效期毫秒traceCleanupDelayMsnumber30000Span 结束后延迟清理 trace 的时间用于吸收迟到更新maxPendingCleanupTracesnumber100等待清理的 trace 数量软上限maxTotalTracesnumber500内存中 trace 总量的硬上限防止内存泄漏其中后五个参数来自 1.0.0 引入的TrackingExporter基类[PR #11870]该基类同时被mastra/braintrust、mastra/langfuse、mastra/langsmith、mastra/posthog四个导出器复用解决了三类共性问题乱序 Span 处理先于父 Span 到达的子 Span 会进入队列待依赖就绪后再处理由earlyQueueMaxAttempts与earlyQueueTTLMs控制重试与失效延迟清理traceCleanupDelayMs让已完成 trace 的数据短暂保留容纳迟到的更新内存管理maxPendingCleanupTraces软上限与maxTotalTraces硬上限双重防护内存泄漏。源码中的默认常量也证实了这些取值SERVERLESS_FLUSH_AT 10、SERVERLESS_FLUSH_INTERVAL 2000、DEFAULT_FLUSH_AT 20、DEFAULT_FLUSH_INTERVAL 10000tracing.ts。对应测试tracing.test.ts验证了 serverless 模式下自动切换flushAt: 10, flushInterval: 2000且手动覆盖flushAt: 50时仅覆盖被显式指定的参数。事件模型与消息转换从 Mastra Span 到 PostHog 属性三层事件映射mapToPostHogEvent只做两路映射MODEL_GENERATION→$ai_generation其余类型 →$ai_spantracing.ts。根 Span 单独走$ai_trace分支。父子关系通过$ai_parent_id建立当父节点是根 Span 时$ai_parent_id直接使用 traceId因为根 Span 不产生$ai_span见isParentRootSpantracing.ts。消息格式的严格转换PostHog 的 LLM Analytics 对消息结构有严格要求源码中的formatMessagestracing.ts会做多层归一化解包生成类 Span 输入常见的{ messages: [...] }包装将字符串内容包装为[{ type: text, text: ... }]结构识别{ text, toolCalls }形式的输出对象转换为带tool-call类型内容的 assistant 消息兜底使用safeStringify序列化并处理不可序列化对象。这一层转换在 1.0.17 版本[PR #15203]专门修复过——此前 generation trace 会把结构化内容变成字符串化 JSON修复后输入{messages: [...]}与带text的输出对象均能被正确提取。生成类事件的关键属性对于$ai_generation事件buildGenerationPropertiestracing.ts输出$ai_model/$ai_provider模型与 Provider缺失时回退为unknown-model/unknown-provider$ai_input/$ai_output_choices格式化后的消息$ai_temperature/$ai_max_tokens采样参数$ai_stream是否流式$ai_toolsOpenAI function 格式的工具定义数组Token 用量属性见下一节。Token 用量与成本计算的精细处理PostHog 会根据 Token 属性计算 LLM 成本因此用量上报格式的正确性直接影响成本准确性。mastra/posthog经历多次迭代最终沉淀为formatUsageMetrics工具函数tracing.ts$ai_input_tokens/$ai_output_tokens输入、输出 Token 总量$ai_cache_read_input_tokens缓存读取 Token$ai_cache_creation_input_tokens缓存写入 Token$ai_cache_creation_5m_input_tokens/$ai_cache_creation_1h_input_tokensAnthropic 按 TTL 拆分的缓存写入 Token1.3.3 版本起新增[PR #21563]。设计要点是输入 Token 保持“毛值”gross上报缓存字段作为其子集单独呈现。源码注释说明PostHog 对非 Anthropic Provider 会在计算成本时自行扣除缓存 Token而对 Anthropic 风格“独占上报”gross input 已排除缓存的场景则自行识别tracing.ts。因此导出器不再做减法从而规避了此前版本的两类 bug负成本问题1.0.26[PR #16876]修复了缓存 Token 存在时成本计算出现负数的问题——此前直接相减会导致负数缓存字段错位1.0.1[PR #12465]把缓存读取/写入 Token 从基础 input 计数中分离为独立字段并增加防御性钳制clamping确保缓存值超过总量时输入 Token 也不会为负。单元测试 usage.test.ts 完整覆盖了上述行为其中一组用例验证了 OpenAI 式提示词缓存下inputTokens10470而cacheRead48384缓存读取大于输入总量时仍然按原样上报、不做减法——这正是避免负成本的根源。4 级 distinct ID 解析与用户识别LLM Analytics 需要把事件关联到具体用户。getDistinctIdtracing.ts按如下优先级解析Span 元数据中的userId该 trace 已缓存的distinctId在_buildSpan阶段会从span.metadata?.userId提取并暂存tracing.ts配置项defaultDistinctId兜底常量anonymous。这一“4 级解析”正是 1.0.0 发布说明中承诺的能力测试 tracing.test.ts 对反馈事件的 distinct ID 还验证了更细的优先级链feedbackUserId userId metadata.userId defaultDistinctId anonymous。用户反馈回传$ai_feedback 事件从 1.2.0 起[PR #19922]导出器支持把用户反馈转发为 PostHog 原生$ai_feedback事件并在 trace 详情中以 User feedback 呈现。使用方式与官方示例一致const trace await mastra.observability.getRecordedTrace({ traceId }); await trace.addFeedback({ feedbackType: thumbs, value: down, comment: Wrong answer, }); // PostHog exporter 自动将其转发为 $ai_feedback 事件无需任何配置改动。底层实现onFeedbackEventtracing.ts会输出$ai_trace_id、$ai_feedback_text、feedback_id、feedback_type、feedback_value等属性其中$ai_feedback_text在缺少 comment 时回退为 value 的字符串形式——因为 PostHog trace 界面只展示带该字段的反馈事件。同时无 traceId 的反馈会被丢弃PostHog 强制要求$ai_trace_id。测试覆盖了这一完整映射tracing.test.ts。Tags、分组分析与工具定义Tags从 $ai_tags 到布尔属性1.0.0 曾以$ai_tags数组属性支持tracingOptions.tags但当前实现1.3.7 之后已演进为把每个 tag 展开为独立的布尔属性如{ production: true, experiment-v2: true }因为 PostHog 不提供 trace 级原生 tagstracing.ts。调用方式保持一致const result await agent.generate(Hello, { tracingOptions: { tags: [production, experiment-v2], }, });测试 tracing.test.ts 明确注释了这一“spread 成独立布尔属性而非数组”的设计取舍。分组分析$groups 的正确挂载1.0.28[PR #17624]修复了 AI 事件的 group analytics 不生效的问题。原因是 posthog-node SDK 以 capture 调用顶层的groups字段为准会覆盖属性层级的$groups。因此withGroups辅助函数tracing.ts会把事件属性中的metadata.$groups镜像到 capture 的顶层groups字段从而支持按组织、项目等维度切片成本等指标。工具定义$ai_tools1.3.0[PR #20243]起当 generation Span 携带工具定义时导出器会以 OpenAI function 格式输出$ai_tools让 PostHog LLM Analytics 展示每次生成实际用到的工具 Schemanew PosthogExporter({ apiKey: process.env.POSTHOG_KEY, host: https://us.i.posthog.com }); // $ai_generation 事件现在包含 // $ai_tools: [ // { // type: function, // function: { name: get_weather, description: Get the weather for a city, parameters: { ... } }, // }, // ]该能力依赖mastra/core的工具定义采集tool-definition capture无需改动配置。测试确认当工具定义为空数组或缺失时不输出该属性tracing.test.ts。Serverless 环境与 flush() 语义1.0.0 同时为所有导出器增加了flush()方法[PR #12003]专门解决 Serverless如 Vercel fluid compute场景下“运行时实例可能被复用、又必须确保 Span 在实例终止前完成上报”的矛盾// 方式一通过 observability 实例刷新全部导出器 const observability mastra.getObservability(); await observability.flush(); // 方式二刷新单个导出器 const exporters observability.getExporters(); await exporters[0].flush();关键区别flush()不会释放资源、也不阻止后续上报而shutdown()则会。源码中_flush仅调用this.#client.flush()_postShutdown才调用this.#client.shutdown()tracing.ts。配合前文提到的serverless: true自动收紧批处理参数攒 10 条或 2 秒即刷即可在冷启动与上报延迟之间取得平衡。版本演进时间线值得关注的里程碑从 CHANGELOG.md 可以梳理出该包的完整演进脉络也是排查历史问题的重要依据版本关键变更1.0.0-beta.1 / 1.0.0引入 PostHog AI 追踪导出器、TrackingExporter 基类、零配置环境变量、flush()、tags、嵌入文档dist/docs/1.0.1修复缓存 Token 混入基础 input 计数的问题拆分为独立字段并加钳制1.0.3posthog-node 从 ^4.0.1 升级到 ^4.18.01.0.9generation span 输出包含工具调用数据支撑 LLM Analytics Tools 面板1.0.17修复消息被字符串化 JSON 化的问题结构化提取输入输出1.0.19posthog-node v4 → v5引入官方 LLM analytics 改进1.0.26修复缓存 Token 导致的负成本计算1.0.28修复 group analytics 未挂载$groups → 顶层 groups1.0.31easy-day-js 供应链事件的安全修复版本推进 latest dist-tag1.2.0反馈导出为 $ai_feedback 事件1.3.0$ai_tools 工具定义导出1.3.1posthog-node 升级至 ^5.46.11.3.3Anthropic TTL 缓存 Token 属性5m / 1h拆分上报1.3.7README 内容更新npm 包移除 CHANGELOG 以减小体积版本号规律也值得注意每个稳定版本都会同步发布-alpha.x预发布序列Updated dependencies记录了与mastra/core、mastra/observability的联动升级因此升级mastra/posthog时应保持三者版本同步。源码与测试导航若想深入阅读或贡献以下路径是最佳入口包入口src/index.ts 仅一行导出全部实现核心实现src/tracing.ts 涵盖配置解析、事件构建、消息转换、反馈转发、flush 全流程单元测试src/tracing.test.ts1400 行覆盖初始化、Span 生命周期、工具定义、隐私模式、tags、反馈映射等src/usage.test.ts 专项验证 Token 用量映射官方 READMEREADME.md 提供最简接入示例版本与发布记录CHANGELOG.md 是本文所有能力迭代的事实依据。总体而言mastra/posthog的价值在于把 Mastra 的通用可观测数据翻译成 PostHog LLM Analytics 的专用事件语言无论是成本核算所需的 Token 字段语义、用户关联所需的 distinct ID 解析还是反馈闭环所需的$ai_feedback都已在导出器内部完成对齐。接入方只需关注业务数据本身即可在 PostHog 中获得按模型、按 Provider、按 tag、按 group 多维下钻的 LLM 可观测视图。【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考