Files
blog/content/posts/logs-dont-lie.md
T

124 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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_wo5次)和 add_object1次)在查工单时,把 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 或凭证。*