第十八章:可观测性要解释状态,不只保存文字
18.1 三种记录服务三种读者
用户希望知道工作进度,开发者希望定位错误,恢复器希望判断下一步能否安全进行。三种需求可以共享事件,但不应该被一条终端输出同时承担。
持久事件适合记录已接纳输入、完整回复和结算结果;实时进度适合展示流式片段;指标适合统计耗时、成本与错误率。DeepSeek 的日志与活跃事件区别、Claude 对 transcript 条目的类型判断,都提示这些边界不能仅凭屏幕显示决定。DeepSeek Harness · dispatch.ts L52–66 Claude Code 2.1.88 提取快照 · sessionStorage.ts L137–151
18.2 贯穿任务的关联身份
一条任务最好能关联 session、turn 或 step、model request、tool call 与执行端 process ID。关联不意味着所有项目必须使用相同命名,而是当一项工具失败时,能找到它来源的请求、参数、策略与后续影响。
记录时间也要说明时钟和边界。用户感知总耗时包括排队、审批、网络、工具执行与最终保存。只显示模型首字耗时,会遗漏用户真正等待的大部分工作。
18.3 少记录内容,多保留定位能力
日志可能包含源码、命令输出、用户消息和凭据。工程应在保留诊断价值与控制敏感数据之间做明确选择。可以记录类型、大小、哈希和受控附件定位符,并按需要对正文进行脱敏。
但脱敏不能让恢复记录失去关键身份。删除工具结果正文后,仍应保留 call ID、结果状态以及完整证据的受控存放方式。把一切内容替换成“已隐藏”,可能使后续调试无法区分工具失败和记录失败。
18.4 让界面展示确定性等级
“已开始”“等待中”“已确认完成”“结果未知”应有不同表现。如果长进程让出控制,应展示仍在运行或等待,而不是用绿色完成标记。若取消信号已发出但执行端尚未确认停止,也要保留这个中间状态。
来源于模型的自然语言可以展示,但不应覆盖宿主确认的状态。模型说“测试通过”时,界面仍应能链接到真正的测试结果。最终汇总也应区分检查过什么、没检查什么和已经观察到的限制。
18.5 做一次故障定位练习
设用户报告“点击发送后两分钟没有文字”。先查输入是否被接纳,再查是否有模型请求开始,是否收到流,是否有审批或工具在等待,最后查前端是否消费对应事件。不要一上来删除整个会话或重复启动任务。
本书实验的日志没有完整生产遥测,但每次请求、工具开始、结果和验收都有类型。你可以从 JSONL 统计出一次修复包含四个模型回复、三个工具调用和一次验收,并观察恢复后这些计数是否增加。