3. 数据源配置:Prometheus、Loki、Elasticsearch 数据源接入与查询语言基础

在构建可观测性体系时,数据源是告警与面板的根基。本章聚焦三大核心数据源——Prometheus(指标)、Loki(日志)、Elasticsearch(搜索与分析)的接入配置,并深入对应的查询语言 PromQL 与 LogQL,为后续质量门禁与阈值优化打下数据基础。

3.1 数据源接入对比与配置要点

三种数据源在 Grafana 中的接入方式、数据模型与适用场景存在显著差异。下表梳理了核心配置参数与最佳实践:

数据源 默认端口 认证方式 核心配置项 数据模型 典型场景
Prometheus 9090 Basic Auth / Bearer URL、Scrape Interval、Timeout 时间序列(Metric + Label) CPU、内存、请求速率、错误率
Loki 3100 Basic Auth / Multi-tenant URL、Max Lines、Derived Fields 日志流(Stream + Label) 应用错误日志、审计日志、事件追踪
Elasticsearch 9200 Basic Auth / URL、Index、Time Field、Version 文档(JSON 结构化数据) 业务指标、全文搜索、聚合分析
配置建议:生产环境中,建议为每个数据源单独配置 Datasource UID,并在面板变量中引用 UID 而非名称,避免数据源重命名导致面板失效。同时,为 Prometheus 和 Loki 开启 HTTP Keep-Alive,减少连接建立开销。

3.2 Prometheus 数据源与 PromQL 基础

Prometheus 是时序指标的事实标准。接入时需确保 Grafana 与 Prometheus 网络可达,并正确配置 Scrape Interval(通常 15s-30s)与 Timeout(通常 10s)。

3.2.1 PromQL 核心概念

  • Instant Vector:某一时刻的时序数据集合,如 http_requests_total{job="api"}
  • Range Vector:一段时间窗口内的时序数据,如 http_requests_total[5m]
  • Scalar:纯数值,如 1、100
  • String:字符串,用于标签匹配

3.2.2 常用 PromQL 查询模式

# 瞬时向量查询:获取当前所有 API 服务的请求总数
http_requests_total{job="api"}

# 速率计算:过去 5 分钟每秒请求数
rate(http_requests_total[5m])

# 聚合查询:按状态码分组统计错误率
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))

# 阈值判断:返回超过 0.05 错误率的服务
(sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
 /
 sum(rate(http_requests_total[5m])) by (service)) > 0.05
常见陷阱:使用 rate() 时,必须确保时间窗口至少为 Scrape Interval 的 4 倍,否则结果可能不准确。例如 Scrape Interval 为 15s,则 [1m] 是安全下限。

3.3 Loki 数据源与 LogQL 基础

Loki 专为日志设计,与 Prometheus 共享标签体系。接入时需配置 Derived Fields,将日志中的 trace ID 或 request ID 提取为可点击链接,实现日志与链路追踪的联动。

3.3.1 LogQL 核心概念

  • Log Stream Selector:通过标签过滤日志流,如 {app="nginx", env="prod"}
  • Line Filter:对日志行内容进行过滤,如 |= "ERROR"、!= "DEBUG"
  • Parser:解析日志内容为结构化字段,如 | json、| logfmt、| regexp
  • Metric Query:将日志转换为指标,如 rate({app="nginx"} |= "5xx" [5m])

3.3.2 常用 LogQL 查询模式

# 基础日志流查询:获取生产环境 Nginx 的错误日志
{app="nginx", env="prod"} |= "ERROR"

# 解析 JSON 日志并过滤特定字段
{app="api"} | json | status >= 500

# 日志速率指标:过去 5 分钟 5xx 错误日志的速率
rate({app="api"} |= "5xx" [5m])

# 聚合统计:按 service 分组统计错误日志数量
sum by (service) (count_over_time({app="api"} |= "ERROR" [5m]))
质量门禁应用:在告警规则中,使用 rate({app="api"} |= "5xx" [5m]) > 0.1 作为阈值,表示过去 5 分钟内每秒超过 0.1 条 5xx 日志时触发告警。相比固定数量阈值,速率阈值更能反映异常趋势。

3.4 Elasticsearch 数据源接入

Elasticsearch 适合存储结构化业务数据与全文搜索。接入时需指定 Index 名称(支持通配符如 nginx-*)和 Time Field(如 @timestamp)。

3.4.1 查询语言基础

Grafana 中的 Elasticsearch 数据源支持两种查询模式:

  • Lucene Query:简单文本搜索,如 status:500 AND method:POST
  • Elasticsearch Query DSL:JSON 格式的复杂查询,支持聚合、过滤、排序
# Lucene 查询示例:查找状态码为 500 且请求方法为 POST 的日志
status:500 AND method:POST

# Query DSL 示例:按 service 分组统计错误数
{
  "query": {
    "bool": {
      "filter": [
        {"range": {"@timestamp": {"gte": "now-5m"}}},
        {"term": {"status": 500}}
      ]
    }
  },
  "aggs": {
    "by_service": {
      "terms": {"field": "service.keyword", "size": 10}
    }
  }
}
性能优化:在 Elasticsearch 面板中,尽量使用 Terms Aggregation 而非 Filters Aggregation,前者在大量分桶时性能更优。同时,为常用字段设置 keyword 类型,避免 text 类型导致的聚合性能问题。

3.5 数据源查询语言对比与选择

维度 PromQL LogQL Elasticsearch Query
数据对象 时序指标 日志流 文档
过滤方式 标签匹配 标签 + 行内容 全文搜索 + 结构化字段
聚合能力 强(rate、avg、quantile) 中(rate、count_over_time) 强(Terms、Date Histogram)
告警适用性 最佳(趋势、速率、分位数) 良好(异常日志速率) 一般(适合静态阈值)
学习曲线 中等 低(与 PromQL 相似) 高(DSL 复杂)

3.6 数据源与查询语言在质量门禁中的角色

下图展示了三种数据源如何协同支撑质量门禁的阈值优化流程:

数据源与查询语言在质量门禁中的角色 Prometheus PromQL 指标查询 Loki LogQL 日志查询 Elasticsearch DSL / Lucene 查询 查询语言层:PromQL / LogQL / DSL 速率计算、聚合、过滤、解析 Grafana 面板:时序图 / 日志面板 / 统计表 质量门禁:基于查询结果的阈值优化与告警触发
关键洞察:在质量门禁中,PromQL 的 rate() 和 histogram_quantile() 用于动态阈值计算;LogQL 的 rate() 用于异常日志速率告警;Elasticsearch 的聚合查询用于业务指标基线分析。三者结合,可实现从指标到日志的全链路阈值优化。

3.7 数据源配置最佳实践清单

  1. 统一标签命名规范:Prometheus 与 Loki 共享标签体系,建议使用 service、env、region 等通用标签,便于跨数据源关联。
  2. 配置 Derived Fields:在 Loki 数据源中,将 trace ID 提取为派生字段,实现日志与 Tempo 或 Jaeger 的链路跳转。
  3. 启用缓存:为 Elasticsearch 数据源开启查询缓存,减少重复查询对 ES 集群的压力。
  4. 设置最大行数:Loki 数据源中设置 Max Lines 为 1000-5000,避免返回过多日志导致面板渲染缓慢。
  5. 使用变量:在面板中使用 $datasource 变量引用数据源 UID,便于在不同环境间迁移。
安全提醒:避免在 Grafana 数据源配置中直接使用明文密码。建议使用 Grafana 加密 API 或 环境变量 注入敏感信息,如 ${PROM_PASSWORD}。