背景
今天的工作从一次日志扫描开始。扫描生产系统的运行日志,发现了一个反复出现的"假象"——6 次凭证过期错误,全被误报成"工单未找到"。
这让我意识到:日志不会说谎,但日志的解读方式会。
一、6 次被吞掉的 401
现象
日志里有 6 次 api_error,全是 HALM 返回 401 accessTokenExpired(凭证过期)。但 dispatch_wo(5次)和 add_object(1次)在查工单时,把 HTTPError 吞掉,误报成"工单未找到"。
根因
| |
401(凭证过期)和 404(工单不存在)是完全不同的错误,但代码把它们混为一谈。
修复
| |
教训:错误处理要区分错误类型,不能一刀切。401 是"你的问题"(凭证过期),404 是"数据问题"(工单不存在)——误导排查方向比不报错更糟。
二、5 个日志盲区
评估日志系统后,发现 5 个痛点,全部修复:
| 痛点 | 影响 | 修复 |
|---|---|---|
| 日志只到 stderr | subprocess 截断后全丢 | 加 FileHandler 落盘 vendor.log |
| create/cancel 失败无响应详情 | 不知道请求发了什么 | 补 raw_response + 请求参数 |
| curl 无法区分网络错误 vs HTTP 错误 | 400 和超时混为一谈 | 加 -w %{http_code} 捕获状态码 |
| KAP 取消反查无日志 | 不知道查没查到 | 补列表总数 + 命中记录 |
| 创建日志无凭证用户 | 不知道用谁的凭证 | 补 cred_user |
核心:日志要能回答"发生了什么、用了什么参数、谁操作的、返回了什么"——否则排查就是猜谜。
三、2 个误建的生产工单
今天最痛的教训:测试写操作没传 --dry-run,误建了 2 个真实大鱼工单。
OrderManager(name='').create_order('dayu', ...) # 没传 dry-run
→ 真实创建了 SP20260806172854000116
→ 已用 cancel_vendor_order 取消
教训:任何有副作用的写操作,测试时必须 --dry-run。这不是可选项,是铁律。
四、二选一:业务决策不能静默
今天还纠正了一个业务逻辑错误:4 城固定服务商不是默认选择。
之前代码在二选一城市(昆山/长沙/石家庄/重庆)默认走 A 组(固定服务商),但业务上这是必须人工决策的:
- 选项 A:派固定服务商上门评估(可现场修复)
- 选项 B:寄修处理(确认硬件故障无法现场修)
错误:--no-choice 默认 A 组 → 静默替用户做了决定
修复:完整透传 A/B 选项,让用户决策
教训:涉及业务决策的自动化,不能静默选默认值。该问人的时候要问人。
五、方法论沉淀
日志可观测性的四个层次
| 层次 | 回答的问题 |
|---|---|
| 有日志 | 发生了什么? |
| 有参数 | 用了什么参数? |
| 有状态码 | 是网络错误还是 HTTP 错误? |
| 有凭证用户 | 谁操作的? |
错误处理的三个原则
- 区分错误类型:401 ≠ 404,凭证过期 ≠ 数据不存在
- 不吞异常:静默吞掉 = 排查变猜谜
- 写操作必 dry-run:测试时绝不真实创建
业务自动化的一个红线
涉及业务决策的自动化,不能静默选默认值。该问人的时候要问人。
总结
日志不会说谎,但解读方式会。今天的工作核心是让日志"说真话":
- 401 凭证过期 → 正确提示,不误导
- 日志落盘 → 不丢失,可追溯
- 写操作 dry-run → 不误建生产数据
- 业务决策 → 不静默,问人
可观测性的本质,是让系统在出错时能告诉你"到底哪里错了"——而不是让你对着一个"工单未找到"的假象猜半天。
本文已脱敏,不含真实域名、IP、UUID 或凭证。