我的观察器在一个月内静默地丢弃了代理日志行。我的CI每周都报告这个问题,但我却称它为不稳定测试。
摘要
作者描述了一个长达一个月的bug,其中代理观察器由于与文件监视器的竞态条件而静默丢弃日志行,最初被误诊为不稳定测试。修复方法是添加定期重新扫描以防止静默数据丢失。
如果你通过跟踪代理已经写入的日志文件来观察你的代理,这是一种值得你花十分钟了解的故障模式。我的运行了一个月,我的CI每周都报告它,我两次将其关闭为不稳定测试。设置:代理写入JSONL日志,一个中心节点按字节偏移跟踪它们,并将事件流式传输到查看器。一个文件监视器说“这个文件增长了”,跟踪器从它的最后偏移读取,新行被输出。很普通。
症状
一个测试间歇性失败,总是在最繁忙的矩阵行上。8月的macos/node 24。上周的ubuntu/node 24。六行中五行每次都是绿色的。测试打开观察器,启动第二个会话,等待中心节点注意到它,附加一行,并期望该行到达。我两次将其读作时间预算只是紧张,第二次我在测试文件的注释中写了这一点,这是最昂贵的错误。
什么杀死了假设
不是失败,而是失败输出。测试转储它接收的每一帧,其形状是:{“kind”:“ready”,“sessionId”:“late-sess”,“replayed”:12} {“kind”:“roster”, ...} {“kind”:“ready”,“sessionId”:“late-sess”,“replayed”:0} ... x26 二十六次在八秒内扫过,零字节读取,无错误,无重置。慢不会那样。慢最终会到达。那是一行永远不会到达的行。
机制
一个监视器异步启动自己。无论你使用fs.watch、fs.watchFile还是chokidar,在“我请求一个监视器”和“监视器已采用其基线”之间有一个窗口。在轮询模式下,基线是一个stat,之前写入的任何内容都在基线内。文件未被视为变化,因为相对于基线它从未变化。所以丢失数据的排序是:t0 赶上读取到EOF,偏移=S1;t1 行被附加,大小S2;t2 轮询器采用其基线:S2...之后没有任何东西与S2不同。我的时间戳将附加放在中心节点打开监视后2毫秒内。正好在其中。
为什么它从未恢复
这是实际的bug,是我的而不是库的。一个丢失的事件如果某物重新读取是可生存的。我有一个500毫秒的扫描来重新扫描子代理目录,它没有重新读取父日志。实时会话扫描对于已经流式传输的会话提前返回。所以主文件的唯一后备是监视器就绪事件触发的一次扫描——如果写入发生在就绪之后,那个机会已经用完了。会话中的每个文件都有一个底限,除了最重要的那个。
修复
重新扫描在同一刻度上读取主日志并重新扫描子代理。一次读取如果找不到任何东西成本一个statSync,因为当偏移已经在文件末尾时跟踪器立即返回。回归测试将监视器保持在一分钟一次轮询,因此监视器报告的任何内容都无法在测试内到达,只有扫描可以交付该行。没有修复时,它在所有平台上都是确定性失败的。
两件值得借鉴的事
将监视器视为尽力而为,并为你跟踪的每个文件提供一个定期底限。空闲时廉价,它将“静默丢失”转换为“最多延迟一个间隔”,这是不同类别的bug。并且:间歇性,仅在最繁忙的运行器上,是竞态条件的描述。不是按重试的原因。区分丢失事件和延迟事件的标志是系统是安静了还是在没有任何东西的情况下继续正确工作。
相似文章
我的管道"成功"运行了一周。结果发现我的代理一直在静默跳过失败的API调用。
一位开发者讲述了他们的自动化管道如何因速率限制静默跳过失败的API调用,产生了看似成功但实际包含空数据的运行。他们讨论了重试与硬失败之间的权衡,并向社区询问代理错误处理的最佳实践。
在生产环境中使用定时任务运行智能体一个月:四个出问题的点,无一归咎于模型
作者分享了在生产环境中使用定时任务运行AI智能体一个月时遇到的四个机械故障,强调所有问题都源于设置问题,而非模型缺陷。
第69天:我们的COMMS代理在24小时内执行中崩溃了3次。它揭示的模式。
一个AI代理(COMMS)在关闭步骤反复崩溃,揭示了按需代理特有的故障模式:工作成功后审计追踪失败。修复方法涉及调整关闭时的生成超时,凸显了需要独立的生命周期检查点。
自主智能体的发帖工具静默返回成功实为失败——监控层如何捕捉到这一缺陷
一位开发者讲述了监控代理如何捕捉到自主社交媒体发帖工具中的静默失败:该工具在未验证帖子是否真正发布的情况下便返回成功,通过URL变化和提示检测加以修复。
我让编程代理在基本无人监督的情况下运行了一个月。这是它们在我没注意时弄坏的东西,以及我之后的改变。
一位开发者讲述了无人监督的编程代理如何破坏意外文件并引入风险,促使他们构建了 VibeRevert,这是一个开源工具,可在代理会话前快照项目状态,以实现安全回滚。