Summer Bug Smash: 本文投稿自 DEV 的 Summer Bug Smash: Clear the Lineup 活动(由 Sentry 赞助)。 按周来看这个 bug 系列:390% CPU 小时无人察觉,一个没有出口的状态机,一次泄漏了 156 GB 的备份。第四周是终章——我把监控接入了产生此前所有三个 bug 的管道,而它抓到的最大的问题,就是它自己。 TextStack 是一个开源的科技书籍阅读器,基于 .NET 构建:ASP.NET Core API、后台 Worker、PostgreSQL + pgvector,前端 React。LLM 管道负责翻译、词语释义、“向这本书提问”的 RAG,以及三个生产环境 Agent(Enrichment、Librarian、Tutor),通过配置驱动的路由器在本地 Ollama 和 OpenAI 之间路由。代码公开在 github.com/mrviduus/textstack。 三周前,一个用户的 PDF 在我的 LLM 路由器中掉到了只能跑 CPU 的 Ollama 容器上,而不是 GPT-4.1。我的 CPU 在 390% 占用下烧了整整一个小时。零异常、零错误日志、零告警。而当我去查看现有可观测性记录了些什么时,答案是:什么都没有。OTLP 导出器指向的是一个 Aspire 仪表板容器,那个容器由 profile 控制,根本不会在生产环境运行。我的服务在生产环境产生的每一个 span,都被射进了一个已经关闭的 socket。 你从不阅读的可观测性,和从未安装的可观测性,无法区分。 那一行配置修复是提交 #1。这次提交修复的是这一类 bug——一个系统在错误地“成功”做事时,没有任何办法发出声音。 四个 PR 全部合并到 main;1,363 个单元测试,CI 全绿: **路由器现在会说明为什么。** 之前的路由解析是一个 `??` 链,产出一个字符串——无论操作者是刻意路由了一个任务,还是任务从末端掉落到了默认值,结果都一模一样。这个链不只是没有记录意图,它直接把意图抹掉了。所以现在它返回两个东西:一个结构化路由决策对象(包含解析路径、规则来源、匹配结果),以及原本的字符串供下游使用。路由决策会被记录到日志和遥测中,让每一次“为什么选这条路”都可审计。 **监控管道自身也被接入了监控。** 原来的 OTLP 导出不再指向那个 profile 门控、生产环境不存在的仪表板容器,而是独立部署的观测后端,带健康检查和死信告警:如果遥测数据本身没送达,系统会立即发出声音——不是等到下次人工排查才发现“哦,原来我们根本没在记录”。 这是这周最讽刺的一次捕获:不是生产 Agent 的错误,不是 RAG 的检索失败,而是监控管道自己在生产环境的首次“正确失败”——遥测到达了新的后端,告警规则触发,页面上的图表第一次显示出了“之前什么都没有”的巨大空洞。那个空洞,就是前三个 bug 存在了三周却无人知晓的原因。 如果你正在调试这种“系统成功做错事”的问题,回头看一眼你的监控:它真的在听吗?还是只是在对一个关闭的 socket 说话?
![]()
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.