结论有前提:如果功能开关会改变路由、模板或内容注入,而你又需要事后判断某次404是否由开关切换引起,那么记录应以“请求发生时的开关状态”为准,而不是以你排查时看到的当前状态为准。做不到这一点,版本记录就只能证明页面后来长什么样,不能证明404发生时页面处于哪个版本。
常见做法有两种。第一种是只记录代码版本,例如提交哈希、发布时间、发布分支。第二种是在代码版本之外,额外记录开关快照和它影响的页面范围。两者都合理,但成立条件不同。
代价也很直接:记录开关快照会增加采集频率、存储量和交接成本,而且开关组合可能很多,不可能全量保存。因此更现实的做法不是记录所有开关,而是只记录与URL生成、路由匹配、模板输出相关的开关,并标注采集时刻。
可区分的原因至少包括:路由未注册、重定向目标被关闭、模板分支不再输出链接、内容源被开关过滤。它们表现相似,但证据不同。
假设某站点在开关A关闭后,/promo/spring 返回404。若日志显示该请求发生时开关A确为关闭,且受控环境中仅切换A即可复现,那么可以初步判定关联。若日志缺失,只能看到“现在开关A是关闭的”,这不足以证明404发生时的状态,因为开关可能在404之后才被改动。
粒度取决于你要回答的问题。若只需判断“是不是这次发布引起的”,按发布批次记录开关快照即可。若需要判断“某个具体URL为什么404”,则要能还原该URL在请求时刻的路由与模板状态。
一个可操作的折中:每次开关变更时,写入一条带时间戳、变更人、开关名、旧值、新值和影响范围的记录;同时在发布产物中保存一份“影响URL生成的开关清单”。排查时先按时间窗口筛选变更,再对照日志中的配置版本号。这样做的结果是,你能快速缩小候选开关,而不是逐个试错;下一步动作也随之明确:要么补齐缺失的请求级快照,要么针对候选开关做受控复现。
反例:如果404来自CDN或反向代理层的缓存与重写规则,而开关只影响应用层,那么记录应用开关状态再完整也无法解释现象。此时请求可能根本没到达应用,日志里也不会出现对应的开关快照。另一个失效情形是开关状态本身没有版本化,只存在于运行时内存中,事后无法还原。
遇到这两种情况,应先把排查边界从应用层扩展到边缘层,确认请求在哪一层被拒绝,再决定是否需要为边缘配置也建立版本记录。否则继续补充应用侧记录只会增加成本,不会提高判断准确度。
先列出当前所有会改变URL输出或路由行为的开关,确认它们是否已有变更日志。对没有日志的开关,补一条最小记录:时间、开关名、值、操作者。然后在一次发布中验证:能否仅凭这些记录加服务端日志,回答“某URL在某个时刻是否应该可访问”。如果答案是否定的,优先补请求级配置版本号,而不是继续增加开关数量或扩大记录范围。