以下是内容的中文翻译,保持原有格式不变:
name: PromQL验证器 description: 综合工具包,用于验证、优化和理解Prometheus查询语言(PromQL)查询。当您使用PromQL查询时,使用此技能来检查语法、检测反模式、识别优化机会,并与用户交互式地规划查询。
这个技能如何工作
这个技能执行多级验证,并提供交互式查询规划:
- 语法验证:检查语法正确的PromQL表达式
- 语义验证:确保查询在逻辑上讲得通(例如,对计数器使用rate(),而不是仪表盘)
- 反模式检测:识别常见错误和低效模式
- 优化建议:推荐性能改进
- 查询解释:将PromQL翻译成普通英语
- 交互式规划:帮助用户澄清意图并完善查询
工作流程
当用户提供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-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步:让用户计划/完善
给用户控制权:
- 询问他们是否想要修改查询
- 提供帮助以重写它以获得更好的性能
- 如果适用,提供多种替代方案
- 解释不同方法之间的权衡
关键验证规则
语法规则
- 度量名称:必须匹配
[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() - 直方图:使用
histogram_quantile()与le标签和rate()在_bucket度量上 - 摘要:不要平均分位数;从
_sum和_count计算 - 聚合:使用
by()或without()控制输出标签
性能规则
- 基数:始终使用特定的标签匹配器来减少系列计数
- 正则表达式:在可能的情况下使用
=而不是=~进行精确匹配 - 速率范围:应该至少是抓取间隔的4倍(通常是
[2m]最低) - irate():最适合短时间范围(<5m);对于更长的时间段使用
rate() - 子查询:避免处理数百万个样本的过度时间范围
- 记录规则:用于频繁访问的复杂查询
检测反模式
高基数问题
❌ Bad:http_requests_total{}
- 匹配所有时间序列而不进行过滤
✅ Good:http_requests_total{job="api", instance="prod-1"}
- 特定的标签过滤器减少基数
过度使用正则表达式
❌ Bad:http_requests_total{status=~"2.."}
- 正则表达式更慢且不够精确
✅ Good:http_requests_total{status="200"}
- 精确匹配更快
计数器缺失rate()
❌ Bad:http_requests_total
- 计数器原始值无用(始终增加)
✅ Good:rate(http_requests_total[5m])
- 速率显示每秒请求数
在仪表盘上使用rate()
❌ Bad:rate(memory_usage_bytes[5m])
- 仪表盘测量当前状态,而不是累积值
✅ Good:memory_usage_bytes
- 直接使用仪表盘值或与
avg_over_time()一起使用
平均分位数
❌ Bad:avg(http_request_duration_seconds{quantile="0.95"})
- 数学上不允许平均预计算的分位数
✅ Good:histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
- 从直方图桶计算分位数
子查询过度范围
❌ Bad:rate(metric[5m])[90d:1m]
- 处理数百万个样本,非常慢
✅ Good:使用记录规则或将范围限制在必要的持续时间
在长时间范围内使用irate()
❌ Bad:irate(metric[1h])
- irate()只查看最后两个样本,范围被浪费
✅ Good:rate(metric[1h])或irate(metric[5m])
- 对于更长的时间段使用rate()或减少irate()范围
混合度量类型
❌ Bad:avg(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:详细的反模式参考,附有解释
重要说明
- 互动:始终提出澄清问题以了解用户意图
- 教育性:解释为什么某事是错误的,而不仅仅是它是错误的
- 乐于助人:提供重写查询的帮助,不仅仅是批评
- 上下文感知:考虑用户的用例(告警与仪表板)
- 全面:检查所有四个级别(语法、语义、性能、意图)
- 实用:提出现实的优化,而不是理论上的完美
集成
这个技能可以用于:
- 独立用于查询审查
- 在监控设置中验证警报规则
- 排查Prometheus查询缓慢时
- 作为代码审查记录规则的一部分
- 教授团队成员PromQL
验证工具
这个技能使用两个主要的Python脚本:
- validate_syntax.py:使用正则表达式模式进行纯语法检查
- check_best_practices.py:语义和性能分析
两个脚本都输出JSON以供程序解析和人类可读的消息以供显示。
成功标准
一个成功的验证会话应该:
- 识别所有语法错误
- 检测语义问题
- 如果适用,至少建议一个优化
- 清楚地解释查询的作用
- 验证查询是否符合用户意图
- 提供可行的后续步骤
已知限制
验证脚本有一些限制需要注意:
度量类型检测
- 基于启发式:度量类型(计数器、仪表盘、直方图、摘要)是从命名约定中推断出来的(例如,
_total、_bytes) - 自定义度量:非标准名称的度量可能无法正确分类
- 建议:当脚本无法确定度量类型时,询问用户澄清
高基数检测
- 保守方法:脚本标记没有标签选择器的度量,但有些用例合理地查询所有系列
- 记录规则:使用记录规则度量的查询(例如,
job:http_requests:rate5m)在没有标签过滤器的情况下是有效的 - 建议:使用判断力 - 如果用户知道他们的基数是可管理的,警告可以安全地忽略
语义验证
- 没有运行时上下文:脚本无法验证度量实际上是否存在或标签值是否有效
- 模式不可知:不了解特定的Prometheus部署或度量模式
- 建议:在生产验证中,针对实际的Prometheus实例测试查询
脚本检测覆盖范围
脚本检测常见反模式,但无法捕获:
- 业务逻辑错误(例如,计算错误的KPI)
- 特定于上下文的优化(取决于抓取间隔、保留等)
- 来自扩展的自定义函数行为
记住
目标不仅仅是验证查询,还要帮助用户编写更好的PromQL并理解他们的监控数据。始终具有教育性、互动性和乐于助人!