(本文含 AI 辅助创作内容)
排查一个「页面自相矛盾」的假故障,最后挖出的根因只有一句话:写某个字段的那条代码路径,在正常运行时从来不会被调用。但它藏得很深,值得完整复盘。
我们的自建监控工作台(一个本地 HTTP 服务渲染的看板)上有一张「服务健康」卡片,上面显示:
而同一页的页脚写着:
云端明明每 30 分钟自动推送一次(推送日志里每天都有成功记录),卡片却显示快照停在四天前。看起来像是「推送停了四天」,但翻日志,推送一直是好的。一个页面上两个关于「最近推送时间」的显示互相矛盾——这就是典型的假红:系统是好的,读数是错的。
排障顺序很重要。先确认真实状态,再查为什么显示错。
直接请求云端的 /status 接口,返回里有 pushed_at 字段:
pushed_at = 2026-10-16 21:25:24真值是二十分钟前。云端是好的。问题锁定在本机那张卡片读的到底是哪个字段。
顺着代码找,发现「最近推送时间」有两个存放处:
pushed_at,由服务端在每次收到推送时写入——这是真值。tools/.wb_cloud.json 里的 last_push 字段——卡片读的是它。关键问题来了:last_push 是谁写的?grep 全部调用方之后,答案浮出水面:
# tools/push_workbench.py(节选)
def push_current():
# ...上传看板 HTML 到云端...
# 注意:这里从不写 .wb_cloud.json 的 last_push
def main():
push_current()
# 只有命令行入口才会在这里写 last_push
state["last_push"] = now()
save(state)结构一目了然:push_current() 是被周期任务调用的那条路径,它只上传、不写时间戳;写 last_push 的代码在 main() 里,而 main() 只有手动在命令行跑这个脚本时才会执行。
所以时间线是:10-12 那天我手动推送过一次,last_push 被写成 23:02;此后每天的自动推送走的是 push_current(),这个函数从不碰这个字段。卡片恒显 10-12 的旧值。云端其实一直是新的,本地却四天没变——读数和事实脱钩了整整四天,没人发现,因为没有告警盯着这个字段。
def push_current():
# ...上传成功后,同样落一次真实时间...
state["last_push"] = now()
save(state)配套两处:
重启服务 → 触发一次重建 → 查推送日志新增成功记录 → 读状态文件确认 last_push 已更新到当前时间 → 刷新页面,卡片显示的时间和推送日志对上了,告警色消失。
这次复盘沉淀下来的判据只有一句话:
判断某个读数是否可信,先问「写它的那条路径」和「读它的那条路径」是不是同一条。
类似的变种我们都见过:计数器写在一个从不触发的分支里、状态字段只有手动模式才更新、备份脚本写的日志和监控读的日志不是同一个文件。共同特征是:功能在别的场景下验证过是对的,但在实际运行的入口上,写值的代码根本不会被调到。
更隐蔽的一点是:这类假红不会报错。字段有值、类型正确、页面能渲染,唯一的异常是「它太旧了」。所以对时间戳类字段,最有效的防线不是断言非空,而是加时效阈值——旧值本身就是告警。
一句话总结:读数是产品,写入是生产线;生产线没接上,读出来的就是库存里的旧货。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。