3. 黄金指标概念
RED 方法(Rate、Errors、Duration)是 Tom Wilkie 在 2015 年提出的面向服务的监控模型,最初用于 Prometheus 微服务监控。在日志领域,RED 方法将三个核心信号从指标空间映射到日志事件空间,使 SRE 能够通过日志直接判断服务的健康状态,而无需依赖指标系统。
3.1 RED 三要素的日志语义
| RED 要素 | 指标定义 | 日志映射 | Loki 查询示例 |
|---|---|---|---|
| Rate(速率) | 每秒请求数(RPS) | 日志行中标识请求开始或结束的事件计数 | sum(rate({job="api"} |= "REQUEST_START"[1m])) |
| Errors(错误) | 失败请求占比或值 | 日志行中 status >= 500 或包含 "ERROR" 级别的事件 | sum(rate({job="api"} |= "status=5" [1m])) |
| Duration(持续时间) | 请求处理耗时(P50/P99) | 日志行中记录的响应时间字段,通过 LogQL 提取并计算分位数 | quantile_over_time(0.99, {job="api"} | json | unwrap duration [5m]) |
关键认知: RED 方法在日志领域的核心价值在于——当指标系统不可用或数据粒度不足时,日志可以作为黄金指标的"备用数据源"。但日志的 RED 查询成本远高于指标,因此应优先使用指标系统承载 RED 监控,日志 RED 仅用于故障排查和根因分析。
3.2 RED 日志黄金指标架构
下图展示了 RED 方法在日志系统中的完整映射链路,从服务请求产生日志,到 Loki 摄取、查询,最终形成三个黄金信号的可视化面板。
3.3 Rate(速率)的日志实现
Rate 在日志中对应的是请求事件的发生频率。与指标系统直接计数不同,日志需要先通过 LogQL 过滤出代表请求开始或结束的事件行,再计算速率。
最佳实践: 在日志中嵌入明确的请求标记(如
REQUEST_START 或 REQUEST_END),避免使用模糊的文本匹配。标记越精确,Rate 查询的准确度越高。
# 计算每分钟请求速率(基于 REQUEST_START 标记)
sum by (service, endpoint) (
rate({app="order-service"} |= "REQUEST_START" [1m])
)
# 计算每分钟请求速率(基于状态码存在性)
sum by (service) (
rate({app="api-gateway"} |~ "status=\d{3}" [1m])
)
3.4 Errors(错误)的日志实现
Errors 在日志中对应的是错误级别事件或错误状态码的出现频率。日志的错误检测比指标更灵活,可以基于日志级别、状态码范围或错误关键字进行多维过滤。
| 错误检测方式 | 适用场景 | LogQL 示例 |
|---|---|---|
| 日志级别过滤 | 结构化日志,明确 ERROR 级别 | {app="payment"} |= "level=ERROR" |
| 状态码范围 | HTTP 服务,status >= 500 | {app="api"} |~ "status=5[0-9]{2}" |
| 异常关键字 | 非结构化日志,包含 exception/error | {app="worker"} |= "Exception" |
| 业务错误码 | 自定义业务错误码(如 err_code=4001) | {app="order"} |= "err_code=" |
# 计算错误率(错误请求 / 总请求)
sum by (service) (
rate({app="api"} |= "status=5" [1m])
) / sum by (service) (
rate({app="api"} |~ "status=\d{3}" [1m])
) * 100
注意: 日志中的错误计数可能包含重复记录(如重试日志、堆栈跟踪多行)。建议在应用层对错误日志进行去重标记,或在 LogQL 中使用
| pattern 提取唯一错误 ID 进行去重。
3.5 Duration(持续时间)的日志实现
Duration 在日志中对应的是请求处理时间的数值提取与分位数计算。这是 RED 三要素中日志实现最复杂的一环,需要日志中包含结构化的耗时字段,并通过 unwrap 操作提取数值。
# 提取 duration 字段并计算 P99 延迟
quantile_over_time(0.99,
{app="order-service"} |= "REQUEST_END"
| json
| unwrap duration [5m]
)
# 按 endpoint 分组计算 P50 延迟
quantile_over_time(0.50,
{app="api-gateway"} |= "REQUEST_END"
| json
| unwrap duration [5m]
) by (endpoint)
3.6 RED 日志标签治理原则
为了高效支持 RED 查询,日志标签(Label)的设计必须遵循以下原则:
- Rate 标签: 至少包含
service、endpoint、method,用于按服务维度聚合速率。 - Errors 标签: 至少包含
status_code、error_type,用于按错误类型分类。 - Duration 标签: 至少包含
duration字段(作为日志行内的结构化字段,而非标签),避免高基数标签爆炸。 - 公共标签:
app、env、host、trace_id作为所有日志的基座标签。
3.7 RED 日志查询性能对比
| RED 要素 | 查询复杂度 | 典型延迟 | 优化建议 |
|---|---|---|---|
| Rate | 低(仅过滤 + rate) | < 1s | 使用精确标记,避免正则 |
| Errors | 中(过滤 + 聚合) | 1-3s | 预聚合错误标签,减少扫描量 |
| Duration | 高(unwrap + 分位数) | 3-10s | 限制时间范围,使用 quantile_over_time 时避免过大窗口 |
实战建议: 在 Loki 中为 Duration 查询创建专用的记录规则(Recording Rules),每 5 分钟预计算 P50/P99 延迟并存储为指标,避免每次查询都扫描全量日志。这是 RED 日志监控从"可用"走向"高效"的关键一步。