重构 · 约 45 分钟
日志解析器:三种格式,一份复制粘贴
src/logparse.py 把三代服务写出的日志解析成记录,summarize() 再据此生成值班看板上的汇总。有两个告警任务也读这个汇总,所以每个键、每个值都得保持原样。测试是通过的,可代码只有两个长函数:时间戳校验、级别映射、服务名清洗在每种格式的分支里各贴了一遍,logfmt 的扫描也是直接内联手写的状态机。
把它重构好:
parse_line()和summarize()的名字和参数不变,对任何输入都返回和现在完全一样的结果,包括那些奇怪的情况(键重复时谁生效、什么算时间戳、哪些行算"跳过");- 不改行为,哪怕看起来像是在修 bug;
- 结构要改到
tests/test_metrics.py通过为止。
tests/test_metrics.py 用 Python 自带的 ast 模块统计 src/,并在程序输出里把起始代码的数值和你的数值并排打印出来:
| 指标 | 上限 |
|---|---|
| 最长函数的行数 | 25 |
单个函数或 lambda 里的分支数(if/elif、for、while、条件表达式、推导式里的每个 if、match 的每个 case,and/or 每多一个操作数算一个) | 8 |
重复代码块(连续三条语句,或三行以上的 if/for/while,忽略字面量和变量名后比较) | 1 |
src/ 里不能用 exec、eval 或 compile:从字符串运行的代码,上面哪一项都量不到。
建议的做法:
- 先把行为钉住。最危险的是那些怪癖:经典格式行尾重复出现的
key=value、ts为空的 JSON 行、带转义引号的 logfmt 值。可以让 AI 助手列出它看到的情况,再逐个实际运行代码核对。 - 把共用的部分(时间戳、级别、服务名)提到一个函数里,三种格式都调用它。
- 每种格式各写一个小解析函数,最后再简化
summarize();标准库里就有现成的计数器。
隐藏测试保留了一份原代码,会在精选的日志行和几千条随机生成的行上逐一比对你的结果,并且同样检查结构指标。你只能看到通过了几个。