Mastra OpenTelemetry 导出器:将 Agent 可观测性数据接入任意 OTLP 平台
2026/9/14 20:06:00 网站建设 项目流程

Mastra OpenTelemetry 导出器:将 Agent 可观测性数据接入任意 OTLP 平台

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

@mastra/otel-exporter是 Mastra 框架的官方 OpenTelemetry 导出组件,负责把 Mastra 运行时产生的 Trace(追踪)与 Log(日志)信号转换为符合 OpenTelemetry 语义约定的数据,并发送到任何兼容 OTLP 的可观测性平台。本文将以 observability/otel-exporter/README.md 为主线,结合包内源码与测试,完整讲解安装、配置、内置服务商支持、数据转换原理与排错方法,帮助你把 Agent、工作流与工具调用的全链路观测数据统一接入 Dash0、SigNoz、New Relic、Traceloop、Laminar 或自建 Collector。

包定位与能力概览

@mastra/otel-exporter属于 observability 目录下的独立发布包(包名@mastra/otel-exporter,见 package.json)。它不是一个完整的可观测性后端,而是一个"导出器"(Exporter):上游是 Mastra 核心(@mastra/core/observability)产生的标准 span 与 log 事件,下游是任意支持 OTLP 的采集端。

从源码结构看,该包的核心职责有三块:

  1. 信号导出:同时支持 Trace 与 Log 两种信号,可分别开关(tracing.ts)。
  2. 语义转换:把 Mastra 自有的 span 类型(模型生成、工具调用、Agent 运行、工作流控制流等)映射为 OpenTelemetry GenAI 语义约定下的 span、属性与日志(span-converter.ts、gen-ai-semantics.ts、log-converter.ts)。
  3. 服务商适配:为 Dash0、SigNoz、New Relic、Traceloop、Laminar 以及任意自定义 OTLP 端点解析出正确的 endpoint、认证头与传输协议(provider-configs.ts)。

README 中特别标注了一条重要注意事项:该包要求根据所选服务商额外安装对应的导出器依赖包。这些依赖在 package.json 中被声明为可选 peerDependencies 与 optionalDependencies,运行期由 loadExporter.ts 按需动态加载——装少了会打印明确的安装提示,但不会导致整个进程崩溃。

安装与前置条件

基础包安装:

npm install @mastra/otel-exporter

运行时环境要求 Node.js >= 22.13.0(见 package.json 的 engines 字段)。包本身是 ESM 优先的双格式产物(dist/index.jsdist/index.cjs),同时支持importrequire

由于导出器采用"信号 + 协议"的二维矩阵动态加载模型(loadExporter.ts),不同传输协议对应不同 npm 包:

协议Trace 导出包Log 导出包附加包
http/json@opentelemetry/exporter-trace-otlp-http@opentelemetry/exporter-logs-otlp-http
http/protobuf@opentelemetry/exporter-trace-otlp-proto@opentelemetry/exporter-logs-otlp-proto
grpc@opentelemetry/exporter-trace-otlp-grpc@opentelemetry/exporter-logs-otlp-grpc@grpc/grpc-js
zipkin@opentelemetry/exporter-zipkin不支持(Log 信号下会自动禁用并给出警告)

例如 Dash0 走 gRPC 协议,就需要:

npm install @opentelemetry/exporter-trace-otlp-grpc @grpc/grpc-js

如果希望同时导出 Log 信号,还要安装对应的@opentelemetry/exporter-logs-otlp-grpc不需要提前安装所有组合:加载器会在初始化时按实际协议动态import对应包,缺失时打印形如Install the required package(s): npm install @opentelemetry/exporter-trace-otlp-proto的提示并禁用该信号(loadExporter.ts)。

基本接入:在 Mastra 中挂载导出器

README 给出的最小接入方式是:创建一个Mastra实例,通过@mastra/observabilityObservability配置注册OtelExporter,并设置标准的OTEL_EXPORTER_OTLP_*环境变量指向你的 Collector。

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

其中:

  • serviceName会被写入导出数据的service.name资源属性,用于在后端平台区分服务;缺省时回退为mastra-service(tracing.ts)。
  • exporters数组可以注册多个导出器。OtelExporter内部的name固定为opentelemetry(tracing.ts)。
  • provider字段支持的对象形状见下文。

README 提到"设置标准OTEL_EXPORTER_OTLP_*环境变量",但需要说明适用边界:该包并未直接读取OTEL_EXPORTER_OTLP_ENDPOINT等环境变量来构造 endpoint(endpoint 由各 provider 配置或服务商专用环境变量决定,见下节),OTEL_EXPORTER_OTLP_*主要用于自建 Collector 配合customprovider 时的习惯性配置以及 OTel SDK 内部行为。最可靠的路径是:customprovider 显式指定 endpoint,或直接使用内置服务商的专用配置

Provider 配置详解:六种接入方式与完整参数表

Provider 类型定义在 types.ts,共六种:dash0signoznewrelictracelooplaminarcustom。解析逻辑集中在 provider-configs.ts,每种配置都支持"代码传入优先、环境变量兜底"的取值策略,并且所有字段均可选——必填项会在运行期校验,缺失时打印错误并禁用 trace 导出(返回 null),而不是抛异常

Dash0(gRPC)

new OtelExporter({ provider: { dash0: { apiKey, endpoint, dataset } } })
字段环境变量说明
apiKeyDASH0_API_KEY必填(运行期校验),以authorization: Bearer <key>形式发送
endpointDASH0_ENDPOINT必填,形如ingress.us-west-2.aws.dash0.com:4317
datasetDASH0_DATASET可选,通过dash0-dataset头指定数据集

Dash0 默认使用 gRPC 协议,endpoint 缺少/v1/traces后缀时会自动补齐(provider-configs.ts)。测试用例验证了最终 endpoint 为ingress.us-west-2.aws.dash0.com:4317/v1/traces、header 为authorization: Bearer test-key(provider-configs.test.ts)。

SigNoz(HTTP/protobuf)

new OtelExporter({ provider: { signoz: { apiKey, region, endpoint } } })
字段环境变量说明
apiKeySIGNOZ_API_KEY必填,通过signoz-ingestion-key头发送
regionSIGNOZ_REGIONus/eu/in,云版端点https://ingest.<region>.signoz.cloud:443/v1/traces
endpointSIGNOZ_ENDPOINT自托管 SigNoz 时填写,覆盖 region 推导的云端点

New Relic(HTTP/protobuf)

new OtelExporter({ provider: { newrelic: { apiKey, endpoint } } })
字段环境变量说明
apiKeyNEW_RELIC_LICENSE_KEY必填(License Key),通过api-key头发送
endpointNEW_RELIC_ENDPOINT可选,EU 区或自定义端点;默认https://otlp.nr-data.net:443/v1/traces

Traceloop(HTTP/json)

new OtelExporter({ provider: { traceloop: { apiKey, destinationId, endpoint } } })
字段环境变量说明
apiKeyTRACELOOP_API_KEY必填,Authorization: Bearer <key>
destinationIdTRACELOOP_DESTINATION_ID可选,通过x-traceloop-destination-id头指定目标
endpointTRACELOOP_ENDPOINT默认https://api.traceloop.com/v1/traces

Laminar(HTTP/protobuf)

new OtelExporter({ provider: { laminar: { apiKey, endpoint } } })
字段环境变量说明
apiKeyLMNR_PROJECT_API_KEY必填,使用 Laminar 标准环境变量名
endpointLAMINAR_ENDPOINT默认https://api.lmnr.ai/v1/traces

Custom(任意 OTLP 端点 / Collector)

new OtelExporter({ provider: { custom: { endpoint: 'http://localhost:4318', // 必填 headers: { Authorization: 'Bearer ...' }, protocol: 'http/protobuf', // 默认 http/json }, }, })

custom是接入自建 OpenTelemetry Collector、或任何未内置服务商的最通用方式:endpoint必填,headersprotocolhttp/json/http/protobuf/grpc/zipkin)可选。注意custom模式下不会自动补/v1/traces后缀——endpoint需要你直接给出完整路径。

各 Provider 解析行为一览

以下汇总自 provider-configs.ts 的实现:

Provider默认协议认证头默认 Endpoint 规则
dash0grpcauthorization: Bearer <key>dash0-dataset自动追加/v1/traces
signozhttp/protobufsignoz-ingestion-keyhttps://ingest.<region>.signoz.cloud:443/v1/traces
newrelichttp/protobufapi-keyhttps://otlp.nr-data.net:443/v1/traces
traceloophttp/jsonAuthorization: Bearer <key>x-traceloop-destination-idhttps://api.traceloop.com/v1/traces
laminarhttp/protobufAuthorization: Bearer <key>https://api.lmnr.ai/v1/traces
customhttp/json(可配)自定义 headers直接使用传入 endpoint

解析器只从配置对象读取第一个 key 来确定 provider 类型(provider-configs.ts),因此一个provider对象内只能出现一个服务商键。另外,debug 模式下打印解析结果时,header 值会被统一替换为[REDACTED],避免 API Key 等凭据泄漏到日志中(provider-configs.ts)。

OtelExporterConfig 完整配置项

OtelExporter的构造参数在 types.ts 中定义,除provider外还包括:

配置项类型默认值作用
providerProviderConfig必填服务商配置;不提供时导出器直接置为禁用态
timeoutnumber(毫秒)30000单批导出超时,同时作为 exportTimeoutMillis
batchSizenumber512单批最大导出条数(maxExportBatchSize)
logLevel'debug' \| 'info' \| 'warn' \| 'error'设为debug时启用导出结果日志与诊断
resourceAttributesDetectedResourceAttributes附加/覆盖导出数据的资源属性
exporterSpanExporter直接注入自定义 span exporter,跳过内置构建
signals.tracesbooleantrue关闭 trace 导出
signals.logsbooleantrue关闭 log 导出

源码 tracing.ts 展示了 batch 处理的完整默认参数:maxExportBatchSize = batchSize || 512maxQueueSize = 2048scheduledDelayMillis = 5000(每 5 秒批量发送一次)、exportTimeoutMillis = timeout || 30000。也就是说,span 并不是实时逐条发送的,而是进入 2048 容量的队列后每 5 秒批量冲刷,理解这一点对排查"数据延迟到达"类问题很有帮助。

logLevel: 'debug'时,导出器会做两件事:一是将 OTel SDK 的 diag 日志级别设为 INFO(刻意不用 DEBUG,因为 OTLP 导出器在 DEBUG 级别会输出巨大 payload,且diag.setLogger是全局的、可能被其他代码覆盖);二是用DebugSpanExporterWrapper/DebugLogExporterWrapper包装真实 exporter,在每次批量导出成功或失败时输出日志——OTel SDK 默认在成功时不打印任何日志,这个包装是排查导出问题的关键手段(tracing.ts)。

Span 转换:Mastra 类型到 OTel GenAI 语义

Mastra 的 span 通过 span-converter.ts 转换为 OTelReadableSpan,转换格式当前固定为GenAI_v1_38_0,即遵循 OpenTelemetry GenAI 语义约定 v1.38.0。

Span 名称与 Kind

  • Span 名称getSpanName生成(gen-ai-semantics.ts):优先组合"操作名 + 实体标识",例如模型生成产生chat gpt-4o这样的名字;工作流控制流类 span 因没有自己的实体名,回退到净化后的原始 span 名。操作名映射关系(gen_ai.operation.name)为:MODEL_GENERATION → chatRAG_EMBEDDING → embeddings、各类工具调用 →execute_toolAGENT_RUN → invoke_agentWORKFLOW_RUN → invoke_workflow(gen-ai-semantics.ts)。
  • Span KindMODEL_GENERATIONRAG_EMBEDDINGMCP_TOOL_CALL映射为CLIENT,其余为INTERNAL(span-converter.ts)。

资源与 Instrumentation Scope

span 上会附带标准资源属性:service.name(来自 observability 配置或mastra-service回退)、service.version(取自@mastra/core包版本)、telemetry.sdk.nametelemetry.sdk.versiontelemetry.sdk.language: nodejsresourceAttributes中重复的键会覆盖上述默认值(span-converter.ts)。

丰富的 GenAI 属性

gen-ai-semantics.ts 是语义转换的核心,按 span 类型注入:

  • 模型生成(MODEL_GENERATION):请求/响应模型名、provider 名(经normalizeProvider归一化,内置了 anthropic、openai、gemini、bedrock、vertex_ai 等别名映射表,见 gen-ai-semantics.ts)、temperature/maxOutputTokens/topP/topK/presencePenalty/frequencyPenalty/stopSequences/seed等请求参数、输入/输出消息(转为 GenAI 语义消息)、finishReasonresponseId、服务地址端口;还会额外输出mastra.completion_start_time用于后端计算首 token 延迟(TTFT)。
  • Token 用量formatUsageMetrics输出gen_ai.usage.input_tokensgen_ai.usage.output_tokens、缓存读写 token(cache_read/cache_creation及 5m/1h 变体)、reasoning_tokens、音频 token 等(gen-ai-semantics.ts)。
  • 工具调用gen_ai.tool.namegen_ai.tool.call.idgen_ai.tool.call.argumentsgen_ai.tool.call.resultgen_ai.tool.type、工具描述;MCP 调用还会附带 MCP server 地址与版本。
  • Agentgen_ai.agent.idgen_ai.agent.namegen_ai.conversation_id(线程 ID 也会映射到该字段)、gen_ai.system_instructions、可用工具列表。
  • 工作流:运行状态、步骤 id、条件分支数/选中步骤、并行分支数、循环类型与迭代次数、sleep 时长、wait 事件名等,统一以mastra.<span_type>.<snake_case>命名空间输出(gen-ai-semantics.ts)。
  • 通用mastra.span.type、输入输出(模型与工具走gen_ai.*约定,其他类型落到mastra.<type>.input/output)、mastra.metadata.*、根 span 的mastra.tags(JSON 序列化以兼容 Jaeger/Zipkin/Tempo 等对数组支持不佳的后端,见 span-converter.ts)。

状态与异常

span 存在errorInfo时,状态置为ERROR并写入exception事件(含exception.messageexception.typeexception.stacktrace),同时error.typeerror.messageerror.domainerror.category被写入属性;正常结束的 span 置为OK,未结束的置为UNSET(span-converter.ts)。

父级关系上,Mastra 的externalParentSpanId会被保留为 OTel 侧父 span,使外部注入的上下文能够延续(span-converter.ts)。

Log 转换:日志信号与 Trace 关联

Log 信号由 log-converter.ts 处理:

  • 严重级别映射:Mastra 的debug/info/warn/error/fatal对应 OTelSeverityNumberDEBUG/INFO/WARN/ERROR/FATALseverityText为对应大写字符串。
  • 属性构建:结构化数据log.datalog.metadata分别映射为mastra.log.<key>mastra.metadata.<key>;对象值做 JSON 序列化,遇到循环引用等无法序列化的值回退为[unserializable]占位符;标签写入mastra.tags
  • Trace 关联:日志在发出时会把traceId/spanId既写入mastra.traceId/mastra.spanId属性,又通过trace.setSpanContext镜像到 OTel 日志 Context 的标准字段(tracing.ts),从而让 Grafana、Datadog、Honeycomb 等后端能用标准 OTLP 字段把日志与 trace 关联起来。日志导出器同样使用 512/2048/5s/30s 的 batch 参数(tracing.ts)。

生命周期:flush 与 shutdown

OtelExporter实现了完整生命周期(tracing.ts):

  • init:由 Mastra 在组件注册时调用,触发所有信号的并行异步初始化,事件处理器会等待初始化 promise 完成后再处理数据;即使没有经过 Mastra,首次收到事件时也会惰性触发同样的初始化。
  • flush:先等待初始化完成,再对所有已激活的 processor/provider 执行forceFlush,适合在服务优雅退出前冲刷缓冲数据。
  • shutdown:等待初始化后关闭所有 processor 与 provider,释放连接。

故障排查速查表

现象可能原因排查手段
Trace 未发送缺少对应协议的导出器包查看启动日志中Install the required package(s):提示,按协议安装
输出Provider configuration is required未传provider使用customprovider 指定通用端点
输出...requires apiKey... Tracing will be disabled未配置服务商 API Key设置对应环境变量或在配置中传入
数据延迟 5 秒以上到达batch 机制(scheduledDelayMillis=5000)属正常行为;如需实时可调小或接受批量语义
需要确认导出成功/失败OTel SDK 成功时不打日志logLevel: 'debug',观察Export completed/Export FAILED日志
日志信号缺失未安装 logs 系列导出包,或signals.logs: false安装@opentelemetry/exporter-logs-otlp-*并确认开关
服务名不对serviceName未传Observabilityotel配置中设置serviceName

小结

@mastra/otel-exporter把"Mastra 应用 → OTLP 平台"这条链路封装成了开箱即用的配置式接入:通过provider一个字段即可完成 endpoint、协议、认证头的全部推导;通过SpanConverter与 GenAI 语义转换,Mastra 的 Agent、工具、工作流原生 span 被翻译成各可观测性后端都能理解的标准模型;batch 机制、debug 日志、信号开关与生命周期管理则保证了生产环境下的可控性。对于尚未内置的服务商,customprovider 可以对接任意 OTLP Collector,因此本文覆盖的接入模式也适用于自建监控基础设施的场景。

延伸阅读

  • 包内自述与变更记录:README.md、CHANGELOG.md
  • 类型定义与配置接口:types.ts
  • Provider 解析与测试:provider-configs.ts、provider-configs.test.ts
  • 信号导出与生命周期:tracing.ts
  • 语义转换实现与测试:span-converter.ts、gen-ai-semantics.ts、log-converter.ts
  • 动态依赖加载:loadExporter.ts

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

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

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

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

立即咨询