Node.js 可观测性与 APM
Node.js 链路在每次 await 处断裂。阿里云 ARMS 代理将其重新拼接
Node.js 服务如今充当 BFF、网关和 AI 编排层,因此一个请求会跨越数据库、缓存、队列和 LLM 调用。阿里云 ARMS Node.js 代理将 OpenTelemetry 链路追踪、运行时健康检查和 AI 可观测性合并到单个 npm 包中。

有用户反馈“这次 AI 助手回答问题花了太长时间。”入口 API 显示响应时间很高。数据库没有慢 SQL。Redis 命中率正常。日志干净。这套检查清单过去足以结案。但在编排 AI 代理的 Node.js 服务中,原因可能隐藏在任何地方:在 LangChain 工具调用内部,在模型首 token 时间(TTFT)飙升中,或在事件循环被阻塞的 200 毫秒里。
正是这种场景,让阿里云 ARMS Node.js 代理有了存在的意义,它针对的是 APM 工具原本并非为此而设计的问题。Node.js 服务不再只是接收请求、查询数据库并返回 JSON。它们充当服务于前端的后端(BFF)、API 网关、实时通信中枢、队列消费者和 AI 代理编排层。单个请求可以横跨 HTTP、数据库、缓存、RPC、消息队列、运行时资源和 LLM。缺失的从来不是监控数据,而是上下文。
链路追踪的汇聚问题
当 Node.js 位于用户与所有下游依赖之间时,即使根因在数据库、缓存、下游 RPC 或模型调用中,缓慢的入口点也会被当作 Node.js 的问题。运行时自身的设计让关联变得更难。Node.js 围绕 Promise、async/await、定时器、回调和事件循环构建,而其中每一处都可能是追踪 ID 丢失的地方。一旦 ID 在异步边界处丢失,链路就会断裂成碎片,只剩下孤立的 span 和零散的日志。
为什么运行时健康会体现在 API 延迟中

API 缓慢并不总是慢 SQL 造成的。可能是事件循环被同步工作阻塞了 200 毫秒,可能是 V8 堆不断攀升直至触发垃圾回收抖动,可能是 CPU 使用率异常,也可能是进程资源耗尽。传统的 API 日志无法回答运行时本身是否健康。该代理通过 MeterManager 收集运行时指标,并使用 gzip 和 protobuf 压缩后上报,因此你既能询问哪条链路慢,也能询问为什么整个服务慢。上报的线程数是基于 CPU 核心数和 libuv 线程池大小的估算值,用于趋势观察,而非精确数值。
AI 调用是新的可观测性目标
Node.js 正在成为 AI 应用的服务器端层。团队基于 OpenAI SDK、LangChain.js、LangGraph、Vercel AI SDK 和 Anthropic Claude SDK 构建智能客服、编程助手、数据分析代理和内部生产力工具。一个请求如今等于 HTTP 加数据库,再加上模型调用、编排、流式传输、工具调用、嵌入和 RAG 检索。
该代理内置的 AI 插桩覆盖这些框架,并用 GenAI 语义丰富链路:模型调用、token 用量、流式响应、工具调用和错误详情。其回报是,回答关于某个用户查询的一个问题时,无需再交叉比对模型平台日志、业务日志和链路日志。
一个 npm 包,三种接入方式
该包名为 @loongsuite/cms_node_sdk,其中 “cms” 是历史遗留的命名约定;在产品侧,它充当 ARMS Node.js 代理。它基于 OpenTelemetry 核心数据模型构建,并与 ARMS 端到端打通。CommonJS 项目预加载它,ESM 项目使用加载钩子,希望显式控制的项目则在代码中启动 SDK:
# CommonJS:在应用启动前预加载
export ARMS_APP_NAME=your-app
export ARMS_REGION_ID=cn-hangzhou
export ARMS_LICENSE_KEY=your-license-key
node -r @loongsuite/cms_node_sdk/register app.js
# ESM:加载器注入
node, experimental-loader=@loongsuite/cms_node_sdk/import-hooks app.mjs
const { NodeSDK } = require('@loongsuite/cms_node_sdk');
const sdk = new NodeSDK({
serviceName: 'your-app',
licenseKey: 'your-license-key',
regionId: 'cn-hangzhou',
workspace: 'your-workspace',
});
sdk.start();
ESM 路径使用 import-in-the-middle 进行模块拦截,文档建议如果你的项目组合了多个加载器,请在测试环境中验证模块加载顺序。编程式接入必须在任何业务模块导入之前运行,否则 HTTP、数据库和缓存模块将不会被插桩。该代理还会将追踪上下文注入 Console、Pino、Winston 和 Bunyan 等日志器,使日志与链路可以一起查询。
上下文默认依赖 AsyncLocalStorage,仅在较旧的运行时上降级为 AsyncHooks,因此 span 能够跨越 Promise、回调和定时器。W3C Trace Context 和 Baggage 传播让 Node.js 服务能与 Java、Go 或 Python 服务在同一个拓扑中相连,而不是孤立存在。内置插桩覆盖了服务端 Node.js 工作真正触及的路径:
| 类别 | 支持的目标 |
|---|---|
| Web 与网络 | HTTP/HTTPS, Express, Koa, Undici, Net, DNS |
| RPC 与实时通信 | gRPC, Socket.IO |
| 数据库 | MySQL, MySQL2, PostgreSQL, MongoDB, Mongoose |
| 缓存 | Redis, ioredis |
| 消息队列 | Kafka |
权衡:构建模块与成品
理解这个代理最清晰的方式,是把它看作一个关于 OpenTelemetry 的产品决策。开源标准提供了构建模块,但仍需有人选择导出器、配置采样、挑选插件、标准化资源属性、关联日志,并解决 AI 可观测性。ARMS 代理提前回答了这些问题,并让答案可以通过控制台修改:它在启动后约 60 秒拉取远程配置,此后每 60 秒拉取一次,无需重启。在流量高峰期间,你可以降低采样率,禁用与业务库版本冲突的插件,或为调试会话提高采样率,之后再恢复。
传统 APM 覆盖 API 和数据库,但往往忽略 AI 调用;AI 可观测性工具追踪提示词、token 和模型链路,却缺乏运行时指标和核心 APM 功能。这个代理是阿里云将两者集于一包的尝试。其设计刻意保持低侵入性:批量导出、压缩传输、采样、插件开关、异常保护(插桩失败不会影响业务流),以及在 SIGINT 和 SIGTERM 时刷新缓冲数据的优雅关闭。环境要求也很简单:Node.js 16.x 或以上,生产环境使用 18 或 20 LTS,外加 ARMS LicenseKey 和地域 ID。
其主张是,Node.js 可观测性应该像安装一个 npm 包一样简单。对于已经身处阿里云可观测性生态的团队来说,这是一个开箱即用的代理,而不是一堆待组装的组件。对于运行自管理 OpenTelemetry 的团队而言,把绑定 ARMS 的代理视为升级还是供应商锁定,这个问题正是厂商自己的表述框架所留下的开放问题。
每天早晨用 3 分钟掌握科技要闻
每个工作日一封邮件,只讲真正重要的 AI 与科技动态。