PromQL验证器 promql-validator

这是一个综合工具包,用于验证、优化和理解Prometheus查询语言(PromQL)查询。它可以帮助用户检查语法、检测反模式、识别优化机会,并与用户交互式地规划查询。

数据分析 0 次安装 0 次浏览 更新于 3/4/2026

以下是内容的中文翻译,保持原有格式不变:


name: PromQL验证器 description: 综合工具包,用于验证、优化和理解Prometheus查询语言(PromQL)查询。当您使用PromQL查询时,使用此技能来检查语法、检测反模式、识别优化机会,并与用户交互式地规划查询。

这个技能如何工作

这个技能执行多级验证,并提供交互式查询规划:

  1. 语法验证:检查语法正确的PromQL表达式
  2. 语义验证:确保查询在逻辑上讲得通(例如,对计数器使用rate(),而不是仪表盘)
  3. 反模式检测:识别常见错误和低效模式
  4. 优化建议:推荐性能改进
  5. 查询解释:将PromQL翻译成普通英语
  6. 交互式规划:帮助用户澄清意图并完善查询

工作流程

当用户提供PromQL查询时,请按照此工作流程进行:

第1步:验证语法

运行语法验证脚本来检查基本正确性:

python3 .claude/skills/promql-validator/scripts/validate_syntax.py "<query>"

脚本将检查:

  • 有效的度量名称和标签匹配器
  • 正确的操作符使用
  • 适当的函数语法
  • 有效的时间持续时间和范围
  • 平衡的括号和引号
  • 正确的修饰符使用(偏移,@)

第2步:检查最佳实践

运行最佳实践检查器以检测反模式和优化机会:

python3 .claude/skills/promql-validator/scripts/check_best_practices.py "<query>"

脚本将识别:

  • 没有标签过滤器的高基数查询
  • 可以是精确匹配的低效正则表达式匹配器
  • 计数器度量缺失rate()/increase()
  • 在仪表盘度量上使用rate()
  • 预计算分位数的平均值
  • 子查询的过度时间范围
  • 在长时间范围内使用irate()
  • 增加更具体的标签过滤器的机会
  • 应该使用记录规则的复杂查询

第3步:解释查询

解析并用普通英语解释查询的作用:

  • 正在查询哪些度量
  • 它们是什么类型的度量(计数器、仪表盘、直方图、摘要)
  • 应用了哪些函数以及为什么
  • 查询计算的内容
  • 输出中将有哪些标签
  • 预期的结果结构是什么样的

所需输出细节(始终明确包含这些):

**输出标签**:[list labels that will be in the result, or "None (fully aggregated to scalar)"]
**预期结果结构**:[即时向量 / 范围向量 / 标量] with [N series / single value]

示例:

**输出标签**:作业,实例
**预期结果结构**:每个作业/实例组合都有一个系列的即时向量

第4步:交互式查询规划(第1阶段 - 停止并等待)

向用户提出澄清问题,以验证查询是否符合他们的意图:

  1. 理解目标:“您试图监控或测量什么?”

    • 请求速率、错误率、延迟、资源使用等。
  2. 验证度量类型:“这是一个计数器(总是增加)、仪表盘(可以上下)、直方图还是摘要?”

    • 这影响使用哪些函数
  3. 澄清时间范围:“您需要什么时间窗口?”

    • 即时值、随时间变化的速率、历史分析
  4. 确认聚合:“您需要跨标签聚合数据吗?如果是,哪些标签?”

    • 通过(作业),通过(实例),没有(吊舱)等。
  5. 检查输出意图:“您是用于告警、仪表板还是即席分析吗?”

    • 影响优化优先级

重要:两阶段对话

在呈现步骤1-4结果(语法、最佳实践、查询解释和意图问题)之后:

⏸️ 停止这里并等待用户响应

在用户回答第4步的澄清问题之前,不要进行步骤5-7。 这确保随后的建议针对用户的实际意图。

第5步:比较意图与实现(第2阶段 - 用户响应后)

只有在用户回答了第4步的澄清问题后,才进行这一步。

在了解了用户的意图之后:

  • 解释当前查询实际上做了什么
  • 突出显示意图和实现之间的任何不匹配
  • 如果查询不符合目标,则建议更正
  • 如果适用,提供替代方法

在相关时,提及已知限制:

  • 注意当度量类型检测是基于启发式的(例如,“脚本根据_bytes后缀推断这是仪表盘。如果正确,请确认。”)
  • 承认当高基数警告可能是误报时(例如,“如果您使用记录规则或知道您的基数很低,此警告可能不适用。”)

第6步:提供优化

根据验证结果:

  • 建议更有效的查询模式
  • 推荐复杂/重复查询的记录规则
  • 提出更好的标签匹配器以降低基数
  • 就适当的时间范围提供建议

参考示例:在建议更正时,使用此格式引用相关示例:

如在`examples/bad_queries.promql`(第91-97行)所示:
❌ BAD: `avg(http_request_duration_seconds{quantile="0.95"})`
✅ GOOD: 使用直方图_quantile()和直方图桶

引用来源:

  • examples/good_queries.promql - 遵循最佳实践的格式良好的模式
  • examples/optimization_examples.promql - 优化前后的比较
  • examples/bad_queries.promql - 展示需要避免的内容
  • docs/best_practices.md - 详细的PromQL最佳实践指南
  • docs/anti_patterns.md - 反模式深入参考,附有解释

引用格式file_path (lines X-Y)引用相关代码片段

第7步:让用户计划/完善

给用户控制权:

  • 询问他们是否想要修改查询
  • 提供帮助以重写它以获得更好的性能
  • 如果适用,提供多种替代方案
  • 解释不同方法之间的权衡

关键验证规则

语法规则

  1. 度量名称:必须匹配[a-zA-Z_:][a-zA-Z0-9_:]*或使用UTF-8引用语法(Prometheus 3.0+):
    • 引用形式:{"my.metric.with.dots"}
    • 使用__name__标签:{__name__="my.metric.with.dots"}
  2. 标签匹配器=(相等)、!=(不相等)、=~(正则匹配)、!~(正则不匹配)
  3. 时间持续时间[0-9]+(ms|s|m|h|d|w|y) - 例如,5m1h7d
  4. 范围向量metric_name[duration] - 例如,http_requests_total[5m]
  5. 偏移修饰符offset <duration> - 例如,metric_name offset 5m
  6. @修饰符@ <timestamp>@ start() / @ end()

语义规则

  1. rate()和irate():应该只与计数器度量(以_total_count_sum_bucket结尾的度量)一起使用
  2. 计数器:通常应该使用rate()increase(),而不是原始值
  3. 仪表盘:不应该使用rate()increase()
  4. 直方图:使用histogram_quantile()le标签和rate()_bucket度量上
  5. 摘要:不要平均分位数;从_sum_count计算
  6. 聚合:使用by()without()控制输出标签

性能规则

  1. 基数:始终使用特定的标签匹配器来减少系列计数
  2. 正则表达式:在可能的情况下使用=而不是=~进行精确匹配
  3. 速率范围:应该至少是抓取间隔的4倍(通常是[2m]最低)
  4. irate():最适合短时间范围(<5m);对于更长的时间段使用rate()
  5. 子查询:避免处理数百万个样本的过度时间范围
  6. 记录规则:用于频繁访问的复杂查询

检测反模式

高基数问题

Badhttp_requests_total{}

  • 匹配所有时间序列而不进行过滤

Goodhttp_requests_total{job="api", instance="prod-1"}

  • 特定的标签过滤器减少基数

过度使用正则表达式

Badhttp_requests_total{status=~"2.."}

  • 正则表达式更慢且不够精确

Goodhttp_requests_total{status="200"}

  • 精确匹配更快

计数器缺失rate()

Badhttp_requests_total

  • 计数器原始值无用(始终增加)

Goodrate(http_requests_total[5m])

  • 速率显示每秒请求数

在仪表盘上使用rate()

Badrate(memory_usage_bytes[5m])

  • 仪表盘测量当前状态,而不是累积值

Goodmemory_usage_bytes

  • 直接使用仪表盘值或与avg_over_time()一起使用

平均分位数

Badavg(http_request_duration_seconds{quantile="0.95"})

  • 数学上不允许平均预计算的分位数

Goodhistogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

  • 从直方图桶计算分位数

子查询过度范围

Badrate(metric[5m])[90d:1m]

  • 处理数百万个样本,非常慢

Good:使用记录规则或将范围限制在必要的持续时间

在长时间范围内使用irate()

Badirate(metric[1h])

  • irate()只查看最后两个样本,范围被浪费

Goodrate(metric[1h])irate(metric[5m])

  • 对于更长的时间段使用rate()或减少irate()范围

混合度量类型

Badavg(http_request_duration_seconds{quantile="0.95"}) / rate(node_memory_usage_bytes[1h]) + sum(http_requests_total)

  • 结合摘要分位数、仪表盘度量和计数器在算术中
  • 产生无意义的结果

Good:将每种度量类型保持在单独的、目的明确的查询中:

  • 延迟: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验证结果

### 语法检查
- 状态:✅ 有效 / ⚠️ 警告 / ❌ 错误
- 问题:[list any syntax errors with line/position]

### 语义检查
- 状态:✅ 有效 / ⚠️ 警告 / ❌ 错误
- 问题:[list any logical problems]

### 性能分析
- 状态:✅ 优化 / ⚠️ 可以改进 / ❌ 效率低下
- 问题:[list optimization opportunities]
- 建议:[specific improvements]

### 查询解释
您的查询:"<query>"

这个查询做:
- [Plain English explanation]
- 度量:[list metrics and their types]
- 函数:[explain each function]
- 输出:[describe result structure]

### 意图验证
让我验证这是否符合您的需求:

1. 您试图测量什么?[您在这里的目标]
2. 这是一个计数器/仪表盘/直方图/摘要吗?[度量类型]
3. 您感兴趣的时间范围是什么?[时间窗口]
4. 您需要聚合吗?如果是,通过哪些标签?[聚合需求]
5. 这是用于告警、仪表板还是分析吗?[用例]

### 建议
[Based on the analysis, suggest improvements or alternatives]

交互式对话

验证后,进行对话:

Claude:“我已经验证了您的查询。它在语法上是正确的,但我注意到它查询了http_requests_total而没有任何标签过滤器。这可能会匹配成千上万的时间序列。您具体想要监控哪个服务或端点?”

用户:[提供意图]

Claude:“太好了!基于此,这是一个优化版本:rate(http_requests_total{job="api-service", path="/users"}[5m])。这计算了过去5分钟内对/users端点每秒请求的速率。这是否符合您的需求?”

用户:[确认或请求更改]

Claude:[提供完善的查询或替代方案]

示例

查看examples/目录:

  • good_queries.promql:遵循最佳实践的编写良好的查询
  • bad_queries.promql:常见错误和反模式(附有更正)
  • optimization_examples.promql:优化前后的示例

文档

查看docs/目录:

  • best_practices.md:全面的PromQL最佳实践指南
  • anti_patterns.md:详细的反模式参考,附有解释

重要说明

  1. 互动:始终提出澄清问题以了解用户意图
  2. 教育性:解释为什么某事是错误的,而不仅仅是它是错误的
  3. 乐于助人:提供重写查询的帮助,不仅仅是批评
  4. 上下文感知:考虑用户的用例(告警与仪表板)
  5. 全面:检查所有四个级别(语法、语义、性能、意图)
  6. 实用:提出现实的优化,而不是理论上的完美

集成

这个技能可以用于:

  • 独立用于查询审查
  • 在监控设置中验证警报规则
  • 排查Prometheus查询缓慢时
  • 作为代码审查记录规则的一部分
  • 教授团队成员PromQL

验证工具

这个技能使用两个主要的Python脚本:

  1. validate_syntax.py:使用正则表达式模式进行纯语法检查
  2. check_best_practices.py:语义和性能分析

两个脚本都输出JSON以供程序解析和人类可读的消息以供显示。

成功标准

一个成功的验证会话应该:

  1. 识别所有语法错误
  2. 检测语义问题
  3. 如果适用,至少建议一个优化
  4. 清楚地解释查询的作用
  5. 验证查询是否符合用户意图
  6. 提供可行的后续步骤

已知限制

验证脚本有一些限制需要注意:

度量类型检测

  • 基于启发式:度量类型(计数器、仪表盘、直方图、摘要)是从命名约定中推断出来的(例如,_total_bytes
  • 自定义度量:非标准名称的度量可能无法正确分类
  • 建议:当脚本无法确定度量类型时,询问用户澄清

高基数检测

  • 保守方法:脚本标记没有标签选择器的度量,但有些用例合理地查询所有系列
  • 记录规则:使用记录规则度量的查询(例如,job:http_requests:rate5m)在没有标签过滤器的情况下是有效的
  • 建议:使用判断力 - 如果用户知道他们的基数是可管理的,警告可以安全地忽略

语义验证

  • 没有运行时上下文:脚本无法验证度量实际上是否存在或标签值是否有效
  • 模式不可知:不了解特定的Prometheus部署或度量模式
  • 建议:在生产验证中,针对实际的Prometheus实例测试查询

脚本检测覆盖范围

脚本检测常见反模式,但无法捕获:

  • 业务逻辑错误(例如,计算错误的KPI)
  • 特定于上下文的优化(取决于抓取间隔、保留等)
  • 来自扩展的自定义函数行为

记住

目标不仅仅是验证查询,还要帮助用户编写更好的PromQL并理解他们的监控数据。始终具有教育性、互动性和乐于助人!