用途
本技能用于建设生产环境的可观测性,覆盖日志、指标、追踪三大支柱。适用的入口场景包括:服务上线前、生产问题调查、监控配置;出口目标是产出一套可工作的监控 Dashboard 与告警规则。其输出路径为:异常时进入 verify-workflow-debug,上线后进入 ship-workflow-canary。前置需加载 CANON.md。
何时不使用
- 还没到上线或生产诊断阶段,只是在本地修复功能。
- 只是单次运行测试或查看日志,不需要长期指标/告警。
- 根因未知且没有可观测数据时,先进入 verify-workflow-debug。
三支柱
- Metrics:数字,知道“有问题”(WHAT)。
- Logging:事件,知道“具体是什么问题”(WHAT + CONTEXT)。
- Tracing:请求链路,知道“问题在哪层”(WHERE)。
Metrics — 症状检测
- RED 方法(服务端点):Rate(每秒请求数)、Errors(失败率)、Duration(P50/P95/P99 延迟)。
- USE 方法(基础设施/资源):Utilization(CPU、内存、磁盘使用率)、Saturation(队列深度、连接池等待)、Errors(硬件错误、网络丢包)。
Logging — 上下文
技能给出了结构化日志的对比示例:
// Bad: 信息不足
console.log('Task created');
// Good: 结构化 + 上下文
logger.info('task.created', {
taskId: task.id,
userId: req.user.id,
title: task.title,
duration: Date.now() - start,
});
日志级别及其在生产环境的使用方式:ERROR(需要人工介入的问题,始终开启)、WARN(需要注意但可自动恢复,始终开启)、INFO(关键业务事件,始终开启)、DEBUG(详细诊断信息,按需开启)、TRACE(逐行追踪,从不开启,太详细)。
Tracing — 请求链路
技能给出的链路示例:
请求进入 → API Gateway(50ms) → Service(200ms) → DB Query(180ms) → 返回
└→ Cache Read(2ms)
分布式追踪在跨越 3 个以上服务时必须使用。追踪 ID 从头传递到尾(不改写)。
告警设计
告警的黄金信号示例:
- 错误率突升(baseline 对比)→ P1
- P95 延迟突升(baseline 对比)→ P1
- 健康检查失败 → P0
- 磁盘/内存使用率 > 90% → P2
- SSL 证书即将过期(< 7 天)→ P2
- 队列积压 > 阈值 → P2
告警设计原则:
- 告警 = 症状,不是原因。“数据库连接池满了”是症状(告警),“N+1 查询导致太多连接”是原因(调试)。
- 告警必须有 Runbook 链接(“怎么办”的文档)。
- 告警阈值必须有足够的余量——P95 > 1s 可能触发太频繁,P95 > 5s 才是真正的异常。
健康检查端点
GET /health→ 公开。返回 200 或 503。负载均衡器用。GET /health/ready→ 内部。检查 DB 连接、Redis 连接、关键依赖。GET /health/live→ 内部。进程存活检查(最简单,仅返回 200)。
Dashboard 设计
按受众分层:
工程师 Dashboard:
- 请求量 + 错误率 + 延迟(按端点)
- 依赖健康(DB、Redis、Queue、外部 API)
- 基础设施(CPU、内存、磁盘、网络)
- 最近部署标记(竖线)
业务 Dashboard:
- 用户操作量(注册、登录、关键操作)
- 转化率(漏斗每步)
- 支付成功率
常见说辞与现实
- “console.log 就够了”:没结构化、没上下文、没级别。日志框架(pino/winston/logrus)成本极低,收益极高。后果:生产问题定位时间 ×3-5;无法自动聚合告警,每次靠人肉翻日志。
- “指标太多看不过来”:告警不靠人看。设置阈值 + 自动告警 + Runbook。人只在告警触发时介入。后果:关键异常遗漏 → 用户先发现 → SLA 损失;人力监控成本不可持续。
- “追踪太贵不搞”:在跨越 3 个以上服务时必须。没追踪时定位慢请求 = 每个服务逐一排查 = 花费更多。后果:跨服务慢请求排查时间 ×5-10;MTTR 从分钟级升到小时级。
- “生产问题靠用户报告才知道”:说明你没有告警。用户在帮你做监控。后果:每次用户报告 = 1-2 小时信任损失 + 品牌损害;主动告警可压缩响应到 5 分钟。
红旗 — STOP
- 生产代码用 console.log 而非结构化日志。
- 日志记录中包含密码、token、PII(个人身份信息)。
- 没有 /health 端点或 /health 始终返回 200(即使 DB 挂了)。
- 关键路径缺少追踪(跨越多服务时的黑盒)。
- 告警无 Runbook 链接(告警触发→不知道做什么)。
- 关键错误被捕获但不记录(
catch (e) {}无声吃掉)。
验证失败处理
- 结构化日志缺失(关键路径用 console.log):替换为 logger.info/error,添加上下文字段。
- 健康检查端点缺失(无 /health 或始终返回 200):实现 /health + /health/ready,检查依赖连通性。
- 核心指标不可见(Dashboard 无请求量/错误率/延迟):添加 RED 指标到 Dashboard,配置自动刷新。
- 告警无 Runbook(告警触发后无人知道怎么做):为每个告警补写 Runbook,链接到告警配置。
- 追踪 ID 不传递(跨服务请求无关联 trace_id):在请求头注入 trace_id,服务间传递并记录。
好坏示例
Good:结构化日志 + 告警 + Runbook
logger.info('task.created', {
taskId: task.id,
userId: req.user.id,
duration: Date.now() - start,
});
// 告警: error_rate > 1% → P1, Runbook: /ops/runbooks/task-error-spike
Bad:console.log + 无告警
console.log('Task created'); // 无上下文、无级别、无法聚合
// 无告警 → 用户先发现生产问题
输出模板
可观测性配置完成:
Dashboard:
- [端点] 请求量 + 错误率 + P95延迟
- [依赖] DB / Redis / Queue 健康
- [基础设施] CPU / 内存 / 磁盘
告警:
- P0: 健康检查失败 → Runbook: <url>
- P1: 错误率 > 1% → Runbook: <url>
- P1: P95延迟 > 5s → Runbook: <url>
- P2: 磁盘 > 90% → Runbook: <url>
健康检查:
- GET /health → 公开 (负载均衡器)
- GET /health/ready → 内部 (DB + Redis + 关键依赖)
追踪:
- trace_id 传递: [是/否/不适用(单服务)]
- 跨服务数: [N]
验证清单
- 结构化日志在关键业务路径上记录。
- /health + /health/ready 端点存在。
- 核心指标在 Dashboard 上可见。
- 关键告警已配置(错误率、延迟、健康检查)。
- 每个告警有 Runbook。
- 分布式追踪 ID 在服务间传递(如果跨越 3+ 服务)。
- 日志不包含密钥或 PII。
限制
产品具体的收费、价格、支持的平台等信息暂未提供。