Loki 日志检索
简介
Nightingale 集成了 Loki 的日志检索能力。在日志检索页面选择 Loki 类型的数据源和时间范围后,可以在查询输入框中输入 LogQL,查看日志原文或切换到统计图表模式做聚合分析。
LogQL 查询由两部分组成:
{日志流标签选择器} | 日志处理管道
其中:
{...}是日志流标签选择器,必须填写,用来缩小 Loki 要扫描的日志流范围。|后面是可选的日志处理管道,可以继续做关键字过滤、正则过滤、JSON/logfmt 解析、字段过滤、格式化等。- 页面时间范围由 Nightingale 的时间选择器控制,不需要在 LogQL 中额外写绝对时间。
- 日志原文模式使用 LogQL 日志查询,统计图表模式使用 LogQL 指标查询,例如
count_over_time、rate、sum by、topk等。
本文后续样例使用以下常见 Loki 标签和 JSON 字段。实际查询时,请替换成你自己的 Loki 标签和日志字段。
| 类型 | 名称 | 示例值 | 常见用途 |
|---|---|---|---|
| 标签 | app |
nginx |
按应用过滤日志流 |
| 标签 | namespace |
prod |
按命名空间过滤日志流 |
| 标签 | pod |
nginx-7d9f |
按 Pod 过滤或分组 |
| 标签 | container |
nginx |
按容器过滤日志流 |
| JSON 字段 | method |
GET |
按请求方法过滤或分组 |
| JSON 字段 | uri |
/api/v1/login |
按请求路径过滤或分组 |
| JSON 字段 | status |
200 |
按状态码过滤或分组 |
| JSON 字段 | remote_addr |
10.0.0.8 |
按客户端 IP 过滤或分组 |
| JSON 字段 | request_time |
0.123 |
统计请求耗时 |
基本查询语句
以下示例可直接放在查询输入框中,用于查看日志原文。
| 场景 | 示例 | ||
|---|---|---|---|
| 查询某个应用的全部日志 | {app="nginx"} |
||
| 同时按命名空间和容器过滤 | {namespace="prod", container="nginx"} |
||
| 标签正则匹配 | `{app=~“nginx | api”}` | |
| 排除某类标签值 | {namespace="prod", pod!~".*-canary-.*"} |
||
| 包含关键字 | `{app=“nginx”} | = “error”` | |
| 排除关键字 | {app="nginx"} != "/health" |
||
| 正则匹配日志原文 | `{app=“nginx”} | ~ “status=(4 | 5)\d\d”` |
| 解析 JSON 后按字段过滤 | `{app=“nginx”} | json | status=“500”` |
| 解析 JSON 后匹配 5xx | `{app=“nginx”} | json | status=~“5.."` |
| 解析 JSON 后过滤慢请求 | `{app=“nginx”} | json | request_time > 0.5` |
| 解析 logfmt 后按级别过滤 | `{app=“api”} | logfmt | level=“error”` |
| 只展示关键信息 | `{app=“nginx”} | json | line_format “{{.method}} {{.uri}} {{.status}}"` |
常见写法:
{app="nginx"} |= "error"
{namespace="prod", container="nginx"} | json | status=~"5.."
{app="api"} | logfmt | level="error"
Loki 只索引标签,不会索引整条日志内容。查询时建议先用
{app="..."}、{namespace="..."}、{container="..."}等标签缩小日志流,再追加关键字或字段过滤。
统计图表查询
统计图表模式需要输入 LogQL 指标查询。最常见的写法是先用 count_over_time 或 rate 把日志转换成时间序列,再用 sum by、topk 等聚合。
统计日志总量
统计最近 5 分钟窗口内的日志条数:
sum(count_over_time({app="nginx"}[5m]))
统计包含 error 关键字的日志条数:
sum(count_over_time({app="nginx"} |= "error"[5m]))
查看日志产生速率
统计某个应用每秒日志产生速率:
sum(rate({app="nginx"}[5m]))
按 Pod 查看日志产生速率:
sum by (pod) (rate({namespace="prod", app="nginx"}[5m]))
按状态码统计数量
如果日志原文是 JSON,且包含 status 字段,可以写:
sum by (status) (
count_over_time({app="nginx"} | json [5m])
)
只统计 5xx:
sum(
count_over_time({app="nginx"} | json | status=~"5.."[5m])
)
查看 Top URI
topk(20,
sum by (uri) (
count_over_time({app="nginx"} | json [5m])
)
)
适用于定位当前时间范围内访问量最高的接口。这里的 uri 需要替换为日志中的真实路径字段。
计算 5xx 错误率
sum(rate({app="nginx"} | json | status=~"5.."[5m]))
/
sum(rate({app="nginx"}[5m]))
* 100
返回值单位是百分比。例如结果为 3.5,表示 5xx 日志约占 3.5%。
统计接口 P99 耗时
如果 JSON 日志中有数值字段 request_time,可以用 unwrap 把字段转换为指标值:
quantile_over_time(0.99,
{app="nginx"}
| json
| unwrap request_time
| __error__=""[5m]
) by (uri)
__error__="" 用于丢弃解析失败或数值转换失败的日志,避免指标查询报错。
使用建议
- 优先使用 Loki 标签缩小查询范围,再追加日志内容过滤。
- 日志原文排查使用
{...} |= "keyword"、| json、| logfmt等管道。 - 趋势、TopN、错误率等图表使用统计图表模式,并把
[5m]调整为适合当前时间范围的窗口。 - 如果某个字段无法用于聚合,先确认日志是否真的被
json、logfmt或regexp解析成字段。