可观测性与结构化日志
通过脱敏日志、OpenTelemetry trace、队列 readiness 与可操作告警关联 Web 和 Worker。
已与启动模板提交
2a1a04a同步。
请在第一次事故发生前使用本页,让客服和故障处理具备基本可观察性。Sushi SaaS 把 JSON 写到 stdout,但有意不替你选择日志存储供应商、保留期、仪表盘或告警产品。
OpenTelemetry 是可选且与供应商无关的。设置 OTEL_ENABLED=true、每个进程独立的 OTEL_SERVICE_NAME,以及标准 OTLP endpoint/header。Next.js 请求、fetch 与 job 入队/执行 span 会被导出,span 内日志包含 trace_id 和 span_id;未启用时没有额外效果。
/api/ready 返回不含 payload 的队列数量、失败/过期 Worker 和最老等待时间。失败任务或等待超过十分钟会标记 degraded,但不会自动下线客户流量;依赖故障仍返回 503。
做出三项运维选择
- 将 stdout 交给托管平台自带的收集器,或转发到 Datadog、Better Stack、Grafana 等服务;应用内的日志契约不变。
- 生产通常使用
info。只在调查具体问题时使用debug,因为它会增加成本并缩短有效保留期。 - 决定客服可搜索哪些标识。request、organization、job、order、Stripe event ID 很有用;邮箱和原始 payload 通常不应成为索引。
可以上线的标准: 一次浏览器请求可通过 ID 追踪到 service/provider;测试 secret 被脱敏;应用错误向用户返回安全且已翻译的提示;告警直接指向操作员需要的日志查询。
Node runtime 使用 Pino,Edge 输出同形 JSON。日志写到 stdout 供托管平台收集,应用不管理日志文件。LOG_LEVEL 可设为 debug、info、warn 或 error。
让 request ID 贯穿 route、service、job、Stripe order/event 与供应商调用。记录 event 名、org_uuid、安全资源 UUID、job/order 号、耗时和结果等结构字段,不要只写叙述文本。
logger 会脱敏 authorization header、cookie、密码、token、API key 等秘密。不要记录原始请求体、预签名 URL 或账户导出数据。route 用 respError 记录内部上下文并返回安全翻译后的 error_code,绝不向浏览器输出 error.message。
监控 readiness、cron、重试耗尽、webhook action-required、延迟和异常 5xx,并用标识把 Slack 告警关联回日志;Slack 不是日志存储。
下一步: 只把需要处理的故障发送到 Slack 运维通知,并继续以结构化日志作为调查依据。