4. CloudWatch Logs深度使用

CloudWatch Logs 是 AWS 上最常用的日志汇聚与检索服务,但很多团队只把它当作“看日志的地方”,忽略了它真正的数据模型与处理链路。要把它用好,先要理解四个核心对象:日志组(Log Group)、日志流(Log Stream)、订阅过滤器(Subscription Filter)和指标过滤器(Metric Filter)。它们共同构成一条从“日志产生”到“检索、告警、外送”的完整链路。

一、日志组与日志流:数据模型与保留策略

日志组是日志的顶层容器,通常按“应用 + 环境”划分,例如 /aws/lambda/order-service-prod、/app/payment/prod。日志组上最重要的两个属性是保留策略(Retention)和加密。保留策略默认是“永不过期”,这在生产环境会持续累积成本,建议按合规要求设置为 7、30、90 或 365 天。日志流是日志组内的子容器,一般对应一个具体的实例、容器或执行环境,例如 Lambda 的每次执行环境、EC2 上的某个进程实例。日志流名称常包含实例 ID 或时间戳,便于定位来源。

一个常见的排障误区是:只按日志组搜索,忽略了日志流的时间边界。日志流一旦关闭(例如容器重启),新日志会写入新的日志流。因此排查“某次请求失败”时,应先用时间范围过滤,再在多个日志流中交叉检索。

二、订阅过滤器:把日志实时外送

订阅过滤器解决的是“日志不只留在 CloudWatch”的问题。它可以把匹配到的日志以实时流方式推送到 Kinesis Data Streams、Kinesis Data Firehose 或 Lambda。典型用途包括:把日志送到 OpenSearch 做全文检索、送到 S3 做长期归档、或送到第三方 SIEM 做安全分析。

订阅过滤器使用过滤模式(Filter Pattern)决定哪些日志被外送。例如只外送 ERROR 级别日志:

{ $.level = "ERROR" }

需要注意:一个日志组最多只能有两个订阅过滤器,且每个过滤器只能有一个目标。如果同时需要归档和告警,通常用 Firehose 分发到多个目的地,而不是叠加多个订阅过滤器。

三、指标过滤器:从日志中提取数值并告警

指标过滤器把日志中的文本或 JSON 字段转换成 CloudWatch 指标,从而可以配置告警。它的核心是“过滤模式 + 指标值”。例如从 JSON 日志中提取响应时间:

{ $.latency = * }
  指标名称:Latency
  指标值:$.latency
  单位:Milliseconds

再比如统计 ERROR 出现次数,用过滤模式 { $.level = "ERROR" },指标值设为 1,即可得到“错误计数”指标。指标过滤器支持默认值和维度,维度可以从日志字段中提取,例如按 $.service 分组,这样就能对每个服务单独告警。

一个实用技巧:指标过滤器只对新写入的日志生效,不会回溯历史日志。因此上线新的指标过滤器后,需要等待一段时间才能看到数据。

四、Logs Insights 查询语法

Logs Insights 是 CloudWatch 的交互式查询引擎,语法接近 SQL 但更偏向日志场景。基本结构是:

fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 20

常用命令包括:fields 选择字段、filter 过滤、stats 聚合、sort 排序、limit 限制条数、parse 解析非结构化文本。例如统计每个接口的 P99 延迟:

fields @timestamp, endpoint, latency
| filter ispresent(latency)
| stats pct(latency, 99) as p99 by endpoint
| sort p99 desc

对于 JSON 日志,可以直接用 $.field 引用字段;对于纯文本日志,用 parse 提取,例如:

parse @message "status=* duration=*" as status, duration
| filter status >= 500
| stats count() by bin(5m)

查询时要注意时间范围和扫描量。Logs Insights 按扫描的数据量计费,范围越大、日志越多,成本越高。生产排障时建议先用窄时间窗口定位,再逐步扩大。

五、生产排障案例:一次订单超时排查

假设订单服务在 14:00 左右出现大量超时告警。排查步骤如下:

  1. 打开日志组 /app/order/prod,时间范围设为 13:55–14:10。
  2. 用 Logs Insights 查询超时请求:fields @timestamp, orderId, latency | filter latency > 3000 | sort @timestamp asc。
  3. 发现超时集中在某个下游依赖,进一步用 stats count() by bin(1m) 看趋势。
  4. 检查该依赖的日志组,确认是否有连接池耗尽或限流错误。
  5. 如果已配置指标过滤器,可直接查看 Latency 指标的突增点,与告警时间对齐。

这个案例的关键在于:日志组定位范围、日志流确认实例、Logs Insights 聚合趋势、指标过滤器验证告警,四者配合才能快速收敛问题。

CloudWatch Logs 数据处理链路 日志源 Lambda / EC2 / ECS 日志组 Log Group /app/order/prod 日志流 Log Stream 实例 / 容器实例 订阅过滤器 Subscription Filter 指标过滤器 Metric Filter Kinesis / Firehose 实时外送 Lambda 自定义处理 CloudWatch 告警 Alarm / SNS Logs Insights 查询: fields @timestamp, orderId, latency | filter latency > 3000 | stats count() by bin(1m) 日志存储 订阅外送 指标与告警
实用建议:为每个生产日志组设置合理的保留策略;对关键业务日志配置指标过滤器并绑定告警;订阅过滤器用于外送,不要用它做告警;Logs Insights 查询时先窄后宽,控制扫描成本。
注意:指标过滤器和订阅过滤器都只对新写入的日志生效,不会处理历史日志。上线前请确认时间窗口和测试日志已就绪。