- 新增三个下行帧(纯新增,既有帧名/形状零改动):observability_log / observability_trace / observability_metrics,各带 ≤1s 节拍、无新数据不发帧、单帧上限(日志 200 / span 100) - 帧壳 {type,data} 不带 sessionId;**不进 frameReachesAll 白名单** ⇒ fail-closed 只发 owner+admin (变异验证两次:加进白名单 → viewer 用例必红) - 推送开启条件=owner/admin 凭据「读过一次」对应 REST(引导数据仍由该次读取返回), 连接全断即退订并停循环(无常驻 goroutine);既有 REST 端点路径/RBAC/形状完全不变 - 前端:删除 logs/metrics/trace 三处 useAutoReload 轮询;新增 observabilityStream(引导+去重合并+窗口) 与 observabilityViews(三个面板 + WS 徽标),长列表统一走已落地的 VirtualList - 复核:build/vet 绿 + gateway 全包测试绿(含真 bus→真 /ws/chat 三角色帧断言)+ `-race`; 前端 tsc 0 错 + vite build 成功 - 待登记契约:api-client 需新增「可观测实时推送」一节
主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批: 已推库 16 个文件 + 本批剩余文件)。 校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0); 全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
- internal/logger/ring.go: Entry{time,level,source,msg} + RingBuffer(2000,满覆盖最旧,不阻塞)+ringHandler(slog旁路,Enabled委托内层,sourceOf提取source=再回落Scoped); Options.Ring非nil才包 - gateway/observability_logs.go: GET /admin/observability/logs?level=&limit= (writeAuth owner/admin) → {data:[{time(RFC3339 UTC),level,source,msg}]} 最新在前; level阈值过滤(warn=warn+error,已标注取舍); limit缺省200上限1000; 未知level400/未注入501 - routes.go注册 + observability.go SetLogBuffer(atomic.Pointer) + cmd/cyrene main.go/wireGatewayLogBuffer接线(logger先于gateway) - 控制台/文件输出零变化; 记录只源自已产出日志,不额外打印敏感 - Docs/api-client v0.35; 测试(ring 10 + observability_logs 8 + cmd端到端2); build/vet/test绿(56)+win/darwin交叉编译