ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

opencodex 失败诊断字段的 usage.jsonl 持久化:让 5xx 事故可复盘、可检索、不丢失

opencodex 失败诊断字段的 usage.jsonl 持久化:让 5xx 事故可复盘、可检索、不丢失 【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载导读opencodex 是面向 OpenAI Codex CLI / App / SDK 与 Claude Code 的通用 Provider 代理README.md。本文聚焦260716_claudecode_hardening工作包 3030_5xx_persistence.md的核心改动把请求失败诊断字段errorCode/terminalStatus/closeReason/upstreamError以additive追加式方式写入usage.jsonl持久化条目解决慢速 502 还是 SSE 中途response.failed无法判定的事故复盘盲区。读完本文你将理解这些字段的落盘语义、触发门槛、脱敏链路与验收断言方式并能直接在自己的部署中通过usage.jsonl回溯任意一次上游失败。背景一次无法判定根因的事故2026-07-16 的事故即260716事件暴露了一个根本性的可观测性缺陷当一次请求以失败结束时运维人员无法区分它到底是上游缓慢返回的 502还是SSE 流中途收到了response.failed。根因在于errorCode、terminalStatus、closeReason、upstreamError这四个诊断字段只存在于进程内存的 200 条环形缓冲区requestLog见 src/server/request-log.ts它们没有随持久化的usage.jsonl条目落盘导致事故发生后内存缓冲被新请求冲掉诊断线索永久丢失。修复策略在 000_plan.md 中定义为三道防线① 代理对 pre-stream 5xx 直接重试② 重试耗尽后映射为 Claude Code 可自行重试的529 overloaded_error③ 即本文——将失败条目以可判定形式持久化为下一次事件提供依据。设计原则不新建文件只在既有条目上做加法该方案的三个关键约束详见 030_5xx_persistence.md不新建日志文件失败诊断直接搭载在既有usage.jsonl条目上避免引入新的文件生命周期、轮转策略与消费端改造。Additive 兼容所有新增字段均为可选字段旧版读取器遇到未知字段会自然忽略因此向后兼容。只写失败不写成功成功条目2xx 且 terminal 为completed保持原样把对usage.jsonl文件增长速率的影响降到最低。实现拆解一PersistedUsageEntry新增可选诊断字段持久化条目的类型定义位于 src/usage/log.ts新增的四个可选字段约 L318-L329export interface PersistedUsageEntry { // ...既有字段... errorCode?: string; /** 封闭枚举来自 request-outcome.ts作为分组键落盘 */ terminalStatus?: RequestTerminalStatus; closeReason?: RequestCloseReason; /** 捕获时刻已完成 redactSecretString slice(0,500) */ upstreamError?: string; }注意实际实现中terminalStatus与closeReason使用的是封闭联合类型RequestTerminalStatus/RequestCloseReason而非文档初稿中的宽字符串字面量。这两个枚举定义在 src/usage/request-outcome.tsRequestTerminalStatus completed | failed | incomplete由结局分类派生aborted排除在外因为它是调用方主动离开而非上游终端RequestCloseReason terminal | client_cancel | non_stream | body_stall | body_overflow。为什么必须是封闭枚举注释给出了清晰理由terminalStatus一旦成为分组键grouping-key slot其值来自上游 terminal frame若类型开放上游可控文本就可能进入分组键request-outcome.ts 中isRequestTerminalStatus/isRequestCloseReason两个读回守卫正是为此而设。normalizeUsageEntryL814-L922在归一化路径中同样对这四个字段做了展开且terminalStatus/closeReason走校验而非真值判断...(entry.errorCode ? { errorCode: entry.errorCode } : {}), ...(isRequestTerminalStatus(entry.terminalStatus) ? { terminalStatus: entry.terminalStatus } : {}), ...(isRequestCloseReason(entry.closeReason) ? { closeReason: entry.closeReason } : {}), ...(entry.upstreamError ? { upstreamError: entry.upstreamError } : {}),这一白名单式归一化与surface、transportPhase等字段遵循同一纪律手改过的损坏行携带未知值时会丢弃该字段而非污染枚举。实现拆解二addRequestLog的失败门槛与字段投影写入侧的改动位于 src/server/request-log.ts 的addRequestLog。核心是仅在失败条目上构造failureDiagnostics并展开进appendUsageEntryconst failureDiagnostics entry.status 400 || (entry.terminalStatus entry.terminalStatus ! completed) ? { ...(entry.errorCode ? { errorCode: entry.errorCode } : {}), ...(entry.terminalStatus ? { terminalStatus: entry.terminalStatus } : {}), ...(entry.closeReason ? { closeReason: entry.closeReason } : {}), ...(entry.upstreamError ? { upstreamError: entry.upstreamError } : {}), } : {}; appendUsageEntry({ /* 既有字段逐字段重建 */, ...failureDiagnostics });这个逐字段重建而非整体 spread 的设计值得注意addRequestLog注释明确指出任何在函数体内漏写的字段都会到达/api/logs却永远到不了usage.jsonlL590-L592因为按 key 的 rollup 正是从usage.jsonl读取的。failureDiagnostics在重建序列的靠后位置展开L634紧随transportPhase/terminalSource之后。门槛语义status 400覆盖所有 HTTP 失败其中499 client-cancel 被刻意纳入——客户端主动取消同样具有诊断价值见 030_5xx_persistence.md 的说明。terminalStatus ! completed捕获HTTP 200 但语义上未完成的情况例如max_output_tokens截断导致的incomplete或 SSE 中途failed。这正是 request-outcome.ts 中classifyRequestOutcome强调先读语义终端、后读数字状态的原因一个 200 携带 incomplete terminal 的行是失败只有数字状态会把它误判为成功。成功条目2xx completedfailureDiagnostics为空对象{}落盘形态与历史完全一致文件增长速率影响最小。脱敏与截断上游错误文本的落盘边界upstreamError不会原样落盘。它的清洗发生在捕获时刻而非持久化时刻位于captureUpstreamError/captureUpstreamErrorParsedsrc/server/request-log.ts优先取response.failedSSE 负载error.message或非流式 JSON 错误体中的第一条非空原因保留原始失败避免被后续重试覆盖统一经过redactSecretString(...)脱敏来自 src/lib/redact.ts再slice(0, 500)截断保证密钥永不进入/api/logs与usage.jsonl无人类可读错误消息时回退到 bridge 发出的response.incomplete结构化原因如max_output_tokens、upstream_stall_timeout、adapter_eof映射为面向读者的标签incompleteReasonLabel。因此持久化侧无需再做任何额外处理PersistedUsageEntry.upstreamError的注释already redacted capped at capture就是这条链路的契约声明。四个诊断字段速查字段类型触发条件语义与来源errorCodestring可选status 400或非completed终端HTTP 映射错误码如 502 →upstream_server_errorterminalStatuscompleted \| failed \| incomplete同上语义终端来自上游 terminal frame作为分组键closeReasonterminal \| client_cancel \| non_stream \| body_stall \| body_overflow同上响应体为何停止被读取upstreamErrorstring可选同上已脱敏 500 字符截断的上游错误原因验收标准与断言路径030_5xx_persistence.md 定义的验收标准Accept criteria要求新增tests/usage-failure-persistence.test.ts失败条目四字段齐备以OPENCODEX_HOMEtmpdir隔离环境依赖 src/config.ts 中 per-call 的环境变量解析可在进程中途覆盖通过addRequestLog写入status: 502、terminalStatus: failed、closeReason: terminal、upstreamError的条目然后断言usage.jsonl最后一行 JSON 中四个字段全部存在。成功条目形态不变status: 200且terminalStatus: completed的条目诊断字段缺席保持既有形状。之所以只能走 env-var 隔离路径是因为addRequestLog直接调用appendUsageEntry无注入 seam测试中另有一条断言路径observeRequestLogsForTestssrc/server/request-log.ts可在内存环上观察落库前的条目配合 tests/claude-integration/claude-messages-endpoint.test.ts 中已有的terminalStatus: failedcloseReason: terminal断言模式交叉验证如该文件 L773-L774。完整验证矩阵见 000_plan.md 的 C-ACTIVATION-GROUNDING-01 一节其中失败持久化一行正是本文所述行为。显式排除项Out of scope为避免范围蔓延030_5xx_persistence.md 明确列出不新建日志文件、不改轮转策略、不做 GUI 暴露不修改 200 条环形缓冲区大小——持久化已达成目的缓冲区扩缩容无必要。复盘价值从看到 502到解释 502该改动让 opencodex 的每次上游失败都留下一条可解释、可检索、可聚合的持久化记录usage.jsonl中的失败行现在同时携带 HTTP 状态、语义终端、关闭原因与脱敏错误文本运维既可以用terminalStatus: failed精确圈出 SSE 中途失败也可以用status 400圈出 pre-stream 拒绝还能用closeReason: client_cancel区分用户主动放弃。它没有发明新的协议只是把已经在内存里存在的事实以兼容旧读取器的形式搬到了磁盘上——这正是 260716 事件教给项目的最小代价教训诊断字段若只活在内存里就等于不存在。赞分享【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载相关推荐三分钟制作专业有声书abogen跨平台AI语音生成终极指南三分钟制作专业有声书abogen跨平台AI语音生成终极指南 还在为制作有声书而烦恼吗想将PDF、EPUB文档一键转换为专业级语音内容吗今天我要为你介绍一个AI 应用语音音频媒体生成本地部署告别会话中断WezTerm持久化方案让你的工作永不丢失告别会话中断WezTerm持久化方案让你的工作永不丢失 你是否经历过这样的场景SSH连接突然断开导致远程任务中断本地终端意外关闭丢失重要工作状态或者需要桌面应用开发工具跨平台Vector gRPC 解压失败错误详情修复让 vector / opentelemetry 源的压缩请求故障可诊断Vector gRPC 解压失败错误详情修复让 vector / opentelemetry 源的压缩请求故障可诊断 导读 在 Vector 的 gRPC 系可观测性数据工程数据集成日志分析上一篇Jellyfin API 实战指南从认证到查库的 4 个场景下一篇彻底告别PS1画面撕裂ScePSX模拟器高精度渲染技术完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表