在 Grafana 搭配 Prometheus 数据源时,很多用户误以为可以在面板查询语句(Query)中直接写正则来匹配指标名称(如 http_.*),但实际上 PromQL 语法不支持直接对指标名使用正则。指标名称必须明确指定,或通过仪表板变量(Variables)实现动态切换;正则表达式主要用于过滤指标携带的标签(Label)值。
先说结论:PromQL 查询中正则主要用于标签过滤,指标名称需明确指定或通过变量动态加载。
- 标签过滤:直接在 Query 中使用
=~操作符。 - 指标名过滤:无法在 Query 中写正则,需创建仪表板变量,使用
label_values(__name__)获取列表并配合正则筛选,最后在 Query 中引用变量。 - 性能建议:避免在高基数标签上使用宽泛正则,变量查询尽量缩小范围。
场景一:正则过滤标签值(PromQL 原生支持)
在 Prometheus 数据源的查询框中,正则表达式主要通过 =~(匹配)和 !~(不匹配)操作符作用于花括号内的标签值。
# 匹配 path 标签以 /api 开头的所有请求
http_requests_total{path=~"/api.*"}
# 排除 status 标签为 500 的错误请求
http_requests_total{status!~"500"}
# 匹配 service 标签为 service-A 到 service-Z 的范围
{service=~"service-[A-Z]"}注意:指标名称(如 http_requests_total)必须完整写出,不能写成 http_.*,否则查询会报错。
场景二:动态切换指标名称(需配合变量)
如果你需要根据正则动态选择多个指标名称(例如只看 http_ 开头的指标),必须在仪表板变量配置阶段实现,而不是在面板查询语句中。
1. 创建仪表板变量
点击仪表板设置图标(齿轮)→ Variables → New variable。
- Name: 例如
metric_name - Type: 选择
Query - Data source: 选择你的 Prometheus 数据源
- Query: 输入
label_values(__name__) - Regex: 在此处填写过滤指标名的正则,例如
/http_.*/(注意前后斜杠)
2. 在面板查询中引用变量
回到面板编辑页面,在 Query 框中使用 $ 或 ${} 引用变量名替换具体的指标名称:
# 使用变量代替固定的指标名
${metric_name}{instance=~"$instance"}这样,当你通过顶部下拉框切换变量值时,面板会自动查询对应的指标数据。
验证方法
配置完成后,不要直接保存,先通过以下方式确认:
1. 查看查询结果预览
在查询编辑器下方点击Table或Time series预览。如果正则生效,结果中应只包含符合模式的标签组合。例如过滤了 /api.*,结果中不应出现 /static 开头的路径。
2. 检查变量下拉框
刷新仪表板,点击顶部变量下拉框。列表中应只显示经过正则筛选后的指标名或标签值,未匹配的值不应出现。
3. 使用 Explore 模式
点击左侧菜单的Explore,选择相同数据源,粘贴查询语句。Explore 模式会显示更详细的日志和元数据,方便确认匹配到的系列(Series)是否符合预期。
常见坑与风险
1. 语法错误导致查询失败
正则表达式必须用双引号包裹,且操作符 =~ 两侧通常建议留空格以增加可读性。错误写法如 path=~ /api.* 或忘记引号会导致解析错误。
2. 部分匹配与全匹配混淆
Prometheus 的正则默认是部分匹配。表达式 /api 会匹配到 /api/users 也会匹配到 /admin/api。如果需要严格匹配开头,必须使用锚点 ^,如 ^/api.*。
3. 变量查询性能隐患
使用 label_values(__name__) 获取所有指标名在大规模集群中可能较慢。建议在变量 Query 中指定具体指标或使用 query_result(up) 等方式缩小范围,并在变量设置的 Regex 框中做二次过滤。
4. 直接在 Query 中写指标名正则
不要在 PromQL 查询语句中尝试写 http_.*{...},这会直接导致语法错误。指标名正则只能在变量配置的 Regex 字段中使用。
参考文档
- Prometheus 查询基础:https://prometheus.io/docs/prometheus/latest/querying/basics/
- Grafana Prometheus 数据源文档:https://grafana.com/docs/grafana/latest/datasources/prometheus/
- PromQL 匹配器说明:https://prometheus.io/docs/prometheus/latest/querying/basics/#string-literals