第一原则:日志要结构化
旧:[INFO] 2026-05-09 10:23:45 user 1234 logged in from 1.2.3.4
新:{"ts":"2026-05-09T10:23:45Z","level":"info","event":"login","user_id":1234,"ip":"1.2.3.4"}
非结构化日志靠 grep;结构化日志能按字段过滤、聚合、关联——性能和能力差几个数量级。
每种语言都有结构化日志库:Python structlog / Node pino / Go slog(标准库自 1.21)/ Java Logback + JsonEncoder。
三类方案
方案 A:ELK / OpenSearch 栈
应用 → Filebeat / Fluent Bit → Logstash → Elasticsearch → Kibana
- Elasticsearch:全文索引数据库,给每个字段建倒排索引
- Logstash:数据加工(过滤 / 转换 / 富化)
- Kibana:可视化 + 查询
- Filebeat / Fluent Bit / Fluentd:采集 agent
2021 年 Elastic 改 License,AWS 分叉出 OpenSearch——开源版的 ES。两者 API 大体兼容,新项目优先 OpenSearch(License 干净)。
特点:
- 全文搜索能力最强
- 灵活的字段查询和聚合
- 重——Elasticsearch 吃 CPU + 内存 + 磁盘
- 索引爆炸:高基数字段进索引会把磁盘吃满
方案 B:Grafana Loki
应用 → Promtail / Fluent Bit → Loki → Grafana
Loki 由 Grafana Labs 出品,借鉴 Prometheus 思路:
- 只对标签做索引(service、env、host 等少量低基数维度)
- 日志正文不索引,按时间排序压缩存对象存储
- 查询:先按标签筛到候选块,再在块内 grep
特点:
- 存储便宜——可以扔到 S3 / R2 / OSS
- 与 Prometheus / Grafana 体验一致(PromQL 风格的 LogQL)
- 全文搜索能力弱于 ES——大量正文 grep 慢
- 适合"标签筛选 + 少量正文 grep"的场景;不适合 SOC 那种全文复杂查询
方案 C:云原生托管
| 厂商 | 服务 | 计费模型常见做法 |
|---|---|---|
| AWS | CloudWatch Logs | 按写入量 + 存储量 |
| GCP | Cloud Logging | 同上 |
| Azure | Log Analytics | 同上 |
| 阿里云 | SLS(日志服务) | 同上 |
| 腾讯云 | CLS | 同上 |
特点:
- 零运维,按量付费
- 与同云的指标 / 告警 / 安全产品深度集成
- 写入量大时账单可观——产品成熟后量起来要看明细
- 跨云搬家麻烦
选型决策
| 情况 | 推荐 |
|---|---|
| 已重度用 K8s + Grafana | Loki |
| 安全 / 审计 / SOC + 复杂全文查询 | OpenSearch |
| 全栈在某家云上 + 不想运维 | 该云的托管日志 |
| 多云 + 预算紧 | Loki(对象存储便宜) |
| 老 ELK 资产 | 继续 ES,逐步迁 OpenSearch |
没有"全场景最优"。评估一周日志量 + 查询模式比看博客有用。
实操建议
1. 在源头丢
不是所有日志都值得收:
- 健康检查日志(每秒打一次)→ 默认丢
- INFO 级别的"业务正常"日志 → 视情况保留 / 不保留
- DEBUG 级别 → 默认不收,问题时再开
2. 不要把 secret 写进日志
代码里加 redactor:自动去掉 password / token / 信用卡号字段。
3. 加 trace_id 关联
每个请求一个 trace_id(OTel 自动生成),打日志时带上——从 traces 跳到 logs,从 logs 跳回 traces。
4. 容量规划
存储 = 写入速率 × 保留天数 × 压缩比。新项目按估算 × 3 准备空间,业务起来观察实际再调。
推荐阅读
- Grafana Loki 文档 / Promtail
- OpenSearch 文档 / ELK Best Practices
- Fluent Bit — 轻量日志 forwarder(CNCF Graduated)
- The Twelve-Factor App: Logs — 日志作为事件流的设计原则
下一篇:把三支柱统一起来——OpenTelemetry。