observability-setup

为系统的关键路径设计可观测性:埋什么指标、日志里该打什么字段、链路追踪怎么串、SLO 与错误预算怎么定、告警阈值怎么取才不吵、值班拿到告警先做什么。当用户要给某个系统或模块设计监控、要加指标或埋点、想知道日志里该打什么字段、要接入链路追踪、要定 SLO 或错误预算、抱怨告警太多太吵要治理、值班看到告警不知道先干什么要写排查手册、上线前要准备观测手段时使用。也触发英文 monitoring / me

SKILL.md

GitHub

可观测性设计

把"这个系统出问题时我们能不能看出来、看出来之后知不知道该干什么"变成一份有清单、有阈值、有处置步骤的方案。设计的起点是关键用户路径与故障模式——用户在哪些路径上会感知到坏掉、这些路径会怎么坏——不先选工具——工具只是把方案落地的手段,换个工具方案本身不该重写。

先确定任务边界

  • 本 skill 产出观测方案:指标清单、日志字段规范、追踪透传点、SLO 与错误预算、告警规则表、值班手册。它不直接改代码、不代接采集端管道、不动生产告警配置,除非用户明确要求并逐项确认。
  • 设计对象是路径与故障模式,不是"把某个 SDK 接进来"。用户只给出技术栈时,先索取关键用户路径,不要直接堆一堆通用指标。
  • 观测手段的覆盖率必须如实标注:设计出来还没落地、还没接采集、还没验证触发过的部分,一律写进"未验证项",不要写成"已具备"。

设计路径

  1. 找关键用户路径。 问清并写下:用户(或上游调用方)在什么入口发起、经过哪几个服务与外部依赖、什么结果算成功。只覆盖少数几条真正重要的路径(主流程、支付/下单一类不可失败的动作、登录鉴权、对外接口),不要试图覆盖所有代码。路径清单没确定就不进入下一步。
  2. 列出每条路径的故障模式。 逐条问"这条路径会怎么坏":依赖超时或拒绝、部分成功、数据不一致、慢查询积压、资源打满、限流或熔断触发、重试风暴、异步任务丢失、配置错误。故障模式决定要观测什么——没有对应的故障模式,就不要为它加指标或告警。
  3. 按故障模式推导监控点。 每个监控点写清三件事:看什么信号(指标 / 日志 / 追踪)、在哪一层看(入口、服务内、依赖、资源)、什么数值算不正常。推导办法见 references/metrics-and-logs.md。
  4. 定指标口径与类型。 四类信号各就位,指标类型按语义选,维度按基数预算选;尾延迟看分位而不是平均值。
  5. 定日志字段与追踪透传点。 按统一字段规范约定字段名与语义,把 trace 上下文在已知的断链位置逐个补上。
  6. 定 SLO 与错误预算。 从用户可感知的成功率与延迟定义 SLO,给出目标值与错误预算的换算关系,以及预算烧完时的处置动作。
  7. 定告警规则与值班手册。 只对"需要人现在做点什么"的情况设告警;每条告警配级别、阈值、持续时间、通知对象与第一处置步骤。
  8. 写方案文档。 按 assets/observability-plan-template.md 落地,并把未覆盖风险与未验证项单独列出。

四类信号与指标类型

四类信号(golden signals)必须在关键路径上各有着落,缺哪一类都要在方案里写明理由:

信号 看什么 常用口径
延迟 用户等多久 请求耗时、队列等待时间、依赖调用耗时
流量 现在有多大压力 每秒请求数、消息处理速率、并发数
错误 有多少请求坏了 错误率、失败计数、重试与超时次数
饱和度 还有多少余量 线程池/连接池占用、队列深度、CPU/内存/磁盘/配额使用率

指标类型按语义选,不要混用:

  • counter(只增):请求总数、错误总数、处理字节数。查询时用 rate() 一类函数取增量,不要把 counter 当瞬间值用。
  • gauge(可升可降):队列深度、连接数、内存占用、当前在线数。它只反映此刻,不能靠它算速率。
  • histogram / summary(看分位):请求耗时、响应体积。用它们算 P50 / P95 / P99,而不是自己维护"平均耗时"。

禁止用平均值掩盖尾延迟。 平均耗时 50ms 完全可能是 99% 的请求 10ms、1% 的请求 8s。用户的体感来自尾部的慢请求,平均值的改善往往只是把慢请求挪走或稀释掉。因此延迟类指标一律看分位,并写清是哪个分位、在哪个时间窗内、以及样本量是否足够回答问题。

标签基数

高基数维度不得作为指标标签:user_id、订单号/交易号、完整 URL(含路径参数与查询串)、traceId / spanId、session id、时间戳、错误消息原文、任意自由文本。它们会让时间序列数量随业务量线性膨胀,带来两个后果:存储与查询成本失控,以及查询退化——聚合与看板越来越慢,直到没人愿意打开它。

正确的做法:

  • 需要按人/按单排查时,把它们放进日志与追踪,用具体标识去检索那一次请求,而不是做成指标维度。
  • 指标上只保留基数可控、枚举有限的维度:服务名、实例、接口模板(把路径参数归一化,如 /orders/{id})、状态码、错误类别、租户分层(如需按客户看,用有限的分组或聚合维度,不要用客户 ID)。
  • 设计时给每个维度估算基数上限,超预算的维度要么换成分组,要么下沉到日志。

日志

日志是"能定位到具体那一次请求"的手段。字段与格式的设计要求:

  • 必需字段:时间戳、级别、消息、traceId / requestId、服务与实例、关键业务标识(如订单号、租户、用户可见的操作类型)。
  • 结构化输出:以键值(JSON 或等价结构)输出,便于检索与聚合;不要把关键信息塞进一句自由文本里。
  • 异常必带堆栈:记录异常时带上类型、消息与堆栈;不要只记 e.getMessage() 把现场丢掉。
  • 不得记录密钥、令牌、口令与个人敏感信息:密码、Authorization 头、token、Cookie、身份证号、银行卡号、手机号、详细地址等一律不落盘;需要定位时记录脱敏后的形态或哈希,并在方案里写明脱敏方式。

本 skill 定的是字段与设计要求(该有哪些字段、叫什么、什么不能记)。具体到代码里某条 log 语句怎么写、级别怎么调、traceId 断了怎么补,由 code-logging 改代码,本 skill 不改。

追踪

追踪回答"这一条请求在各段各花了多久、在哪一段坏的"。关键不在接入 SDK,而在上下文是否连续:

  • traceId 必须跨线程池、异步任务、消息队列与跨服务边界透传,否则一条调用链会碎成互不相关的片段。
  • 常见断链位置要逐个检查:线程池与任务队列(上下文没随任务提交传递)、异步回调与响应式链(中途切线程)、HTTP/RPC 出站调用(未注入透传头)、MQ 生产与消费(未随消息头/属性携带)、定时任务与批处理(无上游,需要自己起一条新链并记业务标识)、网关与网关后的第一跳、日志框架的 MDC/上下文绑定、跨语言或跨团队的边界(需约定头名与格式)。
  • 采样率要写进方案:全量采样在高峰期可能不可承受,降采样必须保留错误与慢请求,不能把最有价值的样本采掉。

透传点清单见 references/metrics-and-logs.md。

SLO 与错误预算

  • SLO 从用户可感知的指标定义:选一条关键路径的一个可观测结果(成功请求比例、延迟低于某阈值的比例),而不是选"CPU 不超过 80%"这类内部状态。
  • 写法要完整:SLI(怎么算)→ 目标值(如 30 天滚动窗口内 99.9%)→ 窗口 → 数据来源。
  • 错误预算 = 1 − 目标值:99.9% 在 30 天窗口内约等于允许约 43 分钟的不可用额度。预算的意义是让"能不能冒风险发版/做变更"变成可算的问题,而不是靠感觉争论。
  • 预算烧完时的处置要提前写清:暂停非必要的风险变更、把人力转向可靠性修复、触发可靠性评审;如果预算长期用不完,说明 SLO 定得偏松,应重新评估目标值。具体换算与烧完处置见 references/alerting-and-runbook.md。

告警

告警必须可行动:每条告警都要写清"看到后该做什么"。一条告警如果值班只能看着它、或者能做的只有"再等一会",它就不是告警,是噪音。

  • 禁止把每个异常都设告警。 代码里每个 catch、每个非零退出、每条 ERROR 日志都设告警,结果是告警量与代码复杂度同步增长,真正需要人介入的那条被淹没。只对用户可感知的坏结果或明确的容量风险设告警。
  • 阈值与持续时间一起取。 只有阈值没有持续时间的规则会被抖动打爆;要不要 for: 5m、窗口多长,取决于该路径的正常波动幅度和你能容忍的发现延迟。取法见 references/alerting-and-runbook.md。
  • 告警分级:按影响面与紧急度分级,并给每级配好通知路由与升级路径(谁在哪里收到、多久没响应升级给谁、什么情况直接叫醒人)。
  • 通知路由:告警要送到真正能处理它的人手上,并写明需要人立即行动还是次日处理;不要在多个渠道重复轰炸同一条告警。
  • 宁可少而准。 十个人人忽略的告警,不如一条每次都能指出问题的告警。定期 review 从不被行动的告警并删掉它。

值班手册

每条告警在手册里至少要有:这条告警意味着什么 → 第一处置步骤 → 需要看哪个看板/执行哪条查询 → 判断"恢复了没有"的判据 → 什么时候升级给谁。手册的操作步骤要具体到能照做(看哪个面板、跑什么查询、看哪个字段),而不是"检查一下服务状态"。模板见 references/alerting-and-runbook.md。

交付内容

用简洁中文给出:

  1. 关键用户路径与故障模式:路径清单 + 每条路径会怎么坏。
  2. 指标清单:名称、类型、标签与基数预算、含义、正常范围。
  3. 日志字段清单与脱敏说明:字段名、语义、必填与否、哪些字段属于敏感信息及其脱敏方式。
  4. 追踪透传点:需要补透传的位置、采样策略、已知断链点。
  5. SLO 与错误预算:SLI、目标值、窗口、预算额度、烧完后的处置。
  6. 告警规则表:规则、阈值、持续时间、级别、通知对象、第一处置步骤。
  7. 看板与查询:每个看板回答什么问题、关键查询语句。
  8. 未覆盖风险与未验证项:哪些路径还没观测手段、哪些规则只是设计出来还没落地验证。不夸大——不得声称未验证的告警已生效、未接入的指标已可用。

建议落点为 .docs/70-运维保障/ 下的观测方案文档(沿用仓库既有命名规范),或直接按模板产出单文件方案。

与相邻 skill 的边界

  • 代码里 log 语句本身的写法与规格化:code-logging。本 skill 定字段与设计要求,code-logging 改代码里的 log 语句。
  • 发布前的准出检查、回滚预案、观测手段是否就位:release-readiness。本 skill 提供观测方案,它判断够不够发。
  • 线上已经出问题需要现场止血与分级:incident-response。
  • 单个故障的根因定位:systematic-debugging。
  • 性能压测、基线与优化验证:performance-investigation。本 skill 只负责把延迟指标观测到,不负责优化它。