关于 signoz-explaining-alerts
signoz-explaining-alerts 是解读现有 SigNoz 告警配置的只读技能,适合需要了解告警监控信号、触发条件和通知路由的用户。它将规则配置转为运维说明,并附上一行触发频率信息,不调查具体事件。
主要功能
- 01读取告警完整配置
- 02说明监控信号、范围与阈值
- 03解释评估窗口和触发时序
- 04解析通知渠道与路由规则
- 05汇总近 7 天触发频率
适用场景
- 01确认现有告警监控的内容与阈值
- 02审查告警条件和通知配置
- 03将告警 JSON 转为运维说明
- 04查看规则近期触发次数
MCP 相关
该技能使用 SigNoz MCP 服务读取告警规则、完整配置和触发历史。运行前确认 `signoz_*` 工具可用;若未配置,先运行 `signoz-mcp-setup`。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ signoz/ agent-skills --skill signoz-explaining-alerts安装后在 Claude Code 中输入/signoz-explaining-alerts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonevals/files/empty-alert-history.jsongrouped-alert-history.json详细介绍
告警解读
将现有 SigNoz 告警的配置解读为通俗易懂的说明。此技能为只读操作,仅关注规则本身:监控什么、何时触发、通知发送到哪里。说明中会包含一行触发频率数据作为参考,但此技能不会调查任何具体的触发事件;这属于 signoz-investigating-alerts 的职责。
前提条件
此技能会调用 SigNoz MCP 服务工具(signoz_get_alert、
signoz_list_alert_rules、signoz_get_alert_history)。
运行工作流前,请确认 signoz_* 工具可用。如果不可用,请先运行
signoz-mcp-setup,以初始化或修复 MCP 连接。
不要仅凭规则名称猜测告警配置。
适用场景
当用户想要以下操作时,使用此技能:
- 了解或解读现有告警规则。
- 确认告警监控的信号及其阈值。
- 审核告警配置是否合理。
- 将原始告警 JSON 转换为运维人员易懂的语言。
当用户想要以下操作时,不要使用此技能:
- 创建新告警 →
signoz-creating-alerts。 - 诊断告警触发原因,或关联触发时间段内的信号
→
signoz-investigating-alerts。 - 修改现有告警 → 直接调用
signoz_update_alert。
必需输入
| 输入 | 必需 | 缺少时的来源 |
|---|---|---|
| 告警标识符(规则 ID 或名称) | 是 | $ARGUMENTS、近期上下文或模糊匹配 |
如果输入缺失或不明确,此技能会尽力处理(并非严格要求;只读操作出错后很容易恢复):
- 调用
signoz_list_alert_rules,遍历所有分页,并查找名称最接近的规则。 - 在回复中说明你的解读: “我将你的请求理解为告警 ‘High Error Rate - Checkout’(id 42)。 如果你指的是其他告警,请告诉我名称或 id。”
- 继续进行说明。用户之后可以纠正。
工作流
步骤 1:确定告警
如果用户提供了规则 ID(UUID 或旧版数字 ID),请跳至步骤 2。 否则:
- 调用
signoz_list_alert_rules,并遍历所有分页:pagination.hasMore为 true 时,表示列表尚未遍历完。 - 按名称匹配(不区分大小写的子串)。如果有多个匹配项, 列出候选项并询问用户要选择哪一个(交互模式),或选择最接近的项并标明假设(自主模式)。
步骤 2:获取完整配置
使用规则 ID 调用 signoz_get_alert。这是必需的:列表响应不包含完整的条件、阈值和通知设置,仅根据名称进行说明属于猜测。
步骤 3:获取单行触发频率摘要
首先,调用 signoz_get_alert_history,设置 timeRange: "7d"、
state: "firing"、order: "desc",并使用较大的 limit。仅当
data.nextCursor 存在时才继续(完整性说明也会报告 hasMore: true):
将该值作为 cursor 传入,将 timeRange 替换为说明中解析出的绝对
start 和 end,并保留相同的 state、filter 和 order。
当 nextCursor 不存在或说明报告 hasMore: false 时停止。绝不要使用
offset,也不要根据页面是否已满来推断数据是否完整。
历史记录的 state 接受 inactive、pending、recovering、firing、nodata
或 disabled。对于“resolved”/“recovered”,使用 state: "inactive";
resolved 不是有效值;recovering 是一种暂时的持续触发状态,并非已解决。
根据完整数据集得出一条规则级摘要。历史记录按标签组
fingerprint 逐条输出,因此绝不能将行数等同于告警触发次数。
统计满足 overallStateChanged: true 和 overallState: "firing" 的不同规则状态转换
(对同一转换时间戳的行去重):
过去 7d 触发 N 次(最近一次触发:<相对时间>)。
如果用户询问的是特定服务、主机或组,则改为按 fingerprint 分组,并统计该序列中
stateChanged: true 且 state: "firing" 的行;同时包含其标签,并将结果称为序列触发,而非
规则级触发。分组规则可以有许多序列状态转换,而整体规则持续处于触发状态。
如果完整历史记录中没有触发状态转换,则报告工具返回的内容:“过去 7d 未返回任何触发事件。”
不要缩短为“未触发”或“从未触发”。完整历史记录仍可能因保留期限或规则以新 ID
重新创建而遗漏触发记录。若用户依赖该答案(例如他们预期告警应当触发),请补充这一注意事项。
如果历史记录调用失败,或分页在 nextCursor 尚未消失时就停止,请说明历史记录不完整,并将
任何计数表述为“至少 N 次”;读取失败或不完整时,绝不要报告零次。
以下各项应作为独立事实分别报告,并分别依据各自的数据来源:
- 触发历史:
signoz_get_alert_history返回的状态转换。 - 当前状态:
signoz_get_alert返回的规则state,或signoz_list_alerts返回的当前 实例。 - 配置:
signoz_get_alert返回的disabled、阈值和路由信息。 - 通知投递:SigNoz 告警工具均不会返回此信息。触发状态转换、配置了通知渠道或渠道测试通过,都不能证明通知已发送或已收到。
不要根据其中一项推断另一项。已禁用的规则在回溯时段内仍可能有过触发记录,历史记录为空也不能证明规则当前处于非活动状态。
这条单行摘要是解释的依据。此处不要深入分析具体的触发记录;那属于 signoz-investigating-alerts。
步骤 4:构建说明
对用户最有用的是简洁明了的摘要。开头应给出能直接回答用户问题的 TL;DR,而不是 泛泛的告警摘要。TL;DR 是部分用户唯一会阅读的内容;如果把答案埋在固定模板之下,就会迫使他们 滚动查找自己原本想知道的信息。
根据用户的问题调整 TL;DR 的形式:
-
“这个告警有什么作用?”/“解释 X”:说明什么情况下会触发:
TL;DR:当
<condition>满足<scope>时触发,并通知<channel>。<fire-frequency line>。 -
“配置正确吗?”/“审核一下”/“有什么需要修改的吗?”:先给出结论和最重要的 1–3 项修改建议,而不是 描述触发条件:
TL;DR:配置总体合理,但建议:(1) 添加
alertOnAbsent(目前服务崩溃后不会触发告警);(2) 修正注解模板{{$topic}}→{{$labels.topic}}(无法 插值);(3) 将严重告警单独路由到 PagerDuty(目前两个级别 都路由到 Slack)。<fire-frequency line>。 -
“X 是如何工作的?”/“解释 count guard”:在任何铺垫之前,先用 1–2 句话说明机制:
TL;DR:count guard 是查询 A 中的
having: count() > 50子句:任何包含不超过 50 个 span 的 1 分钟时间桶都会在评估前被丢弃,因此低流量时段不会触发告警。 -
“阈值是多少?”/聚焦配置的问题:直接说明用户询问的确切内容:
TL;DR:阈值是 3 个标准差(z-score),不是原始速率值。由于采用每日季节性模式,模型会将每个小时与该小时的历史常态进行比较。
始终包含触发频率说明;如果状态不是默认值,还要说明 disabled 状态。这些信息能为各种 TL;DR 提供依据。但要把针对用户具体问题的回答放在最前面。
TL;DR 后,用分为以下四个部分的文字说明。没有有意义内容的部分可以跳过:空的严重性标签、默认通知设置和普通注释都不值得单独设标题。简短易读胜过例行公事般面面俱到;用户不会把它当作检查清单来读。
1. 监控内容:用一段简短的文字说明。结合信号类型(指标/日志/追踪/异常)、查询所衡量的内容和作用范围。将查询转述成运维人员易懂的语言;对于公式,说明每个子查询(A、B 等),并说明 F1(或实际触发的 selectedQueryName)的计算方式,例如“F1 = A × 100 / B → 错误百分比”。解读筛选运算符(= 等于、!= 不等于、IN/NOT IN、LIKE/ILIKE、CONTAINS、REGEXP、EXISTS/NOT EXISTS);列出 IN/NOT IN 的所有值,方便用户核对。说明每个 groupBy 维度及其实际效果(例如,service.name 表示“按服务分别触发”)。
对于异常规则(ruleType: anomaly_rule),明确说明阈值表示与学习到的模式相差的标准差,而非原始值;这是最常见的困惑点。说明 algorithm(基于 z-score 的 standard)、seasonality(每小时/每日/每周),以及较低/较高的目标如何改变敏感度(较低 → 噪声更多,较高 → 只检测极端偏差)。
2. 触发条件:用一段文字说明阈值和时间安排。根据以下映射将阈值规格转换成通俗易懂的表述:
op代码:1高于,2低于,3等于,4不等于,5高于或等于,6低于或等于,7超出边界(载荷中的outside_bounds)。matchType代码:1at_least_once(窗口内任意点),2all_the_times(整个窗口),3on_average(窗口平均值),4in_total(窗口总和),5last(最近的点)。
说明每个阈值级别的 name、target、targetUnit 和关联渠道。阈值始终使用 targetUnit 表示,而不是查询的原生单位(例如,“p99 超过 500 ms 时触发”,而不是“……超过 500 000 000 ns”)。如果设置了 recoveryTarget,请注明(即回滞);如果未设置,则说明数值接近边界时可能发生的告警抖动风险。将时间安排描述为“每隔 <frequency> 检查最近 <evalWindow> 的数据”,并说明 at_least_once 模式下单点超限即可触发,而 all_the_times 则要求整个窗口都满足条件。
3. 通知去向:解析实际路由,而不只是孤立地查看字段。如果 notificationSettings.usePolicy 为 true,请说明组织策略会匹配规则标签、静态标签或动态标签,并且会忽略阈值渠道。否则,v2 threshold_rule 或 promql_rule 仅通过各阈值层级的 channels 路由。如果某个层级没有渠道,请指出它未配置路由或配置有误;绝不能将顶层 preferredChannels 用作每个层级的备用渠道。v1 anomaly_rule 没有阈值或通知设置,因此其直接路由来自 preferredChannels。只有在获取的规则架构定义了该字段时,才将其视为路由配置,不能将它用作跨架构的备用项。如有需要,请从完整分页的 signoz_list_notification_channels 结果中解析名称。还要说明 notificationSettings.groupBy(分组)和 renotify(间隔 + 状态)。只有在 TL;DR 中路由已明确无歧义时,才跳过此部分。
4. 值得注意的问题:只指出非默认且值得用户关注的问题。不要罗列每个缺失字段;重点关注影响较大的问题:
- 关键信号缺少
alertOnAbsent:静默的数据丢失(服务崩溃、埋点失效)不会触发告警。对于生产级规则,务必指出这一点。 alertOnAbsent: true,但renotify.alertStates中没有nodata:无数据告警只会触发一次,之后便不再通知(很容易被忽略)。- 模板变量错误:
{{$topic}}不会被插值;正确形式是{{$labels.topic}}。标签键中的点会变成下划线(service.name→{{$labels.service_name}})。 - 有多个严重性层级,但规则缺少
labels.severity:这会导致基于标签的路由策略失效。这是常见的遗漏。 - 所有层级都路由到同一渠道:这会让分级阈值失去意义。
groupBy基数过高(例如pod.name×partition)→ 集群范围事件期间有引发通知风暴的风险。- 注释或描述文本与
matchType矛盾(例如,描述称“持续超过 5 分钟”,但matchType=at_least_once会在时间窗口内首次超限时触发)。 - 告警名称与筛选目标不符(例如名称写着“checkout”,但筛选条件针对的是
payments);请指出这一点。
如果以上问题都不适用,请省略此部分,不要凑内容。
如果用户只问“这个告警会做什么”,到这里就停止。审计(步骤 5)适用于“配置正确吗”/“审计一下”/“有什么需要更改吗”这类请求。
步骤 5:评估配置(仅在用户提出要求时)
用户可能会在询问说明的同时问“这个告警设置合理吗”。 仅在用户提出要求或请求中有所暗示时才进行评估(审计、审查、 “配置正确吗”)。评估必须以配置中的实际内容为依据:
- 阈值校准:是否适合该信号?请考虑服务的重要性和流量。
- matchType 是否合适:
at_least_once较敏感(可捕获瞬时情况);all_the_times较保守;on_average可平滑噪声。 - 时间窗口与频率:较短的窗口配合
at_least_once可能导致告警嘈杂。 较长的窗口可能延迟检测。 - 多级严重性:同时设置 warning 和 critical 阈值的告警 可实现分级响应。单一严重性级别的告警无法做到这一点。
- 通知路由:critical → 高紧急程度渠道(PagerDuty); warning → 低紧急程度渠道(Slack)。
- 缺少运行手册/说明:如果
annotations为空或 使用默认值,建议补充相关背景信息。 - 缺少数据监控:对于关键指标,如果未设置
alertOnAbsent: true,建议启用。 - GroupBy 基数:高基数的 groupBy 字段可能产生 许多独立的告警序列;请指出可能引发通知风暴的风险。
- 分组查询中的
limit/order:系统只会评估所选的前 N 个序列, 并按整个时间窗口内的排名排序。因此,排在 N 以外的序列永远不会被评估; 按降序排列的below规则可能会漏掉所有触发阈值的序列。除非目的就是监控前 N 项, 否则建议同时移除这两项。 - 筛选条件是否完整:对于包含明确值列表的
IN/NOT IN筛选条件, 请指出看起来不合适的值,或似乎应该包含但缺失的值。 - 触发频率与阈值:如果步骤 3 显示该告警每天触发多次(在 7d 窗口内超过 10 次/天), 阈值可能设置得过严;如果没有返回触发事件,而用户原本预期该告警会触发,阈值可能 设置得过宽,或查询可能有误。请将这些作为待检查的可能原因提出,并同时考虑 是否缺少保留的历史数据。
步骤 6:提供后续步骤
根据说明揭示的信息,最多提出 3 个后续意图,例如调查最近一次触发、 运行底层查询以查看当前值、调整阈值,或为覆盖缺口创建相关告警。酌情判断; 不要为了凑数而补足 3 个。
如果用户只是在查看信息(“这个告警有什么作用?”),且未表示有进一步意图, 则完全跳过后续建议。不提供后续建议,也好过提出不恰当的建议。
防护准则
- 先获取,再解释。 始终调用
signoz_get_alert。不要仅依据规则名称或列表响应进行解释。 - 始终获取触发历史。 一行频率摘要是解释的依据;即使告警已禁用,也要获取,因为已禁用的规则在回溯时间范围内仍可能有过触发记录。
- 将历史相关说法限定在返回的数据范围内。 历史记录为空,只能说明“最近 7d 未返回任何触发事件”,不能说“从未触发”。不要据此推断运行状况、阈值设置是否正确或通知是否送达。
- 解读,不要照搬。 将
op、matchType、筛选表达式和查询 JSON 转换为操作层面的描述。仅在用户提出要求时才展示原始 JSON。 - 解读每个子查询。 对于公式告警,说明每个构建器查询和公式。不要把公式一概说成“错误率”;要说明 A、B 和 F1 各自的计算内容。
- 以实际配置为依据。 不要根据告警名称进行猜测。如果名称中写着“checkout”,但筛选条件针对
payments,就要指出这一点。 - 默认不运行实时查询。 除非用户提出要求,否则不要运行告警的查询。解释的目的是理解规则,而不是检查当前数据。
- 分页列出告警。 在得出某个告警不存在的结论前,遍历
signoz_list_alert_rules的所有页面。 - SigNoz 评估模型。 SigNoz 使用
evalWindow、frequency和matchType,而不是 Prometheus 风格的for持续时间。不要用 Prometheus 术语描述其评估模型。 - 不超出范围。 针对特定触发时间段进行调查,应使用
signoz-investigating-alerts。修改告警应使用signoz_update_alert。
示例
用户:“解释一下我的结账错误率告警”
Agent:
-
signoz_list_alert_rules(分页)→ 找到 “High Error Rate - Checkout”,ID 为 42。 -
signoz_get_alert id=42→ 跟踪公式(A 错误 span / B 总 span × 100),单个严重级别阈值为 5%,op=1、matchType=1,通知渠道为pagerduty-oncall。 -
signoz_get_alert_history id=42 timeRange=7d state=firing order=desc→ 触发过 3 次,最近一次是 2 小时前。 -
回复:
简要说明:过去 5 分钟内,只要结账错误率(错误 span / 总 span) 任意时刻超过 5%,就会触发告警,并通知
pagerduty-oncall。过去 7 天触发过 3 次(最近一次是 2 小时前)。监控内容:
service.name = 'checkout'的跟踪数据。 查询 A 统计has_error = true的 span,查询 B 统计所有 span,F1 = A × 100 / B 得出错误百分比;告警会在 F1 达到条件时 触发。触发条件:
op=above、matchType=at_least_once,目标值 为 5%。每 1 分钟检查过去 5 分钟的数据;只要有一分钟的数值升高, 就会触发告警。值得注意:没有
recoveryTarget(数值在 5% 附近时可能反复触发和恢复);没有alertOnAbsent(结账服务中断导致流量归零时,此规则不会触发)。 -
接着询问:“需要我调查 2 小时前的那次触发吗?”
用户:“解释一下告警规则 17——配置得好吗?”
Agent:
-
signoz_get_alert id=17→ 指标system.cpu.utilization, 两个阈值(警告 80%、严重 90%)、matchType=3(on_average), 过滤条件deployment.environment.name = 'production',分组依据host.name。 -
signoz_get_alert_history id=17→ 已获取完整分页结果,过去 7 天内 未返回任何触发事件。 -
用户问的是“配置得好吗?”,因此简要说明先给出 结论,而非泛泛描述。随后提供解释和完整审查:
简要说明:整体配置合理(双阈值 +
on_average适用于 CPU), 但有两处需要改进:(1)没有alertOnAbsent(Agent 崩溃后会悄无声息地停止上报,此规则无法发现);(2)注释使用了默认值(添加 操作手册 URL 有助于值班人员处理)。过去 7 天内未返回任何触发事件。 仅凭这一点无法判断生产环境是否健康,也无法确定阈值是否过宽松,而且历史记录可能未保留完整的时间范围。监控内容:
deployment.environment.name = 'production'中的system.cpu.utilization,按host.name分组(每台主机分别触发)。触发条件:
op=above、matchType=on_average,两个级别 (警告 80%、严重 90%),时间窗口为 5 分钟。短暂峰值不会触发; 对 CPU 来说,采用平滑处理是恰当的。值得关注的问题:与简要说明中的改进项相同;除此之外均为默认设置。
-
提供后续步骤。
用户:“帮我理解这个异常检测告警”(告警 ID 88)
Agent:
-
signoz_get_alert id=88→ruleType: anomaly_rule、algorithm=standard(基于 z-score)、seasonality=daily、目标值 3,指标http.server.request.duration,范围为service.name = 'api-gateway'。 -
历史记录:过去 7 天触发过 1 次。
-
回复:
简要说明:当 api-gateway 的请求延迟偏离其学习到的每日模式超过 3 个标准差时就会触发(不是原始延迟值,也不是固定值)。 过去 7 天触发过一次。
监控内容:
service.name = 'api-gateway'的http.server.request.duration,通过 Z-score 检测异常,并采用 每日季节性:模型会学习每天每个小时的典型模式,因此只要高峰时段的延迟 符合该时段的历史正常水平,就不会误触发。触发条件:当 |Z-score| > 3 时触发,也就是数值偏离预期模式超过 3 个标准差。目标值越低,灵敏度越高(噪声也越多);目标值越高,则只会检测到极端 偏差。阈值的单位不是秒或毫秒。
-
主动提出调查最近一次触发。