=== 核心技巧:体积用 index/volume_range,不要用 index/stats === 同为 24 小时、同一 selector,两条索引查询差 370 倍: index/stats : 整天聚合,实测 20s 直接超时(之前每日量接口卡 20s 的根因) index/volume_range: 按 step 分桶只累加 chunk 字节,实测 54ms,97 个桶 原因:index/stats 要跨全部 chunk 去重统计 streams/entries; volume_range 只把索引里记录的 chunk 字节数按时间桶求和,不解码内容。 === 后端改动 === services/daily_volume.go: 体积:LokiHistogram(走 volume_range,step 由跨度自动选)→ 累加 54ms 条数:只能 index/stats,降级为「尽力而为」25s 超时; 拿不到就保留上一次的值(不能因为一次超时把历史条数清零), 绝不让它拖住体积入库。 前端图只画体积,条数缺失不影响可读性。 === 前端改动 === DailyVolumeChart:AreaChart(面积)→ BarChart(圆柱) 顶部圆角 radius=[6,6,0,0]、渐变填充、maxBarSize=44 当天未结束的柱子用半透明 + 虚线描边区分,避免把"才过半天"误读成"量掉了" === 实测 === 24h volume_range: 54ms,97 桶,合计 369.61 GB(与全集群 ~370GB/天 吻合) /logs/daily-volume 接口: 10ms(读库) Pod = Hub latest = 4cdc8b9c4841
=== 一、告警引擎稳定性审查(引擎本身是异步的:ticker + goroutine)=== 1) 【高】ticker 无重叠保护 ticker 每 1 分钟触发;一轮规则检查 8 条 × 20~30s = 2~4 分钟,远超一分钟。 原来每过一分钟就再开一轮 → 查询越堆越多,抢走页面查询的 Loki 资源, 每轮越来越慢,最终表现为"告警不响了"。 → 新增 alertCheckRunning(atomic.Bool),上一轮未完成直接跳过本轮并记日志。 2) 【高】单条规则无超时 RunAlertCheck(context.Background()) 没有 deadline:Loki 一旦挂住,整轮永久运行, 叠加问题 1 会让引擎再也不启动新一轮(静默死亡)。 → 每轮总超时 5 分钟(alertRoundTimeout)+ 单条规则 90s(alertRuleTimeout)。 3) 【中】panic 只在整个 tick 层 recover 一条规则 panic 会让本轮后续规则全部跳过。 → per-rule recover,panic 记为一条 failed 投递记录,后续规则继续。 4) 【中】冷却记录每分钟写一条,把真实发送记录挤光 AlertDeliveries 只保留最近 50 条,而处于冷却期时每个 tick 都写一条 cooldown, 一小时内真实的"已发送"记录就全被挤掉了,发送历史没法看。 → recordCooldownThrottled():同一规则 10 分钟最多写一条。附单测。 5) 规则串行本身保留(避免同时压垮 Loki),但配合 1) 才安全。 === 二、每日日志量接口:20 秒 → 10 毫秒 === 根因:GetDailyVolumeHistory 里**同步** await 一次"整天 index/stats"补抓当天数据, 那次查询超时 20s → 整个接口 20s → 前端超时 → 页面显示"每日日志量没数据"; 更糟的是这条重查询还和页面的 histogram/stats 抢 Loki,导致那两个接口同时 502 (访问日志实证:daily-volume latency_ms 20000.997,stats/histogram 502)。 → 接口改为**只读库**,不触发任何 Loki 查询;当天数据由后台每 30 分钟的 定时任务补(CaptureRecentDailyVolumes)。 → 同时把整天 index/stats 的超时从 20s 提到 90s(370GB/天,20s 不够)。 实测:10ms。 === 三、通知通道改名「默认告警」(schemaVersion v8→v9) === "lark 默认告警" / "默认通知通道(待配置 Webhook)" → 统一为「默认告警」。 只改名,不动 Webhook、不动 enabled: 首次部署创建的占位通道必须保持「空 Webhook + 禁用」,由管理员自己填, 否则会出现"已启用但空地址"的通道,告警一命中就全部投递失败。 === 四、其它文案 === 「每日日志量」副标题精简为「每天的日志总量,平台保留历史趋势」, 并移除「平台留存历史」徽标(用户反馈多余)。 === 实测(303134c0c718)=== /logs/daily-volume:10ms(原 20000ms) 通道列表:id=1 name="默认告警" enabled=true hasWebhook=true go test ./... 全绿(含新增 TestRecordCooldownThrottled)
=== 1. 每日日志量必须落库(核心问题:Loki 只留 24 小时)=== 实测:请求"近 7 天每日量",Loki 只返回 27 个**小时**桶,全部在最近 24h 内 —— 因为 retention_period=24h,更早的 chunk 已经被删了。 也就是说「固定近 7 天」这张卡片,过去一直是"6 天空白 + 1 天有数据", 用户看着像坏了,实际是数据物理不存在。 方案:平台自己留存历史。 - models.DailyVolumeSnapshot{Date(本地YYYY-MM-DD), SourceID, Bytes, Entries, Partial} - services/daily_volume.go CaptureDailyVolume 按天抓 index/stats 落库(幂等覆盖) StartDailyVolumeCapture 启动 20s 后回补 + 每 30 分钟检查一次 GetDailyVolumeHistory 读库返回最近 N 天(今天会实时补抓) - 保留 400 天(够看年度趋势),按 source+date 去重 - 前端可选 7 / 30 / 90 / 365 天,能看多长取决于平台积累多久 为什么用"每 30 分钟检查昨天有没有落库"而不是固定 00:10 定时: 平台可能整晚没运行,固定时点的定时器会直接错过;检查式回补不依赖平台在线时刻。 Partial 标记(关键,否则会误读): - 当天未结束 → partial=true - 待抓取日期的起点已超出 24h 保留期 → partial=true(Loki 里就没那么多数据) 实测:10-27 32.5GB/2.65亿条 partial=true(保留期外), 10-28 348GB/28.56亿条 partial=true(当天进行中) === 2. 修一个 Go 副本 bug(自己写的,靠实测发现)=== 第一版用 `for _, snap := range db.DailyVolumeSnapshots` 后改 snap 字段, range 拿到的是**副本**,改动不会写回切片 → 同一天永远保持首次抓取的值, partial 也永不更新(实测发现 10-27 该是 true 却显示 false)。 改为 `for i := range ... { snap := &db.DailyVolumeSnapshots[i] }`。 === 3. 趋势图可读性 === 从"裸折线"换成"渐变面积图",并在图上方给出峰值 / 均值: - 面积图能一眼看出"这一段整体比上一段高",折线只能靠对齐格子数 - 峰值/均值避免用户自己对刻度 - Y 轴与 tooltip 统一 formatBytes,"每桶体积"写进 subtitle 顺带确认:趋势图只画体积(字节),不再混入 error(条数)——单位不同不能同轴。 === 4. 饼图:命名空间分布 → 应用日志量分布 === 本环境的命名空间只有 astralx / log 两个,饼图没有信息量; 改成按应用看谁在刷日志(前 8 名 + 其他),才是运维真正要的答案。 === 5. 告警页拆成三个 Tab === 「告警规则 / 通知通道 / 发送历史」独立成分页(用 ui/tabs)。 之前通道是折叠块、历史堆在规则下面,规则一多就要滚很久才看得到。 发送历史增加空状态文案,不再是"空页面不知道有没有在发"。 === 6. 内置规则关联默认通道 + 首次部署 webhook 留空的评估 === 结论:**webhook 可以留空,但通道必须是禁用状态**。 - 若种子给的是"已启用 + 空地址"通道,规则一命中就必然投递失败, 发送历史堆满红色失败,反而让人以为平台坏了 - 所以首次部署建一个**禁用**的占位通道「默认通知通道(待配置 Webhook)」, 内置规则全部挂到它;管理员填好 Webhook 再启用即可,不用逐条关联 - 保存时加校验:启用则必须有非空 Webhook(返回明确原因,不是裸 500) - schemaVersion v5→v6:把已有的"无通道"规则补挂到默认通道 实测:8 条规则全部已关联通道 === 实测(v11-1028-2252 / 187062644c0f)=== /logs/daily-volume?days=7 → 2 天数据,partial 标记正确 规则 8 条全部有 channelIds 平台 ready、健康 ok