机器人在现场出问题后,日志通常是唯一的线索。但常见的日志只能回答“出错了”,回答不了当时在做什么、哪一步超时、以及这个错误属于哪次任务。缺少这些信息,复盘就只能停留在猜测。

这篇文章讨论的是把日志当作证据来设计:不是为了记录更多,而是为了在事后能回答几个具体问题。

定义要回答的问题确定必要字段统一时间基准贯穿任务与请求 ID记录状态转换而非仅错误可检索与可复现
可用日志的要素时间、身份、状态与原因缺一不可,否则只能证明“出过问题”。
时间戳统一时钟来源,并区分事件发生与记录写入。任务与请求 ID把跨进程、跨层的事件串成一次执行。状态转换记录从什么状态进入什么状态,而不是只记录失败。原因码可枚举的原因分类,便于统计与对比。上下文当时的配置、输入摘要和版本指纹。可检索结构化字段比自由文本更容易被筛选。

先写出你要回答的问题

设计字段之前先列出复盘时要回答的问题。常见的几个:这次任务从哪台设备、哪个请求开始;在哪一步超时;超时前最后收到的有效反馈是什么;同一时刻有没有其他错误;这个问题在这台设备上出现过几次。

这些问题决定了字段,而不是反过来。如果先写日志再想用途,很容易得到大量重复的“进入函数”“离开函数”记录,却在关键判断点缺少信息。

身份字段比详细描述更有用

一段日志如果只有时间和文本,跨进程的同一件事就无法关联。加入以下字段能显著提高可检索性:

1
2
3
4
5
6
7
8
9
ts=2026-09-14T09:30:12.481+08:00
level=WARN
component=device_bridge
task_id=task-2026-09-14-0007
request_id=cmd-0042
from=WAITING_ACK
to=SAFE_STOP
reason=ack_timeout
elapsed_ms=253

关键点是 task_idrequest_id 贯穿所有层。上层任务、设备命令和设备侧反馈都带同一个标识时,事后可以把它们按时间排成一条链,而不需要在文本里猜哪个是相关的。

时间基准要统一并说明来源

不同进程使用不同的时钟来源,会让排列出来的顺序失去意义。至少要明确:时间戳来自哪个时钟、是否与外部时间同步、以及单位。

对于有超时逻辑的系统,记录单调时钟差值比记录墙上时间更可靠,因为墙上时间可能被同步步骤调整。需要跨机器比较时再记录同步后的墙上时间,并标注同步状态。

只记录墙上时间而不记录单调时间,会让那些“时钟跳变导致误判超时”的问题无法被发现。

状态转换比错误字符串更有解释力

只记录“ack 超时”只能说明发生了什么,记录状态转换才能说明系统当时如何理解这件事。上面的示例中 fromtoreason 三项组合,既能做统计也能做流程重建。

原因码建议使用可枚举的集合,而不是自由文本。自由文本适合补充细节,不适合聚合分析。一个稳定的原因码集合,能直接支持“这台设备最近两周最常出现哪种停止原因”这类问题。

高频路径上的日志要有限制

机器人程序里有一部分日志出现在高频路径上,例如每次控制周期或每帧处理。在这些位置无差别打印会改变时序,让原本要观察的性能问题被日志本身掩盖。

可行的做法是分层:正常路径只在状态变化时记录,异常路径按原因码记录并做限流,详细跟踪通过可运行时开启的开关控制。限流要在日志里显式说明“已丢弃 N 条”,否则事后无法知道记录是否完整。

和可复现性的关系

日志能让问题可解释,但不一定能让问题可复现。要复现,需要记录输入和环境:当时的配置、软件版本、以及关键输入数据是否被保存。

如果一次超时与某个传感器输入相关,而没有保存当时的输入,那么日志只能说明超时发生,无法重放。此时补充数据录制比增加日志更有效。两者是互补关系:日志说明发生了什么事,录制数据说明为什么会发生。

参考资料

证据边界

本文讨论日志字段设计与记录策略,不包含任何具体系统的日志样例数据。字段集合需要按要回答的问题裁剪;日志能证明系统当时如何判断,不能证明物理世界发生了什么,涉及执行器行为的结论仍需设备侧反馈或独立测量支持。