mcpField
K
kubesense-alerts

kubesense-alerts

github.com/kubesense-ai云与 DevOps3114 次安装4 天前更新
代码仓库

关于 kubesense-alerts

用于通过读取和创建流程处理 KubeSense 告警的 Skill。它区分正在触发的告警实例、规则定义和历史记录,并指导通过经过验证的 MCP 工具或可审核的导入 JSON 创建规则。

主要功能

  1. 01查看触发中的告警和规则定义
  2. 02检查告警详情与历史
  3. 03查找以往告警调查
  4. 04通过验证创建单条规则
  5. 05验证或准备导入 JSON

适用场景

  1. 01调查触发告警及其历史
  2. 02判断告警是长期反复还是新出现
  3. 03通过 MCP 工具创建单条告警规则
  4. 04准备或验证批量告警导入

MCP 相关

指导 MCP 客户端使用 KubeSense 告警工具查询告警、规则、详情、历史、通知渠道和调查记录。还介绍经过验证的 `create-alert` 与 `validate-alert-json` 工具。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kubesense-ai/kubesense-mcp-skills --skill kubesense-alerts

安装后在 Claude Code 中输入/kubesense-alerts确认已加载。

附带文件references/datadog-migration.mdreferences/import-json.md

详细介绍

KubeSense Alerts

两项不同的任务,别混淆:

  • 读取告警——当前有哪些告警正在触发、哪些超出阈值、是否长期存在。纯 MCP 工具调用。
  • 创建告警——使用 create-alert MCP 工具(经过验证,创建一条规则),或 导入 JSON(可在 UI 中审核,支持批量导入)。

路由

用户在询问……执行此操作
“现在有哪些告警正在触发?”list-active-alerts
“有哪些告警规则/我创建过告警吗?”list-alert-rules(对于 created_by,加上 get-current-user)
“这个告警触发了——哪里出问题了?”针对对应范围调用 get-alert-details,然后使用 kubesense-infra 查看变更和基础设施故障
“这是反复触发还是新出现的?”get-alert-history
“以前有人查明过这个问题的根因吗?”find-investigation-for-alert
“创建一条在……时触发的告警”(一条规则,由 Agent 应用)create-alert MCP 工具
“给我……的告警 JSON”/多条规则/迁移导入 JSON → references/import-json.md
“迁移这些 Datadog 监控器”references/datadog-migration.md
“为什么触发了告警却没人收到通知?”先检查通知渠道的频率,再确认是否有维护时段覆盖
“把这些规则放进列表/文件夹”只能在 UI 中分组——没有 MCP 接口,应如实说明,不要猜测
你手动编写了规则 JSON,想要检查交给用户前先运行 validate-alert-json
“错误预算”“燃烧率”“是否达到了 99.9%”使用 kubesense-slo——燃烧率规则由 SLO 的 alert_types 生成,而不是手动编写

读取告警

工具范围
list-active-alerts当前正在触发的原生存储中的时间序列,并与规则元数据关联。筛选条件:from_time/to_time、fingerprint、acknowledged、assignee、include_resolved。
list-alerts外部 Alertmanager——仅包含标签,不含规则配置。数据来源不同;除非明确需要查看 Alertmanager 状态或静默规则,否则使用 list-active-alerts。
list-alert-rules规则定义,包括已禁用和未触发的规则。按创建时间从新到旧排列。筛选条件:enabled、state、severity、query_type、search、created_by。
get-alert-details某条规则的完整配置(query_config、条件、阈值)以及其触发实例。调查时从这里开始。
get-alert-history触发/已解决状态变更,按时间从新到旧排列——用于判断问题是长期存在还是新出现。
find-investigation-for-alert最近一次已结束的 AI 调查及其根因。found=false 是正常情况,不代表错误。
list-notification-channels仅列出已启用的渠道:id、name、type。

检查手动编写的规则 JSON

每当你自行组装规则文档——导入 JSON、迁移后的 Datadog 监控器或编辑过的导出文件——都要在交给用户前通过 validate-alert-json 验证。该工具不会存储任何内容,并会一次性报告所有问题:

# valid=false findings=2
path                        rule                 message
/query_config/0/queryMode   shape                value must be one of 'builder', 'code'
/metric_query_label         metric_query_label   names query "A", but the rule's queries are labelled "B"

每个 path 都是指向待修复值的 JSON Pointer。重复验证,直到 valid=true。

它验证的是线缆文档——包含 query_config、 threshold_operator 和 frequency_type 的导出/导入格式。它不用于 create-alert 的参数; 该工具会验证自己的输入,并报告相同的问题。

重要

“我创建了哪些告警?”——调用 get-current-user,并将返回的**username**作为 created_by 传入。存储的创建者字段是用户名;电子邮件永远无法匹配,而且这两个值经常不同。

指纹用于标识某条规则的一个触发时间序列(一个命名空间/Pod/工作负载)。 传入指纹可将 get-alert-details/get-alert-history 的结果限定为该实例;省略则查询整条规则。

警报可以离开「正在触发」状态,而无需恢复

有两个表示人为操作的动词用于处于触发状态的序列,它们的含义不同:

表示是否仍处于「正在触发」状态通知
确认「我正在处理」是双重抑制 — 见下文
解决「已处理」否仅针对此次违规进行抑制

解决操作会关闭当前违规;序列一旦不再违规,引擎就会清除标记,因此之后真正再次违规时会照常发送通知。这不是静音。

确认操作通过两种独立机制抑制通知:最长 7 天的 Alertmanager 静默,以及引擎端检查,在数据库标记存在时完全跳过发送。**该标记没有过期时间。**绝不要告诉别人通知会在一周后自动恢复——除非警报解决、状态反复变化,或有人取消确认,否则通知不会恢复。

重要

MCP 输出中的任何内容都无法将这两种情况与真正恢复区分开来。手动解决的序列只会新增一个 ends_at,然后从 list-active-alerts 中消失,这与已恢复的序列完全一样。因此,切勿仅凭 include_resolved 就断定「它在 14:02 恢复了」——应说警报已关闭;如果用户询问已知故障为何变成正常状态,应引导他们查看警报自己的页面,该页面可以区分这两种情况。

创建警报 — 选择哪种方式?

create-alert MCP 工具导入 JSON
每次调用的规则数一个一个或多个(批量)
字段名称fields/group_by_fields 会自动转换——先尝试目录标签,再尝试存储名称。where 则严格要求使用目录标签必须完全正确,使用引擎自己的术语
验证提前验证,并给出精确错误,便于重试导入时由服务器验证
应用者Agent(写入工具,需要审批)用户,在 UI 中操作
最适合用户想立即创建的单条规则便于审核的输出、多条规则、迁移

单条规则优先使用 create-alert——它会根据引擎自己的验证器解析字段名称,因此不会生成引擎拒绝的名称。当用户要求提供「JSON」、想在创建前先审核,或要迁移多个监控项时,优先使用导入 JSON。

create-alert
{
  "signal": "traces",
  "name": "Checkout p95 latency high",
  "description": "p95 above 500ms for 5 minutes",
  "where": "service = checkout",
  "value_operation": "p95",
  "fields": [ { "field": "duration" } ],
  "group_by_fields": [ { "field": "workload" } ],
  "threshold_operator": "greater_than",
  "threshold_value": 500000000,
  "severity": "warning",
  "notification_channels": [1],
  "time_window": "5m",
  "evaluation_interval": "1m"
}
  • signal:metrics | logs | traces。
  • metrics → 提供 promql。logs/traces → 提供 where(search-logs 语法)+ value_operation;若不是 row_count,还需提供 fields。
  • 这里的 value_operation 比查询工具支持的范围更窄:row_count、unique_count、 avg、sum、min、max — 不支持百分位数。若要创建 p95 延迟规则,请使用导入 JSON。
  • 必填项:name、threshold_operator、threshold_value、notification_channels。
  • 默认值:severity=warning、threshold_frequency=at_least_once、 evaluation_interval=1m、time_window=5m。
  • 这里的 threshold_operator 也接受 above/below(导入 JSON 不接受)。构建规则前会先将它们规范化 — above 会存储为 greater_than,below 会存储为 less_than — 因此读取规则时会返回规范值,而不是你发送的值。若已知规范名称,请优先使用。
多个查询与公式

比率——错误率、占总量的比例、一个查询除以另一个查询——不再受导入路径限制。传入 queries 而不是扁平的单查询字段,并为最后一项提供 expression:

{
  "signal": "traces",
  "name": "Checkout 5xx rate above 5%",
  "queries": [
    {"label": "A", "where": "status_code LIKE \"5__\"", "value_operation": "row_count",
     "group_by_fields": [{"field": "workload"}]},
    {"label": "B", "where": "", "value_operation": "row_count",
     "group_by_fields": [{"field": "workload"}]},
    {"label": "C", "expression": "A / B * 100"}
  ],
  "threshold_operator": "greater_than",
  "threshold_value": 5,
  "notification_channels": [1]
}
  • queries 和扁平字段(promql、where、value_operation、fields、 group_by_fields)互斥——传入 queries,所有内容都放在其中。
  • label 默认按位置依次为 A、B、C,且只能使用字母;最多 26 个查询。
  • 公式条目只能包含 expression,且只能引用排在它前面的查询。
  • 每个非公式查询都针对规则唯一的 signal 运行——一条规则不能混用日志与指标。
  • 分组输入必须按相同字段分组。 引擎会按这些键匹配序列,因此两个输入若分组方式不同,其键就无法匹配。 create-alert 会提前拒绝这类规则,并指出两种分组方式——你无法先创建规则再发现问题。
  • 未分组的输入不受此限制,而且这是有意设计的。 单个未分组序列会广播到已分组序列,这正是“此工作负载占总量的比例”:将 A 按 workload 分组,让 B 保持未分组,阈值设为 A / B * 100。
  • 通过导入 JSON引入同样的分组不匹配时,不会进行检查——没有任何东西会拒绝它,连接操作不会产生结果,而空结果会被视为正常。规则就这样悄无声息。这正是通过 create-alert 构建多查询规则的理由。
  • 阈值应用于公式。若有多个查询且没有公式,请在 threshold_query 中指定要设阈值的查询。
  • 在 queries 中接受 "where": ""——分母为“全部”正是其用途——而未加筛选的单查询规则则会被拒绝。

重要

where 使用目录标签,且只能使用目录标签。 使用 status_code,而不是 return_code;使用 instance,而不是 pod_name。若填写存储列名,则会被拒绝:

field "return_code" is a storage column; use the catalog label "status_code" instead

这与下文所述的词汇正好相反;下文规定的是已存储和导入的规则——在那种情况下,return_code 正确,而 service 不正确。同一条规则会根据其进入引擎的方式采用两套词汇。fields 和 group_by_fields 更宽容:create-alert 会先尝试目录标签,再尝试存储名称,因此两者在此处都有效。where 则不会进行转换。

工具自身描述中的示例就有这个错误——它在 where 中填写了 return_code,会被同一工具背后的验证器拒绝。不要照抄。

此处仍无法使用百分位数:value_operation 没有 p95,因此 p95 延迟规则仍需通过导入 JSON 创建。

labels 会为规则及其触发的每条告警附加额外标签。这些标签用于路由,也会在 {{placeholders}} 中解析——见下文。

警告

先调用 list-notification-channels。 notification_channels 为必填项,且必须包含真实的通道 ID。不存在的 ID 会直接导致规则创建失败。如果没有任何通道,请告知用户必须在设置中创建通道——不要悄悄创建规则,因为它会触发告警,却无人收到通知。

这是一个写入工具。调用前,请明确说明你将要创建的内容。

遇到拒绝时

规则存储前会根据线协议约定进行检查,因此拒绝时会指出确切字段:

invalid alert: /query_config/0/queryMode: value must be one of 'builder', 'code'

每条发现都包含指向工具构建的规则的 JSON Pointer,以及相应的问题。修正后再次调用——这次往返比看起来更省事,也远比创建一条存储成功、随后却什么也不评估的规则划算。

两类失败的含义不同。invalid alert: … 表示需要由你修正。failed to create alert rule: … 表示服务器问题——应报告,而不是重试。

字段名称——不同的词汇表

重要

告警引擎接受的字段集与查询工具不同。MCP 查询目录标签(type、instance、service、node)并非在此处全部有效。这里涉及三套词汇表:

  1. 查询工具(analyze-logs、search-traces)——仅目录标签。
  2. 告警分组字段/值字段——标签与存储名称的混合,且会严格验证。
  3. 告警筛选键——分组字段集合,外加额外的存储名称覆盖项。
日志——分组字段和值字段(19 个,精确列表)
instance  workload  namespace  cluster  pod  container  node
pod_name  container_name  level  format  host  body_length
region  app_version  customer_identifier  source
service  env_type

请注意,两种写法都有效:pod 和 pod_name、container 和 container_name、node 和 host、instance。此处的严重性字段是 level,而不是查询工具中的 type。

service 和 env_type 最近才开始被接受(KUBE-2638)。日志目录从一开始就在“分组依据”下拉菜单中提供了这两项,但引擎却拒绝它们,因此选择任一项都会导致规则创建失败。如果遇到仍拒绝它们的安装版本,说明它早于此修复——请改为按 workload 分组。

日志筛选键 = 上述 19 项 加上 env、node_name 和 body。

说明

body 是筛选键,不是维度。 系统接受 raw_filters: {"body": ["timeout"]};但仍会拒绝将 body 用作分组字段或值字段,这是有意为之——按消息文本分组会导致每个不同的行都生成一个序列,而且没有可聚合的内容。body_length 是数值字段,两者并不相同。

根据其存储方式,会产生两种影响。筛选 body 会强制使用原始表(汇总表没有此列),因此每次评估都需要进行完整扫描——在繁忙的租户中将其用于 24h 时间窗口前,值得明确说明这一点。此外,针对 body 的裸 ILIKE 会被重写为令牌搜索,因为在 SQL 中它会进行精确匹配,无法匹配任何实际日志行。令牌搜索不区分大小写,并按非字母数字字符拆分,因此 hasAnyTokens 出现“误报”是索引固有的行为,并非缺陷——请预期会出现这种情况,不要将其报告为告警错误。

不接受 pattern_id:它只存在于汇总表中,因此使用它的规则会在查询回退到原始表时失效。

跟踪——分组字段和值字段(40 个,精确列表)

28 个目录标签:

status  protocol  source  role  status_code  namespace  method
workload  container  region  app_version  resource  server  client
server_namespace  client_namespace  node  operation_name
partner_cluster  customer_identifier  duration  duration_quantile
duration_avg  pod  instance  cluster  return_code  app_service

……再加上 12 个存储名称,这才是 Web 应用实际为跟踪分组保存的名称:

container_name  pod_name  node_name  kind  subtype  protocol_type
clustered_resource  perspective_namespace  perspective_workload
env_type  app_db  issue_reason

过去,分组只接受第一个列表,因此 UI 提供的 27 个可分组跟踪字段中有 12 个在保存时会遭拒——这也是 KUBE-2638 修复的内容,也解释了为什么现在接受 issue_reason,而旧说明中却称其不接受。

跟踪筛选键 = 上述 40 项 加上 is_external、app_name、partner_namespace、partner_workload。

因此,对于跟踪,目录名称和存储名称都可用作筛选键和分组字段(status_code 和 return_code、resource 和 clustered_resource、method 和 subtype)。

警告

跟踪不接受 service——请使用 app_service。 查询工具首选的标签在告警引擎的跟踪侧不存在,拒绝消息也明确说明了这一点。(日志则相反:它们接受 service。)对于日志,node_name 仅可用于筛选——作为维度时,该列名为 host。

标记为 is_attribute: true 的字段会跳过验证;筛选键为空、为 advanced_query 或以 @ 开头时也会跳过验证。

错误字段名会发生什么

导入时,规则会被拒绝,并返回 400 和针对每个字段的消息:

query A (traces): group-by field "issue_reason" is not accepted by the alert engine
and would freeze the rule — not supported by the alert engine

设置这道防护,是为了避免它所阻止的评估时行为:引擎无法解析的名称会导致每次评估都出错,随后引擎会保留规则的当前状态。新规则会悄无声息地永远不触发;已经触发的规则则会冻结——永远无法恢复,而且修改其阈值也没有效果,因为查询会在检查阈值之前出错。

导入时的允许列表是手动维护的引擎允许列表副本,没有自动漂移检查,因此请注意,验证通过但始终不触发的规则可能遇到了这个问题,并在条件图表中确认。

会悄然改变规则的陷阱

陷阱后果
groupBy 条目缺少 field、type 或 is_attribute整个 groupBy 会被清空——规则会作为一个全局序列触发,而不是按标签分别触发
数值型 value_operation(例如 p95)缺少或包含错误的 fields会悄然降级为 row_count——延迟规则变成计数规则
数值运算的 fields[].type 不完全等于 "float"同样会降级
unit: "ns" / "percent" / "short"都是无效值——会悄然变成 auto。请使用 nanoseconds、percentage、number
仅设置 frequency_type: "always"会悄然降级为 at_least_once——还必须发送 threshold_frequency: "always"
单规则导入时设置 notification_channel_ids: []编辑器要求至少有 1 个频道;用户无法点击创建
手动编写的 unified_filter 块导入时绝不会读取——会悄然丢弃
advanced_query 与其他 raw_filters 键同时出现advanced_query 具有排他性;其他所有筛选键都会被丢弃
query_config 条目中包含 label 键会被忽略——标签按位置绑定(索引 0 → A,1 → B)
路由到 pagerduty / jsm / datadog_oncall 的规则设置 send_resolved: false会被拒绝并发出警告。 已恢复的负载会在这些系统中关闭事件,因此抑制它会导致事件永远保持打开状态
删除规则后,用相同名称重新创建规则来“恢复”它删除是软删除——旧规则会保留其历史记录,并继续保持删除状态。你会得到一个没有过往事件的新规则

请务必告知用户在点击创建之前,先在导入编辑器的条件图表中确认各项值。

通知行为

触发中的规则实际多久通知一次,主要由频道而不是规则决定。

设置所在位置作用
group_interval频道Alertmanager 多快会重新检查内容发生变化的组。默认值较短,而且分组规则的内容会随着序列的出现和消失而不断变化——通常,这才是“为什么几乎每次评估都会通知?”的答案,而不是 repeat_interval。
repeat_interval频道内容未变化的触发中组多久重新通知一次。只有在 group_interval 不再触发后,它才会起作用。通常以小时计。
send_resolved频道频道是否会通知恢复情况。
send_resolved规则按规则覆盖频道设置。不设置则继承——在此功能出现之前,所有规则都是如此。

有意不开放 group_wait 和 group_by。设置错误会导致你收不到提醒,而不只是减少提醒次数。

规则上的 send_resolved: false

适用于仅需触发并在恢复时保持静默的信息性规则,例如“出现了新的账本”“部署已开始”,且无需为其单独创建频道。关于哪些情况下会拒绝该设置,请参阅“陷阱”表。

send_count 不是通知次数

每次实际发送的评估都会递增一次,因此它大致等于触发持续时间 ÷ evaluation_interval。在 1m 规则上的两天告警会显示约 3000。绝不要把它说成“向某人发送了 3000 次通知”——实际通知到人的次数受上文所述渠道频率限制。

还有两点会让它无法准确衡量持续时间:

  • **已确认的评估不会计数。**抑制检查会在发送前返回,而递增计数器的 upsert 是发送流程的一部分——因此只要有人保持确认状态,这个数字就会停滞。
  • **它不是按触发事件分别计数。**该行以指纹为键,重新触发会重置 starts_at,但会累加 send_count。一个打开又关闭过五次的序列,计数会累加这五次的总和。
确认

确认会停止针对该次触发实例的通知,而告警仍会显示为 Firing Now——它表示“我正在处理”,而不是“问题已经结束”。取消确认会使静默失效。

它通过两种彼此独立的机制进行抑制,且只有一种有截止时间:最长 7 天的 Alertmanager 静默,以及引擎端的检查——只要数据库中的 acknowledged 标记处于设置状态,就会直接跳过发送。此标记永不过期。

因此,不要告诉任何人分页通知会在一周后自动恢复。只有在序列解决、状态反复变化或有人取消确认时,通知才会恢复——下次实际触发时的 upsert 会清除 acknowledged,以及该次已结束事件的其他信息。

Trace 延迟阈值的单位是纳秒

告警引擎读取的 Trace duration 单位是纳秒,汇总百分位数也一样。

用户描述threshold_value
100ms100000000
250ms250000000
500ms500000000
1s1000000000

ns = ms × 1_000_000。设置 "unit": "nanoseconds"。

说明

这与查询工具不同,后者的 duration WHERE 筛选条件以毫秒表示。告警:纳秒。查询:毫秒。参见 kubesense-traces。

产品自带的 type-tracing 起始模板使用 threshold: 500,描述中写着“ms”——这实际表示 500 纳秒。不要照搬。

文本和模式筛选器

要匹配单个正文内容,请直接按 body 筛选——raw_filters: {"body": ["timeout"]}——并查看日志字段列表下方的说明,了解其代价和匹配方式。

对于简单前缀运算符无法表达的条件——例如对两个短语进行 OR 匹配、混合匹配正文文本与另一个字段,或匹配状态码类别——unified_filter 无法通过导入使用,唯一可行的方法是使用保留键 advanced_query 存放 WHERE 字符串:

"raw_filters": {
  "advanced_query": ["body SUBSTR_ILIKE \"timeout\" OR body SUBSTR_ILIKE \"connection refused\""]
}

状态码类别也是如此——return_code LIKE "5__"(_ = 一个字符:4__ = 4xx,40_ = 40x)。请记住,advanced_query 会替换所有其他筛选器键,因此要将所有条件合并到同一个字符串中。

raw_filters 的值也支持前缀运算符,可用于简单情况:

前缀操作示例
无IN{"level": ["ERROR"]}
-NOT IN{"return_code": ["-200"]}
> < >= <=比较{"duration": [">500000000"]}

由于这些筛选器格式较为繁琐,而且筛选器绑定失败时会静默无效(此时规则会匹配所有内容,而非什么都不匹配),可靠的做法是:在 Explorer 的高级查询编辑器中构建条件,在告警编辑器中添加该条件,在条件图表上验证,然后导出。

名称或描述中的占位符

规则名称或描述中的 {{...}} 会按每个触发序列展开,因此一条规则会为每个分组生成一个标题各不相同的告警。占位符有两个命名空间。

规则自身的标签——其分组键以及携带的任何 labels。每个占位符按以下顺序解析:

  1. 标签键本身。 精确匹配始终优先。

  2. UI 标签别名,且仅当该列位于此告警的标签中时才使用。Group By 下拉菜单中有 16 个字段,它们在界面中显示为一个名称,存储时使用另一个名称:

    service→app_service   domain→cluster        resource→clustered_resource
    container→container_name  node→host         instance→pod_name
    type→level            status_code→return_code  method→subtype
    protocol→protocol_type  role→kind           reason→issue_reason
    primary_workload→perspective_workload   primary_namespace→perspective_namespace
    associate_workload→partner_workload     associate_namespace→partner_namespace
    

    规则 1 可确保解析没有歧义:service 是日志自身的 service 和 Trace 的 app_service 对应的 UI 标签,每条规则都会根据自身的列进行解析。别名不会凭空生成值——如果两者都未用于分组,{{domain}} 就会保持原样,这样拼写错误会显现出来,而不会被悄悄渲染为空。

  3. 与属性同名。 按属性 topic 分组时,{{topic}} 会解析为该属性,即使存储的键是 @topic。

{{@topic}} 也可以使用;当存在同名的普通标签时,应使用这种形式:如果 topic 和 @topic 都存在,{{topic}} 会返回列(规则 1),只有 {{@topic}} 会返回属性。经过消歧的分组键也会在占位符中保留其后缀——同一属性按类型或位置分组两次时,分别使用 {{status:float}} 和 {{status#0}}。

告警自身的事实信息使用保留的 Alert. 前缀:

{{Alert.status}}  {{Alert.value}}  {{Alert.threshold}}  {{Alert.thresholdOperator}}
{{Alert.severity}}  {{Alert.timeWindow}}  {{Alert.frequency}}
{{Alert.startedAt}}  {{Alert.startsAt}}  {{Alert.endsAt}}
{{Alert.evaluatedFrom}}  {{Alert.evaluatedTo}}
  • 前缀不可省略,也不是装饰。裸写的 {{status}} 会优先解析规则的标签 status,因此对于按名为 status 的属性分组的规则,它显示的是“firing”,而不是属性值。这个命名空间消除了冲突——任何分组都无法生成以 Alert. 开头的键。
  • {{Alert.status}} 会渲染为 firing、resolved 或 no_data——这些是小写标记,不是显示文本。
  • startedAt/endsAt 界定事件持续时间;evaluatedFrom/evaluatedTo 界定查询时间范围。 如果规则在 5 分钟的窗口内持续触发 3 小时,事件持续时间就是 3 小时,窗口则是 5 分钟。因此,使用事件持续时间构建的“查看是什么触发了此告警”链接,会展示 3 小时的数据来解释 5 分钟内的情况。请使用 evaluated* 构建链接。
  • 缺失的读数会渲染为 no_value。 对于未测得任何值的序列,{{Alert.value}} 是唯一会显示标记、而不是保持原样的事实信息,因为作者会将它放入告警名称中,而原样发送 {{Alert.value}} 会直接出现在 Slack 消息里。它不会被渲染为 0.00,因为那是有效的测量值。
  • 缺失的时间会保持原样。 对于正在触发的告警,{{Alert.endsAt}} 会渲染为它本身,而不是 0001-01-01;当窗口未知时,evaluatedFrom/evaluatedTo 也一样。

维护窗口

采用 Datadog 风格的计划停机:在一段时间内,某个范围内的窗口会静默告警通知;对于部署了 alert_rule_engine#71 的版本,也会同时静默匹配的工作流触发器,包括触发和恢复两种情况。遥测数据仍会传入,规则仍会评估,告警仍会触发和恢复,历史记录仍会保存,SLO 预算仍会消耗。

理解这一点很重要:被静默的告警在 list-active-alerts 和 get-alert-history 中看起来完全正常。如果用户问为什么触发的告警没有通知任何人,维护窗口可能是原因之一,而没有 MCP 工具能查询维护窗口——请如实说明,并引导用户前往 Alerts → Maintenance Windows,而不是根据告警自身的数据猜测。

  • 范围可以是规则 ID 和/或标签匹配器,采用 Alertmanager 的语义:正则表达式必须匹配整个字符串,不存在的标签按空值处理。
  • 除非明确设置 scope_all,否则空范围不会静默任何内容——空白表单无法屏蔽整个系统。
  • 计划可以是单次、每日或每周,按墙上时钟时间和 IANA 时区存储,因此“每晚 01:00”在夏令时变更后仍是 01:00。
  • 抑制通过 Alertmanager 的静默规则实现,而不是让引擎停止运行。停止运行会触发 resolve_timeout,导致误报一切正常。

导入 JSON

有关完整的顶层架构、query_config 格式、所有枚举、批量导入,以及指标/日志/链路/公式规则的已验证可用示例,请参阅 references/import-json.md。

要点:

  • 使用扁平字段(threshold_operator、threshold_value)和普通时长字符串("5m",而不是 *_prometheus_format)——包括 breach_counting_window,这是导入时读取的字段名;POST 请求体和导出内容使用的是 breach_counting_window_prometheus_format。请同时发送这两个字段,绝不能省略:单独使用 _prometheus_format 字段名会被忽略,规则会静默地采用5 分钟。这适用于 always 和 more_than_once。
  • 一条规则对应一个 JSON 对象。多条规则对应一个 JSON 数组,可通过批量导入并进行试运行审核。绝不要为每条规则分别输出代码片段。
  • 导入时会忽略 enabled 和 query_type——服务器会将规则硬编码为启用状态,并根据第一个查询的 selectedMode 推导类型。
  • 通过 Alerts → Alert Rules → Import JSON → 审核 → Create 应用。在用户确认之前,不会写入任何内容。

绝不要声称告警已通过导入流程创建——需要由用户导入并确认。

先发现,再操作

绝不要杜撰指标名称、字段或频道 ID。

你需要调用
指标名称get-available-metrics → get-metric-labels
日志/链路字段名称和值get-trace-or-log-fields
频道 IDlist-notification-channels
你自己的用户名get-current-user

如果遇到不熟悉的规则格式,请让用户导出一条类似的现有规则并进行修改——这样可以确保 query_config 格式有效。

即使没有 MCP,你仍可根据上述允许列表生成日志/链路规则(这些是规范来源,不是猜测);但不得杜撰 PromQL 指标名称——这些名称因集群而异。请询问用户,或让他们导出一条参考规则。

规则

  1. 发出规则前,先发现每个指标、字段和频道 ID。
  2. 使用告警引擎的字段列表,而不是查询工具的目录标签。对于 trace,使用 level 而不是 type;使用 app_service 而不是 service。
  3. 首先调用 list-notification-channels。绝不编造 ID;[] 会阻止单条规则导入。
  4. Trace 延迟阈值使用纳秒,unit: "nanoseconds"。
  5. 每个 groupBy 条目都要包含全部三个键,否则分组会被静默丢弃。
  6. 数值型 value_operation 需要 fields 的 type: "float",否则会退化为 row_count。
  7. unit 必须是有效的格式化器值——nanoseconds、milliseconds、percentage、 bytes、CPU、number、raw。
  8. 文本/类别筛选条件必须放在 raw_filters.advanced_query 中,绝不能放在 unified_filter 中——advanced_query 会取代所有其他筛选键。
  9. 查询标签是按位置对应的;metric_query_label 用于指定要设置阈值的查询 (单个查询 → A;公式 → 公式的标签)。
  10. 一条规则 → 对象;多条规则 → 一个数组。无论哪种情况,都只用一个代码块。
  11. 只有当指标消失本身就是事件(仪表盘/心跳)时,才使用 no_data_state: "firing"。计数/速率/变化规则绝不能使用——健康时间窗口会返回空结果,而不是 0,因此在数值为 0 时使用 firing 会误触发。使用 normal。
  12. more_than_once 需要设置 breaches_count(≥ 2);always 也需要设置 threshold_frequency。这三种频率都会读取 breach_counting_window—— 对于 more_than_once,在该时间窗口内统计违规次数;对于 always,检查条件在该时间窗口内是否持续成立;对于 at_least_once,在该时间窗口内检查是否解除。若未设置该值,引擎会回退到 time_window,但导入根本不会执行到这一步:编辑器会将空字段默认设为5 分钟。请传入该值。
  13. name 中的 {{field}} 占位符会根据每个触发序列,解析为一个分组键或规则标签,例如按 workload 分组 → "High latency {{workload}}"。找不到匹配项的占位符会保持原样,这可以帮助你发现拼写错误。告警自身的属性需要加上 Alert. 前缀——使用 {{Alert.value}},而不是 {{value}}。
  14. 提醒用户在创建前查看条件图表;除非 create-alert 确实返回了 ID,否则绝不要声称规则已创建。

评论

支持 Markdown