日志采样应该如何设计?
简化版
日志采样应优先保留错误、审计、安全和稀有事件,对高频健康日志按稳定规则采样或聚合。采样必须记录原始数量估计与规则版本,不能让低流量租户或一次性错误完全消失。
详细版
在应用端减少无价值日志,在 Collector 按 service、level、errorCode 和 trace 状态做集中策略;相同模板可按窗口限频并输出 suppressed_count。对同一 traceId 使用确定性采样,使一条链路的日志尽量成组保留。
告警依赖的日志不应在无校正时采样;审计日志独立管道全量保存。监控采样前后字节、丢弃率、规则命中、租户覆盖和事故回溯成功率,并为临时提采样设置自动到期。
完整版教学
一、为什么不能随机丢一半
错误往往稀有,均匀 1% 采样可能把唯一故障丢掉;高频健康日志却仍占绝大多数。策略应依据诊断价值和频率,而不是只依据统一比例。
心法:先保证“重要事件必见”,再压缩“重复健康噪声”。
二、采样规则分层
| 日志类型 | 建议 | 原因 |
|---|---|---|
| 审计/安全 | 全量独立保存 | 合规与取证 |
| ERROR/未知异常 | 高比例或全量 | 稀有且高价值 |
| 健康访问日志 | 比例/速率采样 | 高频重复 |
| DEBUG | 按需短期开启 | 成本大 |
级别并不天然代表价值,业务拒绝可能是 INFO,却影响关键转化。
三、确定性采样
keep = hash(trace_id) % 100 < 5
同一 traceId 的各服务使用相同规则,可避免只保留链路中间一段。没有 traceId 时可用稳定请求键,但不得把敏感 ID 原文输出。
四、模板限频与计数
同一“连接超时”每秒出现 10 万次时,可每窗口保存代表样本,并输出 suppressed_count=99999。只保留一条而无计数,会让故障规模看起来很小。
模板归一要使用 errorCode,不要直接按异常文本聚合,否则动态 ID 会让每条都不同。
五、动态采样
正常时健康日志采 1%,错误升高时将相关服务、route 或 trace 提到 20% 或全量,同时受总预算保护。事故恢复后规则应自动回落,避免长期成本泄漏。
变更要版本化、审计,并在日志元数据注明 sample_rate,查询侧才能正确估算总量。
六、如何验证没有采坏
离线用历史事故回放规则,检查关键错误是否仍可见;线上比较采样前后 errorCode 分布、租户覆盖和告警命中。低流量分组可设最小样本保障。
采样后的计数若要估算总量,应使用已知概率加权;自适应和限频样本不能简单乘固定倍数。
采样决策发生在应用端时,要避免日志库异常阻塞业务线程;缓冲区满的丢弃策略和计数必须可观测。
规则部署先灰度到单个服务或租户,对比丢弃量和查询结果后再扩大。
对于法律保留事件,应绕过普通采样并写入独立、不可变且权限更严的通道。
七、常见误区与追问
- 误区:ERROR 全量、其他统一 1% 就够。 业务异常不一定记录为 ERROR。
- 误区:采样日志可直接计数告警。 必须校正概率或使用指标。
- 误区:只在存储端丢弃即可。 网络和 Collector 成本已经发生。
- 误区:事故时永久打开 DEBUG。 应限范围、限时并自动恢复。
- 追问:如何保留完整链路日志? 对 traceId 做一致的确定性决策。
- 追问:重复错误怎么压缩? 模板限频、代表样本和 suppressed_count。
- 追问:审计日志能采样吗? 通常不能,应独立不可篡改地保存。
八、加强记忆
日志采样按“价值分级—确定性成组—重复限频带计数—动态提采样—预算与验证”设计。错误、审计和稀有事件优先,健康噪声压缩;规则必须可追溯、可自动回落,并用历史事故证明降量后仍能定位。