diff --git a/content/posts/logs-dont-lie.md b/content/posts/logs-dont-lie.md new file mode 100644 index 0000000..76bf161 --- /dev/null +++ b/content/posts/logs-dont-lie.md @@ -0,0 +1,123 @@ +--- +title: "日志不会说谎:从 401 误报到可观测性改造" +description: "一次日志扫描,暴露了 6 次被吞掉的凭证过期错误、5 个日志盲区、2 个误建的生产工单。当错误被静默吞掉,排查就变成了猜谜。" +date: 2026-08-06T18:09:33+08:00 +draft: false +tags: + - 运维 + - 日志 + - 可观测性 + - 排障 +--- + +## 背景 + +今天的工作从一次日志扫描开始。扫描生产系统的运行日志,发现了一个反复出现的"假象"——**6 次凭证过期错误,全被误报成"工单未找到"**。 + +这让我意识到:日志不会说谎,但**日志的解读方式会**。 + +## 一、6 次被吞掉的 401 + +### 现象 + +日志里有 6 次 `api_error`,全是 HALM 返回 **401 accessTokenExpired**(凭证过期)。但 dispatch_wo(5次)和 add_object(1次)在查工单时,把 HTTPError 吞掉,**误报成"工单未找到"**。 + +### 根因 + +```python +# 错误写法:把 HTTPError 当"未找到"处理 +try: + wo = query_wo(wo_num) +except urllib.error.HTTPError: + print("工单未找到") # ← 401 凭证过期也被当成"未找到"! +``` + +401(凭证过期)和 404(工单不存在)是**完全不同的错误**,但代码把它们混为一谈。 + +### 修复 + +```python +except urllib.error.HTTPError as e: + if e.code == 401: + print("凭证已过期,请重新登录") # ← 正确提示 + else: + print("工单未找到") +``` + +**教训**:错误处理要区分错误类型,不能一刀切。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 错误? | +| **有凭证用户** | 谁操作的? | + +### 错误处理的三个原则 + +1. **区分错误类型**:401 ≠ 404,凭证过期 ≠ 数据不存在 +2. **不吞异常**:静默吞掉 = 排查变猜谜 +3. **写操作必 dry-run**:测试时绝不真实创建 + +### 业务自动化的一个红线 + +> 涉及业务决策的自动化,不能静默选默认值。该问人的时候要问人。 + +## 总结 + +日志不会说谎,但**解读方式会**。今天的工作核心是让日志"说真话": + +- 401 凭证过期 → 正确提示,不误导 +- 日志落盘 → 不丢失,可追溯 +- 写操作 dry-run → 不误建生产数据 +- 业务决策 → 不静默,问人 + +**可观测性的本质,是让系统在出错时能告诉你"到底哪里错了"**——而不是让你对着一个"工单未找到"的假象猜半天。 + +--- + +*本文已脱敏,不含真实域名、IP、UUID 或凭证。*