3. 日志黄金指标定义:基于日志的延迟、错误率、流量(QPS)、饱和度(资源使用率)的提取方法与指标化

在可观测性工程中,日志是记录系统行为最原始的载体。但原始日志是“数据”,只有经过结构化提取与指标化,才能转化为可告警、可分析的“黄金指标”。本章聚焦于如何从日志文本中提取延迟、错误率、流量(QPS)和饱和度(资源使用率),并建立标准化的指标管道。

3.1 黄金指标四象限:从日志到指标的映射

Google SRE 定义的四大黄金指标(延迟、错误率、流量、饱和度)在日志领域有明确的对应字段。下表展示了每个黄金指标在日志中的典型来源与提取目标:

黄金指标 日志字段来源 指标化输出 典型聚合方式
延迟 (Latency) 请求耗时、响应时间、处理时长 p50/p90/p99 延迟、平均延迟 Histogram / Summary
错误率 (Error Rate) HTTP 状态码、异常堆栈、错误码 错误请求数 / 总请求数 Counter / Ratio
流量 (Traffic / QPS) 请求日志条目、访问记录 每秒请求数、每分钟事务数 Counter / Rate
饱和度 (Saturation) 连接池耗尽、队列深度、资源超限 当前使用量 / 最大容量 Gauge / Ratio
实战要点:并非所有日志都包含全部四个指标。例如,访问日志天然适合提取延迟和流量,而错误日志更适合提取错误率和饱和度。建议按日志类型(访问日志、错误日志、审计日志)分别建立指标提取规则。

3.2 延迟指标提取:从耗时字段到百分位指标

延迟是衡量系统响应速度的核心指标。在日志中,延迟通常以毫秒或微秒为单位记录在特定字段中。提取流程分为三步:

  1. 字段定位:在日志解析阶段,将耗时字段(如 response_time、duration_ms、latency)提取为数值类型。
  2. 指标化:将每个请求的延迟值记录到 Prometheus Histogram 或类似结构中,自动计算分位数。
  3. 告警阈值:通常关注 p99 延迟,例如“p99 延迟超过 500ms 持续 5 分钟”。
# 示例:使用 Fluentd 提取 Nginx 访问日志中的延迟字段
<source>
  @type tail
  path /var/log/nginx/access.log
  format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>\d+) (?<size>\d+) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<request_time>[0-9\.]+)$/
  <parse>
    @type regexp
    expression /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>\d+) (?<size>\d+) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<request_time>[0-9\.]+)$/
    types request_time:float
  </parse>
</source>

3.3 错误率指标提取:状态码与异常分类

错误率是系统健康度的直接体现。日志中的错误通常分为两类:

  • 显式错误:HTTP 5xx 状态码、业务错误码(如 ERROR 级别日志)。
  • 隐式错误:超时、连接重置、空响应等非标准错误。

提取错误率时,需要定义“错误”的边界。建议采用以下规则:

日志类型 错误判定条件 指标名称
HTTP 访问日志 status >= 500 http_requests_errors_total
应用日志 level == "ERROR" 或 "FATAL" app_log_errors_total
数据库慢查询日志 query_time > 1.0 db_slow_queries_total
告警降噪提示:不要对所有错误一视同仁。建议将错误分为“致命错误”(如数据库连接失败)和“业务错误”(如用户输入校验失败)。致命错误应触发高优先级告警,业务错误可聚合后降级为低优先级。

3.4 流量指标提取:QPS 与吞吐量

流量指标反映系统负载水平。在日志中,每一条请求日志代表一次流量事件。提取 QPS 的核心是:

  1. 计数:对日志条目按时间窗口(如 1 分钟)进行计数。
  2. 速率计算:将计数转换为每秒速率(QPS = 计数 / 时间窗口秒数)。
  3. 维度拆分:按接口、客户端、区域等维度拆分流量,便于定位热点。
# PromQL 示例:计算每分钟平均 QPS
rate(http_requests_total[1m])

# 按路径拆分 QPS
sum by (path) (rate(http_requests_total[1m]))

3.5 饱和度指标提取:资源使用率与队列深度

饱和度是系统容量压力的早期信号。日志中提取饱和度通常依赖以下模式:

  • 连接池日志:记录当前活跃连接数 / 最大连接数。
  • 队列日志:记录当前队列深度 / 最大队列长度。
  • 限流日志:记录被限流的请求数。

饱和度指标通常以 Gauge 形式存储,计算公式为:saturation_ratio = current_value / max_capacity。当饱和度超过 80% 时应触发预警,超过 95% 时应触发紧急告警。

案例:某微服务在日志中输出 pool.active=45 pool.max=50。通过正则提取 active 和 max 字段,计算饱和度 = 45/50 = 90%,触发告警。后续排查发现数据库连接泄漏,修复后饱和度降至 30%。

3.6 指标化管道架构:从日志到告警的完整链路

将日志黄金指标从提取到告警的完整流程可视化如下:

日志黄金指标提取与指标化管道 原始日志 日志采集 字段提取 指标化 告警 说明: 原始日志 → 采集(Fluentd/Logstash)→ 字段提取(正则/JSON 解析)→ 指标化(Prometheus Histogram/Gauge)→ 告警引擎 每个环节都需定义字段映射规则,确保延迟、错误率、QPS、饱和度被正确提取。

3.7 指标化最佳实践与常见陷阱

实践 说明 陷阱
字段类型强制转换 将字符串类型的耗时字段显式转换为 float/int 忽略转换导致指标聚合失败
错误分类标签 为错误指标添加 error_type 标签(如 timeout、rejected) 标签基数爆炸,影响存储性能
QPS 按维度聚合 至少按接口、状态码、客户端 IP 三个维度聚合 仅聚合全局 QPS,无法定位热点
饱和度基线校准 根据历史数据设定饱和度告警基线 使用固定阈值导致误报或漏报
降噪技巧:在指标化阶段,为每个黄金指标添加 env、service、region 等公共标签。这有助于在告警阶段快速聚合和过滤,避免重复告警。

3.8 本章小结

日志黄金指标的提取与指标化是告警降噪的基础。核心要点包括:

  • 延迟指标需关注百分位(p99),而非平均值。
  • 错误率需区分致命错误与业务错误,避免告警风暴。
  • 流量指标需按维度拆分,支持热点定位。
  • 饱和度指标需结合容量规划,设定动态基线。
  • 指标化管道需保证字段类型正确、标签可控、存储高效。