线上出问题了。你第一反应是什么?我相信绝大多数开发者的答案是:看日志。但现实往往是——日志散落在十几台服务器上,你得一台一台 SSH 上去 grep;或者日志只有最近两天的,三天前的已经被滚动覆盖了;更糟的是有的日志写了但其实根本没人在输出。日志不是没有,是“你没有好好管它”。这篇文章,我们来聊聊怎么让日志真正成为你的帮手而非摆设。
一、从“写好日志”说起
在谈日志采集系统之前,先说一个更基础的问题:你的日志值得被采集吗?
我见过太多的日志是这样的:
// 毫无意义的日志
logger.info("处理完成");
logger.error("出错啦: " + e.getMessage());
这段日志有什么问题?第一,“处理完成”——处理了什么?什么参数?耗时多少?什么都看不出来。第二,只打印了异常信息没有打印堆栈,出问题后你根本不知道是哪一行报的错。
好的日志应该是一篇“微型事故报告”。 它至少应该包含:
- 时间:什么时候发生的
- 上下文:什么请求、什么用户、什么参数
- 结果:成功还是失败?耗时多少?
- 关联 ID:能不能沿着这个 ID 找到相关日志?
一个更好的版本:
String traceId = MDC.get("traceId");
logger.info("订单处理完成 [orderId={}, userId={}, amount={}, duration={}ms]",
orderId, userId, amount, duration);
有了这样的日志,出问题时你就不用靠“猜”来定位了——日志本身就告诉了你关键信息。
第一条原则:日志采集的前提,是你先写好了值得采集的日志。
二、日志采集的演进:从“人找日志”到“日志等人”
日志管理方式的演进,基本就是软件行业成长的一个缩影。
阶段一:手动看日志(石器时代)
ssh server-01
tail -f /var/log/app.log
grep "ERROR" /var/log/app.log | less
几台服务器还好,几十台呢?几百台呢?而且日志文件会滚动、会覆盖,三天前的日志可能已经没了。
阶段二:集中存储(入门级)
把一个 NFS 或者共享存储挂到所有服务器上,日志都写到一个地方。优点是日志集中了,但查询效率极低。你要在几百 GB 的日志文件里找一条错误信息,grep 一次可能要几分钟。
阶段三:结构化采集与搜索(现代方案)
这就是 ELK(Elasticsearch + Logstash + Kibana)和 Loki 这类方案要解决的问题:日志自动采集、结构化存储、快速搜索。日志不再是“文件”,变成了可查询的数据库。
三、两大主流方案:ELK vs Loki
3.1 ELK Stack
ELK 是日志领域的老牌方案,三件套各司其职:
- Elasticsearch:负责存储和全文搜索。日志来了建立倒排索引,查询速度极快。
- Logstash:负责日志的收集、过滤和转换。可以把原始的文本日志解析成结构化的 JSON。
- Kibana:负责可视化。提供了丰富的 Dashboard 和搜索界面。
实际部署中常常还加一个 Filebeat——它是轻量级的日志采集 agent,部署在每台应用服务器上,负责“把日志送到 Logstash”。它比 Logstash 轻得多,不占什么资源。
应用服务器 → Filebeat → Logstash → Elasticsearch → Kibana(查询展示)
ELK 的优势是成熟、生态丰富、搜索能力极强。但你得接受它比较“重”——Elasticsearch 吃内存是出了名的,小团队可能有点吃不消。
3.2 Loki + Grafana
Loki 是 Grafana 实验室推出的轻量级日志方案。它的设计哲学和 ELK 完全相反:
Loki 不对日志内容建全文索引,而是对日志的标签(labels)建索引。 也就是说,搜索的时候不是“在所有日志文本中搜某个关键词”,而是先通过标签筛选出相关日志,再在这些日志里用类似 grep 的方式搜索。
这种设计带来的结果是:Loki 非常省资源,可以轻松跑在中小规格的服务器上。但代价是全文搜索不如 ES 那么快。
3.3 怎么选?
| 维度 | ELK | Loki |
|---|---|---|
| 资源占用 | 高(ES 吃内存) | 低 |
| 搜索能力 | 极强(全文索引) | 较强(标签索引 + 文本扫描) |
| 与 Grafana 整合 | 需要配置 | 原生整合 |
| 上手难度 | 中高 | 较低 |
| 适用场景 | 日志量巨大,对搜索要求高 | 中小规模,已在用 Prometheus+Grafana |
如果你们团队已经在用 Prometheus + Grafana 做指标监控,那 Loki 是天然的日志补充——同一个 Grafana 页面,上面看指标,下面看日志,关联起来排查问题特别爽。
如果你们是一个大型系统,日志量巨大,每天 TB 级别,且经常要在日志中做复杂的全文搜索——那 ELK 是更合适的选择。
四、实践要点:上线前要确定的几件事
不管你选 ELK 还是 Loki,上线前有几件事必须想清楚:
4.1 日志结构要统一
日志要 JSON 格式,字段名要规范。所有服务的日志用同一套字段规范:
{
"timestamp": "2026-01-31T10:00:00Z",
"level": "INFO",
"service": "order-service",
"traceId": "abc123",
"message": "订单处理完成",
"orderId": "ORD-001",
"durationMs": 45
}
不要这个服务用 userId,那个服务用 user_id,第三个服务用 uid。统一命名规范,查询时才不会“漏掉”日志。
4.2 日志级别要合理
不要把所有东西都打成 INFO 级别。一个简单的级别分工:
- ERROR:需要立即关注的问题(支付失败、数据库挂了)
- WARN:不太正常但暂时不影响业务(重试成功、配额接近上限)
- INFO:关键业务事件(下单成功、用户注册)
- DEBUG:调试信息,生产环境默认关闭
级别混乱的后果是:查生产日志时,关键信息被海量 DEBUG 日志淹没了。
4.3 日志保留策略
日志不能无限存下去——磁盘是有成本的。一般做法:
- 热数据(最近 3-7 天):保留在快速存储上,方便高频查询
- 温数据(7-30 天):移到低成本存储
- 冷数据(30 天以上):归档或删除
这个策略取决于业务需求。金融类可能要求保留几年日志,一般互联网业务一到三个月就够用。
小结
日志采集不是一个“装个工具就完了”的事。它需要三个层面的配合:你写好日志、采集系统把日志集中起来、团队养成查日志的习惯。少了任何一环,日志系统就是一个摆设。
下一篇,我们来聊指标监控——如果说日志告诉你“为什么出问题”,那指标告诉你的就是“出没出问题”。
每天前进一小步,就是一个新的高度!