mcpField
S
signoz-explaining-alerts

signoz-explaining-alerts

github.com/signoz云与 DevOps19344 次安装5 天前更新
代码仓库

关于 signoz-explaining-alerts

signoz-explaining-alerts 是解读现有 SigNoz 告警配置的只读技能,适合需要了解告警监控信号、触发条件和通知路由的用户。它将规则配置转为运维说明,并附上一行触发频率信息,不调查具体事件。

主要功能

  1. 01读取告警完整配置
  2. 02说明监控信号、范围与阈值
  3. 03解释评估窗口和触发时序
  4. 04解析通知渠道与路由规则
  5. 05汇总近 7 天触发频率

适用场景

  1. 01确认现有告警监控的内容与阈值
  2. 02审查告警条件和通知配置
  3. 03将告警 JSON 转为运维说明
  4. 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.json
evals/files/
empty-alert-history.json
grouped-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、近期上下文或模糊匹配

如果输入缺失或不明确,此技能会尽力处理(并非严格要求;只读操作出错后很容易恢复):

  1. 调用 signoz_list_alert_rules,遍历所有分页,并查找名称最接近的规则。
  2. 在回复中说明你的解读: “我将你的请求理解为告警 ‘High Error Rate - Checkout’(id 42)。 如果你指的是其他告警,请告诉我名称或 id。”
  3. 继续进行说明。用户之后可以纠正。

工作流

步骤 1:确定告警

如果用户提供了规则 ID(UUID 或旧版数字 ID),请跳至步骤 2。 否则:

  1. 调用 signoz_list_alert_rules,并遍历所有分页: pagination.hasMore 为 true 时,表示列表尚未遍历完。
  2. 按名称匹配(不区分大小写的子串)。如果有多个匹配项, 列出候选项并询问用户要选择哪一个(交互模式),或选择最接近的项并标明假设(自主模式)。
步骤 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 代码:1 at_least_once(窗口内任意点),2 all_the_times(整个窗口),3 on_average(窗口平均值),4 in_total(窗口总和),5 last(最近的点)。

说明每个阈值级别的 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:

  1. signoz_list_alert_rules(分页)→ 找到 “High Error Rate - Checkout”,ID 为 42。

  2. signoz_get_alert id=42 → 跟踪公式(A 错误 span / B 总 span × 100),单个严重级别阈值为 5%,op=1、 matchType=1,通知渠道为 pagerduty-oncall。

  3. signoz_get_alert_history id=42 timeRange=7d state=firing order=desc → 触发过 3 次,最近一次是 2 小时前。

  4. 回复:

    简要说明:过去 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(结账服务中断导致流量归零时,此规则不会触发)。

  5. 接着询问:“需要我调查 2 小时前的那次触发吗?”


用户:“解释一下告警规则 17——配置得好吗?”

Agent:

  1. signoz_get_alert id=17 → 指标 system.cpu.utilization, 两个阈值(警告 80%、严重 90%)、matchType=3(on_average), 过滤条件 deployment.environment.name = 'production',分组依据 host.name。

  2. signoz_get_alert_history id=17 → 已获取完整分页结果,过去 7 天内 未返回任何触发事件。

  3. 用户问的是“配置得好吗?”,因此简要说明先给出 结论,而非泛泛描述。随后提供解释和完整审查:

    简要说明:整体配置合理(双阈值 + 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 来说,采用平滑处理是恰当的。

    值得关注的问题:与简要说明中的改进项相同;除此之外均为默认设置。

  4. 提供后续步骤。


用户:“帮我理解这个异常检测告警”(告警 ID 88)

Agent:

  1. signoz_get_alert id=88 → ruleType: anomaly_rule、 algorithm=standard(基于 z-score)、seasonality=daily、目标值 3,指标 http.server.request.duration,范围为 service.name = 'api-gateway'。

  2. 历史记录:过去 7 天触发过 1 次。

  3. 回复:

    简要说明:当 api-gateway 的请求延迟偏离其学习到的每日模式超过 3 个标准差时就会触发(不是原始延迟值,也不是固定值)。 过去 7 天触发过一次。

    监控内容:service.name = 'api-gateway' 的 http.server.request.duration,通过 Z-score 检测异常,并采用 每日季节性:模型会学习每天每个小时的典型模式,因此只要高峰时段的延迟 符合该时段的历史正常水平,就不会误触发。

    触发条件:当 |Z-score| > 3 时触发,也就是数值偏离预期模式超过 3 个标准差。目标值越低,灵敏度越高(噪声也越多);目标值越高,则只会检测到极端 偏差。阈值的单位不是秒或毫秒。

  4. 主动提出调查最近一次触发。

评论

支持 Markdown