TT Lab
博客 开始
学习 学习路径 课程

故障指挥与复盘

受影响的有多少人——按规则统计影响

在 TT Lab 中继续学习

目标

从支付故障的访问日志中过滤掉不是用户的请求,合并重试,按规则统计人,求出请求、失败、错误率、受影响 用户。把这套规则做成脚本,使其对从未见过的日志也正确;最后修好给出不同数字的三个团队的 脚本。

为什么重要

影响数字是情况通告、赔偿、监管报告、SLO 直接拿来使用的值。可即使是同一份日志,去掉什么、合并什么不同, 数字就会差好几倍。放入健康检查,故障看起来比实际大;把请求数当作人数,影响就被夸大;丢掉区间的 时区,就会统计错误的时间段。在争论“谁对”之前先对齐规则,并把规则留成代码,这就是这个实验的核心。

步骤

  1. 用 python3 /opt/fixtures/ic/ickit.py open impact 展开素材,阅读 /root/ic/impact/README.txt 中的统计规则。把 access.log 中健康检查(路径恰好是 /healthz 或 /readyz)的行数,以一个数字写入 /root/ic/impact/answers/health.txt。
  2. 把从整个日志中去掉健康检查、机器人(User-Agent 中含 bot、crawler、spider,不区分大小写)、内部网段(客户端 IP 以 10. 开头)之后的行数,以一个数字写入 /root/ic/impact/answers/external.txt。
  3. 把事故区间(window.txt,KST)内首次尝试落入其中的外部请求数,以及其中最后一次尝试状态为 500 以上的请求数,以 requests=<n>、failed=<n> 两行写入 /root/ic/impact/answers/requests.txt(同一 req 的行是一个请求)。
  4. 按同一规则,以百分比(保留两位小数)计算事故区间的错误率,以及从日志开头到区间开始之前的平时错误率,以 error_rate=<percent>、baseline_rate=<percent> 两行写入 /root/ic/impact/answers/rate.txt。
  5. 把区间内至少有一个请求失败的人数,以及区间内发送过请求的人数,以 affected_users=<n>、active_users=<n> 两行写入 /root/ic/impact/answers/users.txt。人按 user= 统计,未登录的请求(user=-)把一个 session= 算作一个人。
  6. 让 /root/ic/impact/impact.sh <log> <start-iso> <end-iso> 按 README 的规则输出 requests=<n>、failed=<n>、affected_users=<n> 三行(需要执行权限,语言不限——由第一行的 shebang 决定)。区间参数是 2026-11-04T14:10:00+09:00 形式。评分器会用这个实验的日志,以及当场新生成的其他日志和区间来运行它。
  7. 运行 incident ic-impact-dispute 会触发故障事件。日志相同(/srv/impact/access.log)、区间相同(/srv/impact/window.txt),可 /srv/impact/bin/statuspage、support、sre 三个脚本的 affected_users 却各不相同。按 README 的规则修好这三个脚本,让三者都给出同一个真值(调用方式不变,直接写入数字会在其他日志上失败)。在 /root/incident/ic-impact-dispute/report.txt 中写下 statuspage: <code>、support: <code>、sre: <code> 三行以及 evidence: <defective-line>。每个脚本的代码是以下之一:includes-probes(没有去掉健康检查、机器人、内部网段)、requests-as-users(把失败请求数当作人数)、retries-double-counted(重试中只要失败过一次就算失败)、sampling-gap(日志样本缺失)、sessions-as-users(已登录的人也按会话分别计算)、window-timezone(丢掉了区间时刻的时区)。

参考

展开素材——健康检查有几行

用 python3 /opt/fixtures/ic/ickit.py open impact 展开素材,阅读 /root/ic/impact/README.txt 中的统计规则。把 access.log 中健康检查(路径恰好是 /healthz 或 /readyz)的行数,以一个数字写入 /root/ic/impact/answers/health.txt。

请求行在引号内包含方法、路径、协议。按空格切分,路径是第四栏。

只留下外部用户的行

把从整个日志中去掉健康检查、机器人(User-Agent 中含 bot、crawler、spider,不区分大小写)、内部网段(客户端 IP 以 10. 开头)之后的行数,以一个数字写入 /root/ic/impact/answers/external.txt。

User-Agent 是用引号括起来的第二栏——以引号作分隔符(awk -F'"'),它就是第四栏。在整行中查找 bot,可能会匹配到其他栏。

区间内的请求与失败——重试合并为一

把事故区间(window.txt,KST)内首次尝试落入其中的外部请求数,以及其中最后一次尝试状态为 500 以上的请求数,以 requests=<n>、failed=<n> 两行写入 /root/ic/impact/answers/requests.txt(同一 req 的行是一个请求)。

日志是 UTC,区间是 KST。要为每个请求分别记住首次尝试的时刻和最后一次尝试的状态——用 python 的两个 dict 很方便。

错误率与平时错误率

按同一规则,以百分比(保留两位小数)计算事故区间的错误率,以及从日志开头到区间开始之前的平时错误率,以 error_rate=<percent>、baseline_rate=<percent> 两行写入 /root/ic/impact/answers/rate.txt。

错误率 = 失败请求 ÷ 请求 × 100。分母和分子必须是同一规则(外部请求、重试算一个请求)。是百分比(9.33),不是比率(0.09)。

统计受影响的人

把区间内至少有一个请求失败的人数,以及区间内发送过请求的人数,以 affected_users=<n>、active_users=<n> 两行写入 /root/ic/impact/answers/users.txt。人按 user= 统计,未登录的请求(user=-)把一个 session= 算作一个人。

失败请求数与人数不同。已登录的人即使有多个会话,也是一个人。

把规则写成脚本

让 /root/ic/impact/impact.sh <log> <start-iso> <end-iso> 按 README 的规则输出 requests=<n>、failed=<n>、affected_users=<n> 三行(需要执行权限,语言不限——由第一行的 shebang 决定)。区间参数是 2026-11-04T14:10:00+09:00 形式。评分器会用这个实验的日志,以及当场新生成的其他日志和区间来运行它。

把前面三步的计算汇集到一个接收参数的文件中即可。不要丢掉区间参数的时区标记。

故障事件——三个团队的影响数字各不相同

运行 incident ic-impact-dispute 会触发故障事件。日志相同(/srv/impact/access.log)、区间相同(/srv/impact/window.txt),可 /srv/impact/bin/statuspage、support、sre 三个脚本的 affected_users 却各不相同。按 README 的规则修好这三个脚本,让三者都给出同一个真值(调用方式不变,直接写入数字会在其他日志上失败)。在 /root/incident/ic-impact-dispute/report.txt 中写下 statuspage: <code>、support: <code>、sre: <code> 三行以及 evidence: <defective-line>。每个脚本的代码是以下之一:includes-probes(没有去掉健康检查、机器人、内部网段)、requests-as-users(把失败请求数当作人数)、retries-double-counted(重试中只要失败过一次就算失败)、sampling-gap(日志样本缺失)、sessions-as-users(已登录的人也按会话分别计算)、window-timezone(丢掉了区间时刻的时区)。

方向:三个脚本是从同一个模板分岔出来的。与 README 的五条规则逐条对照,每个脚本都会出现一处错位。 工具:diff(把两个脚本并排)、不用 python3 -X 也能用 print 查看中间值、前面步骤的 impact.sh。 具体:依次查看过滤条件(路径、User-Agent、IP)、选择最后一次尝试的那一行、收集人的数据类型(是集合还是列表,放进去的是什么)、读取区间参数的那一行。修好后用同样的参数运行三者,确认数字是否收敛为一个。