VictoriaLogs LogsQL 使用指南

4 阅读4分钟

20分钟掌握日志查询

核心原理

LogsQL 做三件事:过滤 → 提取 → 统计

查询执行流程:

_time:1h error | extract_regexp ... | stats by (url) count()
    ↓                  ↓                      ↓
1. 扫描索引      2. 逐条提取字段        3. 内存聚合
   10亿条  →        1万条  →              100

关键:必须先指定 _time(否则扫描全库会超时),越早过滤越快。


1分钟:基础查询

_time:5m                                      # 看最近 5 分钟的日志
_time:1h error                                # 找包含 error 的日志
_time:1h service_name:"api" error -debug      # 组合过滤

时间范围5m 1h 1d 7d 30d

立即试试:打开 Web UI (http://your-server:9428/select/vmui),输入 _time:5m 看看有什么日志。


2分钟:过滤语法

字段匹配(索引加速)

service_name:"api"      # 精确匹配
log_type:"error"        # 日志类型
host:"server1"          # 主机名

文本搜索

error                   # 关键词
"cannot open"           # 短语
err*                    # 通配符
-debug                  # 排除

逻辑组合

error timeout           # AND(空格)
error OR warning        # OR
(error OR warning) AND service_name:"api" -debug

高级时间

_time:[2026-02-24, 2026-02-25)           # 指定日期
_time:30d AND _time:week_range[Tue, Tue]  # 只要周二

3分钟:统计分析

计数和分组

_time:1h error | stats count()                              # 有多少条
_time:1h error | stats by (service_name) count() as cnt    # 按服务分组

Top N

_time:1h error 
| stats by (service_name) count() as cnt 
| sort by (cnt)      # 默认降序
| limit 10

时间趋势

_time:1d error | stats by (_time:1h) count()   # 每小时错误数

统计函数

count()              # 计数
sum(field)           # 求和
avg(field)           # 平均
min(field) max(field)  # 最小/最大
count_uniq(field)    # 去重计数

4分钟:提取字段

日志是文本,用正则提取结构化字段:

_time:1h 
| extract_regexp '"url":"(?P<url>[^"]+)"'      # 提取 url
| extract_regexp '"cost":(?P<cost>[0-9]+)'     # 提取 cost
| stats by (url) avg(cost) as avg_ms           # 统计平均耗时
| sort by (avg_ms) | limit 10

常用正则

'"url":"(?P<url>[^"]+)"'              # JSON 字符串
'"cost":(?P<cost>[0-9]+)'             # JSON 数字
'ip=(?P<ip>([0-9]+[.]){3}[0-9]+)'     # IP 地址

技巧:先用 | limit 10 看原始日志,确认正则能匹配。


实战场景

故障排查

哪个服务错误最多?

_time:5m (error OR exception) 
| stats by (service_name) count() as cnt 
| sort by (cnt) 
| limit 10

某个接口为什么慢?

_time:1h service_name:"api" 
| extract_regexp '"url":"(?P<url>[^"]+)"' 
| extract_regexp '"cost":(?P<cost>[0-9]+)' 
| stats by (url) avg(cost) as avg_ms, max(cost) as max_ms 
| sort by (avg_ms) 
| limit 10

周期性问题(每周二都慢)

_time:30d log_type:"slow" AND _time:week_range[Tue, Tue] 
| extract_regexp '"url":"(?P<url>[^"]+)"' 
| stats by (_time:1d, url) count() 
| sort by (_time)

性能分析

哪些用户受影响?

_time:1h error 
| extract_regexp '"user_id":"(?P<user_id>[^"]+)"' 
| extract_regexp '"url":"(?P<url>[^"]+)"' 
| stats by (url) count() as errors, count_uniq(user_id) as users 
| sort by (users) 
| limit 20

流量趋势

_time:1d 
| stats by (_time:10m) count() 
| sort by (_time)

调试技巧

查询慢或超时?

  1. 缩小时间:_time:1h 而不是 _time:30d
  2. 先用索引字段:service_name:"xxx" log_type:"error"
  3. 测试时加 | limit 10

反模式

❌ _time:30d | extract_regexp ...  # 先扫描 30 天,慢!
✅ _time:30d service_name:"api" | extract_regexp ...  # 先过滤,快!

查询报错?

  1. 去掉管道,只留过滤器
  2. 逐个加管道,定位问题
  3. | limit 10 检查字段名

常见错误

  • missing whitespace → 检查括号、引号
  • cannot parse → 正则表达式有问题
  • field not found → 字段名错误

正则不匹配?

  1. _time:5m | limit 10 看原始日志
  2. 在 regex101.com 调试正则
  3. 确认能匹配后再加到查询

速查:我想...

我想...查询
看看最近有什么日志_time:5m
找错误日志_time:1h error
找特定服务的错误_time:1h service_name:"api" error
统计错误数量_time:1h error | stats count()
找错误最多的服务_time:1h error | stats by (service_name) count() as cnt | sort by (cnt) | limit 10
看每小时错误趋势_time:1d error | stats by (_time:1h) count()
找最慢的接口_time:1h | extract_regexp '"url":"(?P<url>[^"]+)"' | extract_regexp '"cost":(?P<cost>[0-9]+)' | stats by (url) avg(cost) as avg_ms | sort by (avg_ms) | limit 10
找周二的慢日志_time:30d AND _time:week_range[Tue, Tue] log_type:"slow"
看有多少不同的用户_time:1h | extract_regexp '"user_id":"(?P<user_id>[^"]+)"' | stats count_uniq(user_id)

语法速查

功能语法
时间_time:5m _time:1h _time:1d _time:7d
时间范围_time:[2026-02-24, 2026-02-25)
周几_time:week_range[Tue, Tue]
字段匹配service_name:"api" host:"server1"
关键词error "cannot open" err*
逻辑a b (AND) a OR b -a (NOT)
提取extract_regexp '"url":"(?P<url>[^"]+)"'
统计stats count() stats by (field) count()
聚合avg() sum() min() max() count_uniq()
排序sort by (field) sort by (field) asc
限制limit 10

记住

公式过滤器 | 管道 = 先找日志,再加工

必须:每个查询都要有 _time

最佳实践

  1. 总是加时间过滤
  2. 优先用索引字段(service_namelog_type
  3. 先过滤再处理
  4. 测试时用 limit 限制结果

文档docs.victoriametrics.com/victorialog…