VictoriaLogs 日志检索
简介
Nightingale 集成了 VictoriaLogs 的日志检索能力。在日志检索页面选择 VictoriaLogs 类型的数据源和时间范围后,可以在查询输入框中输入 LogsQL,查看日志原文或切换到统计图表模式做聚合分析。
LogsQL 查询由过滤条件和管道组成:
过滤条件 | 管道
其中:
|左侧是过滤条件,用来筛选日志。只需要查看原始日志时,可以只写这一部分。|右侧是可选管道,可以做字段选择、排序、限制条数、统计聚合等。- 页面时间范围由 Nightingale 的时间选择器控制,通常不需要在 LogsQL 中额外写
_time条件。 - VictoriaLogs 支持
{app="nginx"}这种日志流过滤。如果字段已作为 stream field 写入,优先使用日志流过滤,查询效率更高。
本文后续样例使用以下常见日志字段。实际查询时,请替换成你自己的 VictoriaLogs 字段名。
| 字段 | 示例值 | 常见用途 |
|---|---|---|
app |
nginx |
按应用过滤或分组 |
namespace |
prod |
按命名空间过滤或分组 |
pod |
nginx-7d9f |
按 Pod 过滤或分组 |
method |
GET |
按请求方法过滤或分组 |
uri |
/api/v1/login |
按请求路径过滤或分组 |
status |
200 |
按状态码过滤或分组 |
remote_addr |
10.0.0.8 |
按客户端 IP 过滤或分组 |
request_time |
0.123 |
统计请求耗时 |
如果字段名中包含点号、冒号、空格等特殊字符,建议用双引号包裹字段名,例如 "log.level":"error"。
基本查询语句
以下示例可直接放在查询输入框中,用于查看日志原文。
| 场景 | 示例 | |
|---|---|---|
| 全量查询 | * |
|
| 按关键字查询 | error |
|
| 按短语查询 | "internal server error" |
|
| 按日志流过滤 | {app="nginx"} |
|
| 按多个日志流字段过滤 | {namespace="prod", app="nginx"} |
|
| 按字段查询 | status:"500" |
|
| 精确匹配字段完整值 | method:="GET" |
|
| 按字段正则查询 | uri:~"/api/v1/.*" |
|
| 查询 5xx 状态码 | status:~"5.." |
|
| 数值比较 | request_time:>0.5 |
|
| 数值范围 | status:>=500 status:<=599 |
|
| 排除健康检查 | NOT uri:"/health" |
|
| 多条件与关系 | app:"nginx" AND status:"500" |
|
| 多条件或关系 | status:"500" OR status:"502" |
|
| 只展示部分字段 | `error | fields _time, app, status, uri, _msg` |
| 按时间倒序取 20 条 | `error | sort by (_time desc) limit 20` |
常见写法:
{app="nginx"} error
{namespace="prod", app="nginx"} status:~"5.."
request_time:>0.5 NOT uri:"/health"
VictoriaLogs 中多个过滤条件可以用
AND连接,也可以直接用空格连接。为了便于阅读,复杂条件建议显式写AND、OR、NOT并加括号。
统计图表查询
统计图表模式可以使用 stats、math、sort、limit 等 LogsQL 管道。以下示例中的 _time:1m 表示按 1 分钟做时间桶;如果查询时间范围较大,可以把它改成 _time:5m、_time:1h 等更大的粒度。
统计日志总量
统计当前时间范围内的日志总数:
* | stats count() log_count
统计错误日志总数:
error | stats count() error_count
按状态码统计数量
* | stats by (status) count() log_count
| sort by (log_count desc)
| limit 20
适用于查看 HTTP 状态码分布,例如 2xx、4xx、5xx 哪类日志最多。
查看 Top URI
* | stats by (uri) count() pv
| sort by (pv desc)
| limit 20
如果只关注 5xx 请求,可以先过滤状态码:
status:~"5.." | stats by (uri) count() error_count
| sort by (error_count desc)
| limit 20
最近 1 小时日志量趋势
先在页面时间范围中选择最近 1 小时,再输入:
* | stats by (_time:1m) count() log_count
| sort by (_time)
这个查询会把当前时间范围内的日志按 1 分钟聚合。
最近 1 小时 5xx 趋势
status:~"5.." | stats by (_time:1m) count() error_count
| sort by (_time)
按时间统计不同状态码数量
* | stats by (_time:1m, status) count() log_count
| sort by (_time, status)
适用于观察某个时间点 5xx 是否突然升高,或 4xx 是否集中出现。
计算错误率
* | stats by (_time:1m)
count() total,
count() if (status:~"5..") errors
| math (errors / total * 100) as error_rate
| sort by (_time)
返回的 error_rate 单位是百分比。例如结果为 3.5,表示该时间桶内 5xx 日志占比约为 3.5%。
统计接口平均耗时
* | stats by (uri)
count() log_count,
avg(request_time) avg_request_time
| sort by (avg_request_time desc)
| limit 20
适用于定位平均耗时最高的接口。这里的 request_time 需要是可解析为数值的字段。
按客户端 IP 统计访问量
* | stats by (remote_addr) count() pv
| sort by (pv desc)
| limit 20
统计不同客户端 IP 数量趋势
* | stats by (_time:1m) count_uniq(remote_addr) unique_ip_count
| sort by (_time)
适用于观察当前时间范围内,不同客户端 IP 数量是否有异常变化。
使用建议
- 如果日志已配置 stream field,优先使用
{app="..."}、{namespace="..."}这类日志流过滤。 - 只看原始日志时,使用关键字、字段过滤、
fields、sort、limit即可。 - 做趋势、TopN、错误率等分析时,使用统计图表模式,并用
stats by (...)聚合。 - 大范围查询时先缩小字段过滤或日志流过滤,再扩大时间范围,避免一次扫描过多日志。