4. 日志采集策略:从源头掐掉“无用”的日志
日志量为什么总是失控?
我见过太多团队,一上来就把所有日志全量采集,结果磁盘撑爆、检索慢得像蜗牛。其实很多日志根本没人看,或者看了也没用。源头控制,说白了就是“能不采就不采,采了就采有价值的”。这一章,我专门聊聊采样率和级别过滤这两个最实在的省钱手段。
核心原则:每一条日志生成前,先问自己三句话——
- 这条日志是谁用的?
- 如果丢了,会不会影响故障排查?
- 能不能用更低成本的方式替代?
答不上来的,基本都可以砍掉。
4.1 级别过滤:别让DEBUG日志占用你宝贵的存储
先问个基础问题:你们的日志级别是全部开的,还是分级开的?
我在很多项目里看到,开发为了方便,写日志时随手就INFO,甚至把DEBUG级别直接带到生产。结果呢?一个日活百万的应用,光DEBUG日志一天就能跑出几十GB。我经历过一次教训——一次大促前,业务方要求加日志追踪用户行为,结果忘了改级别,当天日志存储直接超预算3倍,紧急扩容花了冤枉钱。从那以后,我把级别过滤写进了CI/CD的检查卡点。
我的建议:生产环境只保留WARN和ERROR级别的日志,INFO按模块按需开启,DEBUG不能开。
如果实在需要DEBUG日志用于线上排查,用“动态开关”模式——比如在配置中心打个标记,临时开启某个模块的DEBUG,排查完立刻关闭。别让DEBUG睡在生产环境里。
级别过滤的配置示例(以logback为例):
<!-- 生产环境只保留WARN和ERROR -->
<root level="WARN">
<appender-ref ref="FILE"/>
</root>
<!-- 支付模块单独开INFO,用于业务监控 -->
<logger name="com.mycompany.payment" level="INFO"/>
<!-- 风险控制模块临时开DEBUG(排查完必须关掉) -->
<logger name="com.mycompany.risk" level="DEBUG"/>
你看,只要控制好级别,一天就能砍掉70%-80%的日志量。这可不是估算,我测过一个中型电商系统,全开INFO日均日志200GB,改成WARN+ERROR后直接降到30GB,六分之一的量。
4.2 采样率:不是所有请求都需要记录
级别过滤能干掉大多数低价值的日志,但WARN以上的日志依然可能很多。比如接口异常、调用超时,虽然级别高,但量一大照样撑不住。这时候就得靠采样了。
采样,说白了就是“抽着记”。我常用的几种策略:
| 采样策略 | 适用场景 | 成本效果 |
|---|---|---|
| 固定率采样(如10%) | 高流量、重复性高的访问日志 | 直接节省90%存储 |
| 自适应采样 | 流量波动大,低峰期全量,高峰期降采样 | 平衡排查与成本 |
| 错误全量 + 正常采样的混合策略 | 需要保证异常日志不丢失 | 成本可控且故障可追溯 |
举个例子。我曾经维护过一个视频推荐系统,每天几十亿次请求。如果每条请求日志都落盘,存储成本惊人。我们用的方案是:
- 错误请求(HTTP 4xx/5xx)全量记录,一条不丢;
- 正常请求按1%随机采样,只在用户投诉或做A/B实验时才临时放大采样率到10%;
- 关键指标(如推荐点击率)单独采集,不依赖日志采样。
这个方案落地后,日志存储成本下降了85%,而排查问题的能力几乎没有减弱。
避坑指南:我曾经踩过的两个采样坑
第一个坑:采样率设成常数,比如固定10%,结果业务高峰期流量翻倍,日志量也跟着暴增。后来改成了基于令牌桶的限速采样,保证日志写入速率不超过磁盘IO瓶颈。
第二个坑:采样只对同一类日志生效,却忽略了“低频重要事件”。比如某个接口虽然只返回一次错误,但这次错误背后的原因很重要。我的做法:对错误码、异常类型做单独的白名单,白名单内的日志永远全量,剩余的部分才按采样走。
4.3 动态开关:把采样率变成可配的参数
你想想看,如果一个系统上线后采样率就写死在代码里,运营人员改起来多麻烦。我个人习惯是把采样率做成配置中心参数,通过Apollo或Nacos实时下发。
# 配置中心示例
log.sampling.enabled=true
log.sampling.rate=0.05
log.sampling.whitelist=com.mycompany.keymodule.*
配合监控,一旦发现某个时段异常增多(比如突然来了攻击流量),可以临时关闭采样,全量记录所有日志用于事后分析。分析完再把采样率调回来。整个过程不用重启应用,也不用重新发布。
4.4 不要忽略的细节:日志内容和格式精简
你可能觉得这只是小头,但我算过一笔账:
- 一条日志里带了完整的堆栈信息(50行),占用约2KB;
- 如果只保留关键错误消息和类名、行号,不到200字节。
假设每天10亿条日志,每条多写1.8KB,就是1.8TB的额外存储。一年下来多少钱?按云上对象存储每GB每月0.12元算,仅这一个细节就能省下近3万元/年。嗯,去掉堆栈,保留摘要,是我做过的性价比最高的优化之一。
一个小技巧:在日志框架里用MDC(Mapped Diagnostic Context)把请求ID、用户ID、业务流水号等关键字段统一放在一条日志的头部,然后正文尽量简短。这样既保留了上下文,又不会把日志撑得太肥。
到这里,你应该能感受到:源头控制不是一刀切地“少记”,而是精细地“选着记”。级别过滤砍掉废话,采样率稀释高频噪音,内容精简去掉冗余。三者结合,成本自然下来。