调试
昂贵错误在于修复第一个看似合理的原因。花费最初几分钟进行缩小范围,而不是修补。
方法
- 捕获确切的失败。 完整的错误文本、堆栈跟踪、退出代码、时间戳、请求ID、运行的命令。将其放入代码块。转述的错误会丢失那一个关键标记。
- 复现它。 找到最小、最快的方式按需触发它。如果无法复现,说明原因并从日志入手;不要默默猜测。
- 确定变更了什么。
git log --since、最近的部署、依赖项升级、配置或IAM变更、提供者升级、证书过期。大多数事件都是由变更引起的。 - 形成两个或三个假设,并按可能性及检查成本排序。在测试之前写下来。
- 一次测试一个假设,使用仅在该假设成立时才相关的变更。恢复没有帮助的更改;不要累积推测性编辑。
- 修复原因。 然后编写一个回归测试,该测试在没有修复时会失败(请参考
tdd技能)。 - 以与复现相同的方式验证,并运行更广泛的测试套件。
根据症状查找位置
| 症状 | 优先检查项 |
|---|---|
| 本地正常,CI失败 | 环境变量、密钥、操作系统/架构、Node/Python版本、缓存依赖、时区、工作目录 |
| 间歇性/不稳定 | 测试之间的共享状态、时间、顺序、网络、重试隐藏真实失败 |
| AWS AccessDenied | 哪个主体(aws sts get-caller-identity)、资源策略 vs 身份策略、SCP、权限边界、KMS密钥策略、区域 |
| Lambda超时/冷启动 | VPC连接、DNS、处理程序外初始化、内存大小、X-Ray中的下游延迟 |
| Terraform错误 | 提供者版本、状态漂移(terraform plan -refresh-only)、-target残留、锁定文件 |
| Kubernetes Pod未就绪 | kubectl describe pod、事件、探针、资源限制、镜像拉取、Secret/ConfigMap挂载 |
| 部署后5xx | 比较之前的镜像/提交、健康检查路径、环境/配置差异、数据库迁移顺序 |
规则
- 在阅读代码之前先阅读日志。日志告诉你“在哪里”;代码告诉你“为什么”。
- 如果需要,添加临时日志记录,并在提交前移除它。
- 切勿通过扩大权限、禁用TLS验证、捕获并吞掉异常或添加重试而不理解重试的对象来“修复”。
- 当你修复时,用一句话写下:原因、为什么没有被捕获、下次如何预防。这句话放在PR或提交正文中。