1. 为什么“能打印日志”不等于“可观测”
最常见的误区是把日志当作调试副产物:每个模块随意输出一段文本。 这种日志在本地看似有用,一旦进入分布式环境就会失效——你无法按请求关联、无法按服务聚合、 无法精确过滤某类错误,最终只能“人肉翻全文”。可观测日志的目标是:在事故发生的分钟级窗口里, 让工程师快速回答三个问题:哪条链路失败、失败原因是什么、影响范围多大。
2. 结构化日志(Structured Logging):字段规范先于工具选型
工具可换,字段规范不能乱。建议至少固定这些字段:`timestamp`、`level`、`service`、`env`、 `trace_id`、`span_id`、`event_name`、`error_code`、`message`、`request_id`。 这样你的日志才能跨服务聚合、跨平台搜索,并与 tracing/metrics 建立联动。
| Field | Purpose | Example |
|---|---|---|
| trace_id | 关联同一请求链路 | c3b6f...e9 |
| event_name | 语义化事件分类 | checkout.payment.failed |
| error_code | 稳定错误枚举,便于聚合 | PAYMENT_TIMEOUT |
{
"timestamp": "2026-03-18T12:34:56.789Z",
"level": "ERROR",
"service": "payments-api",
"env": "prod",
"trace_id": "6f7259c2f4f9414bbf1d5e5b6f2e85c1",
"span_id": "0f4e9d8f4b50a2ce",
"request_id": "req-4dca",
"event_name": "checkout.payment.failed",
"error_code": "PAYMENT_TIMEOUT",
"message": "provider timeout after 3000ms"
}
3. 采集与索引:如何在“可查”与“可负担”之间平衡
日志成本通常由三个量级决定:吞吐、保留期、索引粒度。你需要按业务价值分层: `hot` 层用于近期排障(高索引、快查询),`cold` 层用于审计回溯(低成本、慢查询)。 同时要尽量把高基数字段(如 user_id)从默认索引里移出,以避免爆炸性成本增长。
4. 与发布治理联动:让日志成为回滚与审计证据
日志体系要服务发布治理。建议给每次发布打 `release_id`、`commit_sha`、`pipeline_run_id`, 并在回滚时也写对应事件。这样你在事故复盘时可以直接回答: “哪次发布后出现异常、异常发生在什么服务、回滚是否恢复、恢复耗时多久”。
{
"timestamp": "2026-03-18T13:00:00.000Z",
"level": "INFO",
"service": "deploy-controller",
"event_name": "release.promoted",
"release_id": "rel-20260318-42",
"commit_sha": "9f3baf2",
"pipeline_run_id": "gha-18283910",
"env": "prod",
"message": "promoted canary to 100%"
}
5. 安全与隐私:日志不是“可无限复制的明文仓库”
日志里最容易泄露的数据包括 token、手机号、邮箱、身份证号、银行卡号以及内部密钥片段。 你的日志管道必须在入口处做脱敏/掩码(redaction/masking),并限制谁能查什么。 同时要给审计查询留痕:谁在何时查询了哪些索引、导出过哪些数据。
6. 本章清单
- 统一结构化日志字段规范,并固定命名风格(snake_case 或 camelCase 选一种)。
- 打通日志流水线:采集、解析、增强、过滤、分层存储与查询。
- 为发布与回滚增加 release markers(release_id、commit_sha、pipeline_run_id)。
- 建立热温冷保留策略,控制索引字段和高基数成本。
- 对敏感字段做入口脱敏,并给日志查询加 RBAC 与审计。
- 预告下一章:指标(Metrics)与 SLO/SLI,解决“问题规模和优先级”判定。