帮助用户快速排查 Node.js 进程的异常根因。
当线上 JS 进程出现 CPU 飙高、内存泄漏、未捕获异常或定时器异常时,用户能够在最短时间内定位到问题的根本原因并采取行动。
mito-node CLI 提供两种等价的使用方式,覆盖「人」和「AI Agent」两类用户:
面向开发者和运维人员的终端交互界面,基于 Ink/React 构建。
使用场景:
- 开发者收到告警,需要实时观察进程状态
- 排查生产环境偶发性问题,需要持续监控
- 需要人工判断和操作的复杂调试流程
交互流程:
- 自动发现当前系统中的 Node.js 进程
- 选择目标进程
- 选择诊断命令
- 实时展示诊断结果(图表、表格、日志)
设计原则:
- 零配置启动,开箱即用
- 可视化呈现关键指标(CPU 使用率曲线、内存分布图)
- 引导式操作,降低排障门槛
面向 AI Agent 的非交互式调用接口,通过命令行参数一次性指定目标和操作。
使用场景:
- AI Agent 自动诊断异常进程
- CI/CD 流水线中的自动化健康检查
- 脚本编排多步骤诊断流程
调用方式:
# 采集 CPU Profile
mito-node cpuprofile -p <pid> -d 10000
# 获取内存信息
mito-node memory -p <pid>
# 生成进程诊断报告
mito-node report -p <pid>
# 获取堆快照
mito-node heapsnapshot -p <pid>
# 远程执行代码
mito-node run-code -p <pid> -c "process.memoryUsage()"设计原则:
- 结构化输出(JSON),方便 Agent 解析
- 单次调用完成单一诊断动作,无副作用
- 明确的退出码,便于流程控制
- 快速响应,超时可控
| 痛点 | 解决方案 |
|---|---|
| Node.js 进程异常时不知道从哪里入手 | 提供引导式排障流程和一键诊断命令 |
| CPU Profiling / Heap Snapshot 操作复杂 | 一条命令完成采集,自动保存文件 |
| 线上环境无法安装调试工具 | 通过 Inspector 协议远程连接,无需重启进程 |
| AI Agent 无法理解进程状态 | 提供结构化数据输出,Agent 可直接推理 |
| 定时器泄漏难以定位 | Shimmer 劫持 setTimeout/setInterval,记录创建调用栈 |
| 传统 APM 开销大、侵入性强 | 轻量 SDK + Rust Agent 高性能数据处理,最小化对业务的影响 |
| 异常类型 | 诊断手段 | 输出产物 |
|---|---|---|
| CPU 飙高 | CPU Profiling | .cpuprofile 文件(可导入 Chrome DevTools) |
| 内存泄漏 | Heap Snapshot + 内存趋势监控 | .heapsnapshot 文件 + 内存使用数据 |
| 未捕获异常 | JS Error 采集 | 错误堆栈 + 上下文信息 |
| 定时器异常 | setTimeout/setInterval 劫持 | 定时器创建记录 + 调用栈 |
| 进程状态异常 | Process Report | Node.js 诊断报告(libuv handles、环境变量等) |
| 任意运行时状态 | 远程代码执行 | 表达式求值结果 |
┌─────────────────────────────────────────────────────────┐
│ 用户 / AI Agent │
├─────────────────────────────────────────────────────────┤
│ mito-node CLI(Inspector 协议连接) │
│ ┌──────────────────┬──────────────────────┐ │
│ │ TUI 模式 (Ink) │ 参数模式 (Commander) │ │
│ └──────────────────┴──────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 目标 Node.js 进程 │
│ ┌──────────────────────────────────────────┐ │
│ │ @mitojs/node SDK(嵌入式采集) │ │
│ │ Collectors → Subjects → Rust Agent │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
- CLI 负责「连接 → 诊断 → 呈现」,是用户/Agent 的操作入口
- SDK 负责「采集 → 传输」,嵌入目标进程持续收集运行时数据
- Rust Agent 负责「接收 → 处理 → 存储」,高性能后端,不影响 JS 主线程
代码必须按职责清晰分层,禁止跨层直接调用:
┌─────────────────────────────────────────┐
│ Interface Layer(接口层) │
│ CLI 命令解析 / TUI 渲染 / JSON 输出 │
├─────────────────────────────────────────┤
│ Service Layer(服务层) │
│ 诊断流程编排 / Inspector 会话管理 │
├─────────────────────────────────────────┤
│ Core Layer(核心层) │
│ Collector / Subject / 数据模型 │
├─────────────────────────────────────────┤
│ Infrastructure Layer(基础设施层) │
│ IPC 通信 / Binary 管理 / Worker Thread │
└─────────────────────────────────────────┘
原则:
- 上层依赖下层,下层不感知上层
- 每层通过明确的接口(interface/type)暴露能力
- 跨层数据传递使用定义好的 DTO,不透传内部结构
诊断能力通过插件机制扩展,而非硬编码:
interface DiagnosticPlugin {
name: string
description: string
// 该插件支持的诊断场景
supports: DiagnosticScenario[]
// 执行诊断,返回结构化结果
execute(context: DiagnosticContext): Promise<DiagnosticResult>
// 可选:提供 TUI 渲染组件
render?: (data: DiagnosticResult) => ReactElement
}设计目标:
- 新增诊断能力只需实现一个 Plugin,无需修改核心流程
- 内置插件:CPU Profiling、Heap Snapshot、Memory Info、Process Report、JS Error、Timeout Detection
- 插件可声明依赖关系(如「内存泄漏诊断」依赖「Heap Snapshot」+「Memory Trend」)
- CLI 命令自动从已注册插件生成,保持命令与能力的一致性
代码默认不写注释,但以下关键位置必须添加注释:
| 场景 | 说明 | 示例 |
|---|---|---|
| 非显而易见的设计决策 | 解释 WHY,不解释 WHAT | // 使用 fd 3 而非 stdio 避免与子进程日志混淆 |
| 平台兼容性处理 | 标注哪些平台需要特殊逻辑 | // Windows 不支持 SIGUSR1,改用 named pipe 激活 Inspector |
| 性能关键路径 | 标注为什么选择某种实现方式 | // 使用 BigInt hrtime 避免浮点精度丢失导致 CPU 计算偏差 |
| 协议/规范约束 | 引用外部规范 | // Chrome DevTools Protocol: Runtime.evaluate |
| 临时 workaround | 标注上下文和移除条件 | // WORKAROUND: Node 18 Inspector 在 worker 中不触发 ready 事件,v20 已修复 |
| 插件接口契约 | 说明实现者必须遵守的约束 | // 插件必须在 30s 内返回结果,超时将被强制终止 |
禁止的注释:
- 重复代码语义的注释(
// 获取内存信息→getMemoryInfo()) - 变更日志式注释(
// 2024-01-01: 新增 xxx) - 注释掉的代码块(直接删除,用 git 追溯)
- 用户从发现异常到定位根因的时间 < 5 分钟
- AI Agent 能通过 CLI 输出独立完成 80% 的常见异常诊断
- SDK 对目标进程的性能影响 < 1% CPU / < 10MB 内存
- 支持不重启进程的情况下完成全部诊断操作
- 新增诊断能力只需实现一个插件,不修改核心代码
- 任何开发者阅读代码时,能通过分层和命名快速理解模块职责