关于 promql-validator
promql-validator 是用于检查和解释 PromQL 查询的技能,涵盖语法与语义检查、反模式检测及优化建议。它还通过交互式流程,将查询实际行为与用户意图进行比较。
主要功能
- 01检查 PromQL 语法
- 02评估指标类型用法与查询语义
- 03检测反模式和性能问题
- 04解释查询及其输出标签
- 05通过交互式规划优化查询
适用场景
- 01将查询加入仪表板前进行检查
- 02查找低效的过滤条件或聚合方式
- 03对照监控目标检查查询行为
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ akin-ozer/ cc-devops-skills --skill promql-validator安装后在 Claude Code 中输入/promql-validator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
docs/anti_patterns.mdbest_practices.mdexamples/bad_queries.promqlgood_queries.promqloptimization_examples.promqlscripts/check_best_practices.pytest_validators.pyvalidate_syntax.py详细介绍
此技能的工作方式
此技能会执行多级验证,并提供交互式查询规划:
- 语法验证:检查 PromQL 表达式的语法是否正确
- 语义验证:确保查询在逻辑上合理(例如,对计数器使用 rate(),而非对仪表盘使用)
- 反模式检测:识别常见错误和低效模式
- 优化建议:建议性能改进方案
- 查询说明:将 PromQL 转换为通俗易懂的英语
- 交互式规划:帮助用户明确意图并完善查询
工作流
用户提供 PromQL 查询时,请遵循以下工作流:
工作目录要求
请从仓库根目录运行验证命令,以确保相对路径正确解析:
cd "$(git rev-parse --show-toplevel)"
如果从其他位置运行,请使用 scripts/ 文件的绝对路径。
第 1 步:验证语法
运行语法验证脚本,检查基本正确性:
python3 devops-skills-plugin/skills/promql-validator/scripts/validate_syntax.py "<query>"
输出解析说明:
- 退出码为
0:语法有效 - 退出码非零:语法错误;包含 stderr 并指出具体词元/位置
- 优先引用最小的错误片段,然后提供修正后的查询
脚本将检查:
- 指标名称和标签匹配器是否有效
- 运算符使用是否正确
- 函数语法是否正确
- 时间长度和范围是否有效
- 括号和引号是否匹配
- 修饰符(offset、@)使用是否正确
第 2 步:检查最佳实践
运行最佳实践检查器,以检测反模式和优化机会:
python3 devops-skills-plugin/skills/promql-validator/scripts/check_best_practices.py "<query>"
输出解析说明:
- 将脚本各部分视为独立发现项(基数、指标类型误用、正则表达式误用等)
- 如果脚本输出为空,但查询较复杂,请额外进行人工检查,并将其标记为
manual-review - 保留脚本对发现项的原有措辞,然后用通俗英语补充改进建议
脚本将识别:
- 未使用标签过滤器的高基数查询
- 本可使用精确匹配却使用了低效正则表达式匹配器的情况
- 计数器指标缺少 rate()/increase() 的情况
- 在仪表盘指标上使用 rate() 的情况
- 对预先计算的分位数求平均值的情况
- 时间范围过大的子查询
- 在较长时间范围内使用 irate() 的情况
- 添加更具体标签过滤器的机会
- 应使用记录规则的复杂查询
第 3 步:说明查询
解析查询,并用通俗易懂的英语说明其作用:
- 查询了哪些指标
- 这些指标的类型(计数器、仪表盘、直方图、摘要)
- 使用了哪些函数,以及使用原因
- 查询计算的内容
- 输出中会包含哪些标签
- 预期结果的结构
必需的输出详情(始终明确包含以下内容):
**Output Labels**: [list labels that will be in the result, or "None (fully aggregated to scalar)"]
**Expected Result Structure**: [instant vector / range vector / scalar] with [N series / single value]
示例:
**Output Labels**: job, instance
**Expected Result Structure**: Instant vector with one series per job/instance combination
行号引用方法(必需)
在建议中引用示例/文档时,请包含文件路径和从 1 开始计数的行号:
examples/good_queries.promql:42
docs/best_practices.md:88
规则:
- 引用最相关的单行(多行代码片段则引用起始行)
- 引用范围要精确;不要引用整个文件
- 如果无法获取行号,请说明
line number unavailable,并提供文件路径
步骤 4:交互式查询规划(阶段 1 - 停止并等待)
向用户提问以澄清问题,确认查询符合其意图:
-
了解目标:“你想监控或衡量什么?”
- 请求率、错误率、延迟、资源使用情况等
-
确认指标类型:“这是计数器(始终递增)、仪表(可升可降)、直方图还是摘要?”
- 这会影响要使用的函数
-
明确时间范围:“你需要哪个时间窗口?”
- 即时值、随时间变化的速率、历史分析
-
确认聚合方式:“你需要跨标签聚合数据吗?如果需要,要按哪些标签聚合?”
- by (job)、by (instance)、without (pod) 等
-
确认输出用途:“你是要将其用于告警、仪表板还是临时分析?”
- 这会影响优化优先级
重要:两阶段对话
呈现步骤 1-4 的结果(语法、最佳实践、查询说明和意图问题)后:
⏸️ 在此处停止并等待用户回复
在用户回答澄清问题之前,不要继续执行步骤 5-7。 这样可以确保后续建议符合用户的实际意图。
步骤 5:比较意图与实现(阶段 2 - 用户回复后)
只有在用户回答了步骤 4 中的澄清问题后,才能继续执行此步骤。
了解用户的意图后:
- 说明当前查询实际执行的操作
- 指出意图与实现之间的任何不匹配之处
- 如果查询不符合目标,建议进行修正
- 如适用,提供替代方案
相关时,请说明已知限制:
- 指出指标类型检测是基于启发式的(例如:“脚本根据
_bytes后缀推断这是一个仪表。请确认是否正确。”) - 说明高基数警告可能是误报(例如:“如果你使用的是记录规则,或者确认基数较低,则此警告可能不适用。”)
步骤 6:提供优化建议
根据验证结果:
- 建议更高效的查询模式
- 对复杂或重复的查询,建议使用记录规则
- 建议使用更合适的标签匹配器来降低基数
- 建议采用适当的时间范围
参考示例:建议修正时,按以下格式引用相关示例:
As shown in `examples/bad_queries.promql` (lines 91-97):
❌ BAD: `avg(http_request_duration_seconds{quantile="0.95"})`
✅ GOOD: Use histogram_quantile() with histogram buckets
引用来源:
examples/good_queries.promql- 规范模式examples/optimization_examples.promql- 优化前后对比examples/bad_queries.promql- 展示应避免的写法docs/best_practices.md- 详细说明docs/anti_patterns.md- 反模式深入解析
引用格式:file_path (lines X-Y),并引用相关代码片段
步骤 7:让用户规划和改进
让用户掌握主动权:
- 询问他们是否想修改查询
- 提供帮助,重写查询以提升性能
- 如适用,提供多个替代方案
- 说明不同方法之间的权衡
关键验证规则
语法规则
- 指标名称:必须匹配
[a-zA-Z_:][a-zA-Z0-9_:]*,或使用 UTF-8 引号语法(Prometheus 3.0+):- 引号形式:
{"my.metric.with.dots"} - 使用 name 标签:
{__name__="my.metric.with.dots"}
- 引号形式:
- 标签匹配器:
=(等于)、!=(不等于)、=~(正则匹配)、!~(正则不匹配) - 时间长度:
[0-9]+(ms|s|m|h|d|w|y)- 例如,5m、1h、7d - 范围向量:
metric_name[duration]- 例如,http_requests_total[5m] - 偏移修饰符:
offset <duration>- 例如,metric_name offset 5m - @ 修饰符:
@ <timestamp>或@ start()/@ end()
语义规则
- rate() 和 irate():仅应与计数器指标(以
_total、_count、_sum或_bucket结尾的指标)搭配使用 - 计数器:通常应使用
rate()或increase(),而不是原始值 - 仪表盘:不应使用
rate()或increase() - 直方图:应使用带有
le标签的histogram_quantile(),并对_bucket指标使用rate() - 摘要:不要对分位数求平均;应根据
_sum和_count计算 - 聚合:使用
by()或without()控制输出标签
性能规则
- 基数:始终使用具体的标签匹配器来减少时间序列数量
- 正则表达式:如果可能,应使用
=而不是=~进行精确匹配 - 速率范围:应至少为抓取间隔的 4 倍(通常最小为
[2m]) - irate():最适用于较短范围(<5m);较长时间段应使用
rate() - 子查询:避免使用过长的时间范围,以免处理数百万个样本
- 记录规则:对于频繁访问的复杂查询,应使用记录规则
需要检测的反模式
高基数问题
❌ 错误:http_requests_total{}
- 未经过滤便匹配所有时间序列
✅ 正确:http_requests_total{job="api", instance="prod-1"}
- 具体的标签筛选条件可降低基数
过度使用正则表达式
❌ 错误:http_requests_total{status=~"2.."}
- 正则表达式速度较慢,且不够精确
✅ 正确:http_requests_total{status="200"}
- 精确匹配速度更快
计数器缺少 rate()
❌ 错误:http_requests_total
- 计数器原始值没有实用价值(始终递增)
✅ 正确:rate(http_requests_total[5m])
- 速率表示每秒请求数
对仪表盘使用 rate()
❌ 错误:rate(memory_usage_bytes[5m])
- 仪表盘衡量当前状态,而非累积值
✅ 正确:memory_usage_bytes
- 直接使用仪表盘值,或搭配
avg_over_time()
对分位数求平均
❌ 错误:avg(http_request_duration_seconds{quantile="0.95"})
- 对预先计算的分位数求平均在数学上无效
✅ 正确:histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
- 根据直方图桶计算分位数
子查询范围过长
❌ 错误:rate(metric[5m])[90d:1m]
- 会处理数百万个样本,速度非常慢
✅ 正确:使用记录规则,或将范围限制在所需时长内
在较长范围内使用 irate()
❌ 错误:irate(metric[1h])
- irate() 只查看最后两个样本,范围设置毫无意义
✅ 正确:rate(metric[1h]) 或 irate(metric[5m])
- 较长范围应使用 rate(),或缩短 irate() 的范围
混用指标类型
❌ 错误:avg(http_request_duration_seconds{quantile="0.95"}) / rate(node_memory_usage_bytes[1h]) + sum(http_requests_total)
- 将摘要分位数、仪表盘指标和计数器用于算术运算
- 会产生毫无意义的结果
✅ 正确:将每种指标类型分别放在用途明确的查询中:
- 延迟:
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) - 内存:
node_memory_usage_bytes{instance="prod-1"} - 请求速率:
rate(http_requests_total{job="api"}[5m])
输出格式
请按以下结构提供验证结果:
## PromQL Validation Results
### Syntax Check
- Status: ✅ VALID / ⚠️ WARNING / ❌ ERROR
- Issues: [list any syntax errors with line/position]
### Semantic Check
- Status: ✅ VALID / ⚠️ WARNING / ❌ ERROR
- Issues: [list any logical problems]
### Performance Analysis
- Status: ✅ OPTIMIZED / ⚠️ CAN BE IMPROVED / ❌ INEFFICIENT
- Issues: [list optimization opportunities]
- Suggestions: [specific improvements]
### Query Explanation
Your query: `<query>`
This query does:
- [Plain English explanation]
- Metrics: [list metrics and their types]
- Functions: [explain each function]
- Output: [describe result structure]
### Intent Verification
Let me verify this matches your needs:
1. What are you trying to measure? [your goal here]
2. Is this a counter/gauge/histogram/summary? [metric type]
3. What time range interests you? [time window]
4. Do you need aggregation? If so, by which labels? [aggregation needs]
5. Is this for alerting, dashboarding, or analysis? [use case]
### Recommendations
[Based on the analysis, suggest improvements or alternatives]
交互式对话
验证后,继续对话:
Claude:“我已验证你的查询。语法正确,但我注意到它查询 http_requests_total 时没有任何标签筛选条件。这可能匹配数千条时间序列。你想监控哪个具体服务或端点?”
User:[提供意图]
Claude:“很好!根据你的需求,下面是优化后的版本:rate(http_requests_total{job="api-service", path="/users"}[5m])。这会计算过去 5 分钟内发往 /users 端点的每秒速率。这样符合你的需求吗?”
User:[确认或要求修改]
Claude:[提供优化后的查询或替代方案]
示例
请参阅 examples/ 目录:
good_queries.promql:遵循最佳实践的优质查询bad_queries.promql:常见错误和反模式(附修正方法)optimization_examples.promql:优化前后的示例
文档
请参阅 docs/ 目录:
best_practices.md:全面的 PromQL 最佳实践指南anti_patterns.md:详细的反模式参考及说明
重要说明
- 积极互动:始终提出澄清问题,了解用户意图
- 注重讲解:说明问题出在哪里以及原因,而不只是指出有问题
- 提供帮助:主动提出重写查询,而不只是批评
- 结合上下文:考虑用户的使用场景(告警还是仪表盘)
- 全面检查:检查所有四个层面(语法、语义、性能、意图)
- 注重实用:建议切实可行的优化,而非理论上的完美方案
集成
此技能可用于:
- 独立进行查询审查
- 设置监控时验证告警规则
- 排查缓慢的 Prometheus 查询
- 作为代码审查的一部分检查记录规则
- 向团队成员讲解 PromQL
验证工具
此技能使用两个主要的 Python 脚本:
- validate_syntax.py:使用正则表达式进行纯语法检查
- check_best_practices.py:进行语义和性能分析
两个脚本都会输出 JSON,以便程序化解析;也会输出便于阅读的消息供人查看。
成功标准
一次成功的验证应当:
- 找出所有语法错误
- 检测语义问题
- 至少提出一项优化建议(如适用)
- 清楚说明查询的作用
- 确认查询符合用户意图
- 提供可执行的后续步骤
已知限制
验证脚本存在一些需要注意的限制:
指标类型检测
- 基于启发式规则:根据命名约定(例如
_total、_bytes)推断指标类型(counter、gauge、histogram、summary) - 自定义指标:名称不符合标准的指标可能无法正确分类
- 建议:如果脚本无法确定指标类型,请向用户确认
高基数检测
- 保守做法:脚本会标记未指定标签选择器的指标,但某些使用场景确实需要查询所有时间序列
- 记录规则:使用记录规则指标(例如
job:http_requests:rate5m)的查询无需标签过滤器也有效 - 建议:根据实际情况判断——如果用户确定其基数可控,可以放心忽略警告
语义验证
- 没有运行时上下文:脚本无法验证指标是否实际存在,也无法确认标签值是否有效
- 不依赖特定架构:不了解特定 Prometheus 部署或指标架构
- 建议:进行生产环境验证时,请在实际的 Prometheus 实例上测试查询
脚本检测覆盖范围
脚本可以检测常见反模式,但无法发现:
- 业务逻辑错误(例如,计算了错误的 KPI)
- 特定上下文的优化(取决于抓取间隔、保留期等)
- 扩展提供的自定义函数行为
请记住
目标不仅是验证查询,更是帮助用户编写更好的 PromQL,并理解其监控数据。始终注重讲解、积极互动并提供帮助!