4. LogQL指标化:从日志中提取指标

日志检索的核心价值在于从非结构化文本中提取可量化的指标。本章将深入讲解如何通过LogQL将日志流转换为时间序列指标,实现从“看日志”到“算指标”的跨越。

4.1 核心概念:日志量到时间序列的转换

日志数据本质上是事件流,而指标是时间序列。LogQL的指标化过程就是将离散的日志事件按时间窗口聚合,生成连续的、可计算的数值序列。

关键转换逻辑: 日志行 → 时间窗口分组 → 聚合计算 → 时间序列输出
概念 日志数据 指标数据
数据形态 非结构化/半结构化文本 数值 + 标签
时间粒度 事件发生时刻(精确到纳秒) 聚合窗口(如1m、5m)
查询结果 日志行列表 时间序列点
典型操作 过滤、正则提取 rate、count_over_time、sum by
日志 → 时间序列转换流程 日志流 {job="api", env="prod"} 过滤 |= "error" 时间窗口 [5m] 聚合 count_over_time 输出:时间序列指标 {job="api"} 0.5 ops/s (rate) 转换要点 • 日志行 → 计数 • 时间窗口 → 速率 • 标签 → 维度

4.2 三大核心指标函数

4.2.1 count_over_time:日志计数指标

count_over_time 是最基础的指标化函数,用于统计指定时间窗口内的日志行数。它直接将日志量转换为计数指标。

# 统计每5分钟API服务的错误日志数量
count_over_time({job="api-server"} |= "error" [5m])

# 按环境分组统计
count_over_time({job="api-server"} |= "error" [5m]) by (env)
适用场景: 错误率监控、日志量突增检测、事件频率分析。当需要了解“某类日志出现了多少次”时,count_over_time 是最直接的选择。

4.2.2 rate:速率指标

rate 函数计算日志事件的每秒速率,是比 count_over_time 更平滑的指标形式。它自动处理时间窗口边界,适合告警和趋势分析。

# 计算每秒错误日志速率
rate({job="api-server"} |= "error" [5m])

# 按路径分组计算速率
rate({job="api-server"} |= "error" [5m]) by (path)
函数 输出单位 适用场景 告警友好度
count_over_time 计数(整数) 总量监控、突增检测 中等(受窗口大小影响)
rate 每秒速率(浮点数) 趋势分析、SLO计算 高(平滑稳定)

4.2.3 sum by:维度聚合

sum by 是 LogQL 中的降维聚合操作,用于将多个标签维度的指标合并计算。它通常与 count_over_time 或 rate 配合使用。

# 按 service 维度聚合错误速率
sum by (service) (
  rate({job="api-server"} |= "error" [5m])
)

# 多维度聚合:service + method
sum by (service, method) (
  rate({job="api-server"} |= "error" [5m])
)
注意: sum by 会丢弃未指定的标签。如果希望保留所有标签,使用 sum without 排除指定标签。错误使用 sum by 可能导致指标精度丢失。

4.3 实战:构建错误率指标

以下是一个完整的错误率指标构建流程,结合了过滤、速率计算和维度聚合。

# 步骤1:计算总请求速率
total_rate = rate({job="api-server"} [5m])

# 步骤2:计算错误请求速率
error_rate = rate({job="api-server"} |= "error" [5m])

# 步骤3:计算错误率(百分比)
error_rate / total_rate * 100

# 步骤4:按端点分组
sum by (endpoint) (
  rate({job="api-server"} |= "error" [5m])
) / sum by (endpoint) (
  rate({job="api-server"} [5m])
) * 100
错误率指标计算架构 原始日志流 200/404/500 混合 总请求计数 count_over_time 错误请求计数 |= "error" + count 总速率 rate [5m] 错误速率 rate [5m] 错误率 % error / total 关键公式 error_rate = sum by (endpoint) (rate({job="api"} |= "error" [5m])) / sum by (endpoint) (rate({job="api"} [5m])) * 100

4.4 常见陷阱与最佳实践

  • 窗口大小选择: 短窗口(1m)响应快但波动大,长窗口(15m)平滑但延迟高。建议告警用5m,报表用15m。
  • 标签爆炸: sum by 时避免使用高基数标签(如 user_id、request_id),会导致大量时间序列,影响性能。
  • 空结果处理: 当某时间窗口无匹配日志时,count_over_time 返回0,rate 返回0。注意告警规则中处理除零错误。
  • 性能优化: 先过滤再聚合,将 |= "error" 放在最前面,减少后续处理的数据量。
Golden Signals 映射: 本章的 rate + sum by 组合是构建“错误率”(Error Rate)和“请求速率”(Traffic)两个 Golden Signals 的核心方法。通过合理选择标签维度,可以同时监控服务级别和端点级别的健康状态。