3、LogQL入门:日志查询语法、标签匹配、管道操作、度量查询
LogQL 是 Loki 的专属查询语言,受 PromQL 和 SQL 启发,专为日志数据设计。理解 LogQL 是构建 SLI 口径和进行故障排查的基础。本章将系统讲解 LogQL 的核心概念:日志流选择器、行过滤器、管道操作以及度量查询。
3.1 核心概念:日志流与标签
在 LogQL 中,查询的第一步是选择日志流。日志流由一组标签(Labels)唯一标识,这些标签通常来自日志采集器(如 Promtail)或 Loki 的配置。标签是键值对,例如 job="api-server"、env="production"、service="payment"。
3.2 日志流选择器
日志流选择器用于指定要查询的日志流集合。它使用花括号 {} 包裹标签匹配表达式。
| 匹配操作符 | 含义 | 示例 |
|---|---|---|
= |
精确匹配 | {job="api-server"} |
!= |
不等于 | {job!="cron-job"} |
=~ |
正则匹配 | {job=~"api-.*"} |
!~ |
正则排除 | {job!~"debug-.*"} |
组合示例:
{env="production", service=~"auth|payment", job!="batch"}
该查询选择所有 env="production" 且 service 以 "auth" 或 "payment" 开头,且 job 不是 "batch" 的日志流。
3.3 行过滤器
在选定日志流后,可以使用行过滤器对日志行内容进行文本搜索。行过滤器使用管道符 | 连接。
| 过滤器 | 语法 | 说明 |
|---|---|---|
| 包含 | |= "error" |
日志行包含 "error" |
| 不包含 | != "debug" |
日志行不包含 "debug" |
| 正则包含 | |~ "5[0-9]{2}" |
日志行匹配正则(如 5xx 状态码) |
| 正则排除 | !~ "health" |
日志行不匹配正则 |
完整查询示例:
{env="production", service="api"} |= "error" |~ "5[0-9]{2}"
该查询从生产环境的 api 服务中,筛选出包含 "error" 且匹配 5xx 状态码的日志行。
3.4 管道操作:解析与提取
管道操作允许对日志行进行解析、提取字段、格式化输出等。这是构建结构化日志查询的核心能力。
3.4.1 常用管道操作符
| 操作符 | 作用 | 示例 |
|---|---|---|
logfmt |
解析 logfmt 格式日志 | | logfmt |
json |
解析 JSON 格式日志 | | json |
regexp |
使用正则提取字段 | | regexp "(?P<status>\d{3})" |
pattern |
使用模式匹配提取 | | pattern "<ip> - - <method>" |
unpack |
解包已打包的日志 | | unpack |
line_format |
格式化输出行内容 | | line_format "{{.status}}" |
label_format |
格式化标签值 | | label_format new_status="{{.status}}" |
JSON 解析示例:
{job="api-server"} |= "error" | json | line_format "{{.message}} - {{.status}}"
该查询解析 JSON 日志,提取 message 和 status 字段,并重新格式化输出。
3.4.2 管道操作流程
3.5 度量查询:从日志到指标
LogQL 最强大的特性之一是将日志转换为度量指标。度量查询使用函数包装日志查询,返回时间序列数据,可直接用于 Grafana 面板或告警。
3.5.1 核心度量函数
| 函数 | 作用 | 返回类型 |
|---|---|---|
rate |
计算日志行速率(每秒) | Gauge |
count_over_time |
计算时间窗口内的日志行数 | Gauge |
sum_over_time |
计算时间窗口内数值字段的总和 | Gauge |
avg_over_time |
计算时间窗口内数值字段的平均值 | Gauge |
max_over_time |
计算时间窗口内数值字段的最大值 | Gauge |
min_over_time |
计算时间窗口内数值字段的最小值 | Gauge |
stdvar_over_time |
计算时间窗口内数值字段的方差 | Gauge |
stddev_over_time |
计算时间窗口内数值字段的标准差 | Gauge |
quantile_over_time |
计算时间窗口内数值字段的分位数 | Gauge |
first_over_time |
返回时间窗口内第一个值 | Gauge |
last_over_time |
返回时间窗口内最后一个值 | Gauge |
3.5.2 常用度量查询模式
1. 错误率计算(SLI 核心)
sum(rate({job="api-server"} |= "error" [5m])) / sum(rate({job="api-server"} [5m]))
该查询计算 5 分钟内 API 服务器的错误日志占比,是构建错误率 SLI 的基础。
2. 请求延迟分析
quantile_over_time({job="api-server"} | json | unwrap duration [5m])
该查询计算 5 分钟内请求延迟的 P99 分位数,需要日志中包含 duration 字段。
3. 特定状态码计数
count_over_time({job="api-server"} |~ "5[0-9]{2}" [5m])
该查询统计 5 分钟内 5xx 状态码的出现次数。
3.6 度量查询中的 unwrap 与 by
unwrap 用于从日志行中提取数值字段,供度量函数使用。by 用于按标签分组聚合。
示例:按服务分组计算平均延迟
avg_over_time({env="production"} | json | unwrap duration [5m]) by (service)
该查询按 service 标签分组,计算每个服务在 5 分钟内的平均请求延迟。
3.7 完整查询示例:构建 SLI 口径
以下是一个完整的 LogQL 查询,用于计算 CI/CD 流水线中部署阶段的错误率 SLI:
sum(rate({env="production", job="deploy"} |= "error" [5m]))
/
sum(rate({env="production", job="deploy"} [5m]))
* 100
null as zero 或 transform 处理空值情况。
3.8 查询性能优化建议
- 优先使用标签匹配:在
{}中尽可能精确地选择日志流,减少扫描范围。 - 行过滤器前置:将
|=、!=等行过滤器放在管道最前面,尽早过滤无关日志。 - 避免过度使用正则:正则匹配性能低于精确匹配,尽量使用
=或|=。 - 合理设置时间范围:度量查询中的时间窗口(如
[5m])应与查询范围匹配,避免过大窗口导致性能下降。 - 使用
by控制基数:分组标签的基数(唯一值数量)不宜过高,否则会导致内存压力。