日志与监控:从 PM2 日志到业务可观测性
本文目录
PM2 能管理 Node.js 进程和收集 stdout/stderr,但“进程在线”不代表请求成功、后台队列没有积压或数据库可用。可观测性要回答:发生了什么、影响谁、从哪一段开始、恢复是否有效。围绕用户可见结果建立信号,而不是只堆更多日志。
四类信号各自回答不同问题
- 结构化日志:某个事件/请求的上下文和结果,适合排查单次故障与审计。
- 指标:一段时间内的计数、比率、分位数和资源占用,适合趋势、告警和容量规划。
- 分布式追踪:一次请求跨网关、服务、数据库和外部 API 的跨度与耗时。
- 健康检查:进程是否存活,以及是否具备接收新流量的条件;探针不应暴露详细环境信息。
请求关联和结构化日志
入口生成或校验 requestId/traceId,并通过可信上下文传播到下游。日志用 JSON 字段而非字符串拼接:时间、服务名/版本、路由模板、方法、状态、耗时、关联 ID、脱敏后的 actor 标识和错误分类。记录路由模板而不是含个人信息的原始 URL;异常消息要清洗 CR/LF,避免日志注入。
严禁记录密码、Authorization、Cookie、JWT、数据库连接串、完整请求体、支付资料和未脱敏用户文本。不同用途的安全审计和性能日志可分开保留,设置访问权限、加密、轮转和期限。将错误详情限制给有权限的日志系统,面向用户的 API 返回稳定错误,不泄漏堆栈。
指标:RED 与饱和度
服务端可先看 RED:Request rate、Error rate、Duration。再补充 saturation:CPU、内存/GC、事件循环延迟、连接池等待、数据库连接、队列最老任务年龄、磁盘空间和文件描述符。只看平均延迟会掩盖尾部用户;关注 P50/P95/P99,并按路由模板、状态码和服务版本分组。
指标标签不要使用 userId、requestId、完整 URL、任意异常文本等高基数字段,否则时序数量会爆炸。把请求级细节留在 trace/log,指标标签只选有限枚举。报警应基于用户影响或 SLO 消耗,而不是单个瞬时 CPU 尖峰。
OpenTelemetry 接入顺序
Node.js 自动/手工 instrumentation 的初始化时机很重要:SDK 通常要在应用和被观测依赖加载前启动,避免模块已加载后才注册 instrumentation。trace、metrics、logs 的 JS 稳定性与生态状态不同;按 OpenTelemetry 当前 JavaScript 文档确认所用 SDK/exporter 状态。设置采样率、导出超时、队列上限和凭据,Collector/外部端点故障不能拖垮主请求。
为每个边界补 span:入口、数据库查询、HTTP 下游、队列消费。只给 span 增加安全属性,例如操作名、结果和有限状态码;不把密钥、用户全文或大对象放在 attributes。生产采样要覆盖错误和慢请求,同时控制费用与敏感数据风险。
健康、就绪与优雅退出
Liveness 回答进程是否需要重启;readiness 回答此刻是否可以收新请求。昂贵依赖检查不应被高频探针无限放大。部署收到 SIGTERM 时停止接收新请求、停止领取任务、等待在途事务有限时间、关闭 HTTP server/数据库/Redis 连接,超时再退出。优雅关闭需要真实集成测试,而不只是在 PM2 里看进程被重启。
PM2 的 restart 可能造成短暂停机;只有应用支持无状态多实例、就绪信号和安全关闭时,reload 才适合逐实例切换。进程日志使用轮转和磁盘阈值,禁止用无上限日志文件填满根分区。进程内 session、定时器或缓存若依赖单实例,开启 cluster/reload 前先评估共享状态。
从告警到复盘
告警包含症状、影响范围、看板、最近变更、初始排查与升级路径。操作手册说明如何止损、回滚、验证恢复和清理临时数据。故障后记时间线、检测延迟、恢复动作、用户影响和具体改进项;不把复盘写成只责怪个人的故事。
参考:OpenTelemetry JavaScript、OTel exporters、PM2 process management、Node.js process signals、OWASP Logging Cheat Sheet。
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。