mcpField
P
pagerduty-oncall

pagerduty-oncall

github.com/delexw云与 DevOps257 次安装31 周前更新
代码仓库

关于 pagerduty-oncall

pagerduty-oncall 是通过 pd CLI 调查 PagerDuty 事件并生成结构化分析报告的 skill。它支持事件列表和单个事件调查,并可按升级策略与时间范围筛选。

主要功能

  1. 01列出事件或调查指定事件
  2. 02按升级策略和时间筛选
  3. 03收集事件日志、备注和分析数据
  4. 04生成结构化事件报告

适用场景

  1. 01回顾指定时间范围内的事件
  2. 02调查 PagerDuty 事件及相关活动
  3. 03查找跨团队事件的时间关联

安装

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

$npx skills add https://github.com/delexw/claude-code-misc --skill pagerduty-oncall

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

config.json
scripts/
extract-json.js
filter-eps.js
filter-incidents.js
parse-analytics.js
parse-log.js
parse-notes.js

详细介绍

PagerDuty 值班事件调查员

进行身份验证,列出升级策略,获取所有事件及其详情,然后分析这些事件与值班团队的相关性。

输入

原始参数:$ARGUMENTS

根据参数推断:

  • QUERY:要调查的内容。默认为“今天的事件”。根据时间范围推导 --since 和 --until 日期(YYYY-MM-DD),使用 UTC(而非本地时区)。参见步骤 5 中的日期推导表。
  • MODE:根据 QUERY 推断。
    • 如果 QUERY 以“incident ”开头,或包含 PagerDuty URL(匹配 pagerduty\.com/incidents/([A-Z0-9]+))→ 单个事件模式
    • 否则 → 列表模式(现有行为)
  • SINCE:(可选)分析时间窗口的 UTC ISO8601 起始时间。在列表模式下,优先于从 QUERY 推导的日期。
  • UNTIL:(可选)分析时间窗口的 UTC ISO8601 结束时间。在列表模式下,优先于从 QUERY 推导的日期。
  • TZ_DISPLAY:(可选)用于报告显示的时区缩写(例如调用机器上 date +"%Z" 的输出)。提供此值时,报告中的所有时间戳均使用该值,而非通过系统时钟检测时区。

目标升级策略

按以下顺序确定要调查的升级策略列表:

  1. config.json — config.json 中的 escalation_policies 数组
  2. PD_ESCALATION_POLICIES — 以逗号分隔的环境变量(例如 "On Call, Platform Engineering On-Call")
  3. 如果两者均为空,则包含所有升级策略

系统要求

  • 已安装 pd CLI(https://github.com/martindstone/pagerduty-cli)
  • 已设置环境变量 PAGERDUTY_API_TOKEN,且其中包含有效的 PagerDuty REST API 令牌。重要: 检查此变量时,至少验证 2 次,才能判断它未设置。由于 shell 上下文不同,环境变量可能会显示为未设置。切勿泄露其值——只检查是否存在(例如 test -n "$PAGERDUTY_API_TOKEN")。

脚本

所有解析和筛选均由 ${CLAUDE_SKILL_DIR}/scripts/ 中的脚本处理:

脚本用途
extract-json.js从可能包含非 JSON 文本的 pd CLI 输出中提取 JSON
filter-eps.js按目标名称筛选 EP,并提取相关字段
filter-incidents.js根据 ep-list.json 中的服务 ID 筛选事件,并提取相关字段
parse-log.js从事件日志条目中提取相关字段
parse-notes.js从事件备注中提取相关字段
parse-analytics.js从事件分析数据中提取相关字段

所有脚本均从标准输入读取并写入标准输出。先通过 extract-json.js 管道处理 pd CLI 输出,再通过相应的筛选或解析脚本处理。

输出目录

所有中间 JSON 文件和最终报告均保存到:

.pagerduty-oncall-tmp/
├── ep-list.json              # Filtered escalation policies
├── incidents.json            # Incidents filtered by target EPs
├── logs/<INCIDENT_ID>.json   # Log entries per incident
├── notes/<INCIDENT_ID>.json  # Notes per incident
├── analytics/<INCIDENT_ID>.json # Analytics per incident
└── report.md                 # Final analysis report

执行

1. 验证连接

检查是否已设置 PAGERDUTY_API_TOKEN(在判断缺失前至少验证 2 次):

test -n "$PAGERDUTY_API_TOKEN" && echo "TOKEN_SET" || echo "TOKEN_MISSING"

如果已设置令牌,则进行身份验证:

pd auth add --token "$PAGERDUTY_API_TOKEN"

如果身份验证失败,请使用 AskUserQuestion 告知用户,并链接到 PagerDuty CLI 用户指南以查看设置说明。在身份验证成功前,切勿继续。

2. 检测本地时区

如果未提供 TZ_DISPLAY,则运行以下命令,以获取当前机器的本地时区:

date +"%Z"

记录输出,并将其用作报告中所有时间戳的显示时区。

3. 准备输出目录

创建输出目录 .pagerduty-oncall-tmp/ 及其子目录 logs/、notes/、analytics/,然后再保存任何文件。

4. 加载升级策略配置

使用 Read 工具读取 config.json。提取 escalation_policies 数组。

如果该数组为空,则检查是否设置了 PD_ESCALATION_POLICIES 环境变量:

test -n "$PD_ESCALATION_POLICIES" && echo "$PD_ESCALATION_POLICIES" || echo "EMPTY"

构建下一步所需的目标 EP 名称列表。如果两个来源都为空,则不传入任何名称(即包含所有 EP)。

5. 列出并筛选升级策略

通过一个管道完成获取、提取 JSON、按目标名称筛选并保存:

pd ep list --json 2>&1 | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js | node ${CLAUDE_SKILL_DIR}/scripts/filter-eps.js "EP Name 1" "EP Name 2" > .pagerduty-oncall-tmp/ep-list.json

将每个目标 EP 名称作为单独的参数传给 filter-eps.js。如果没有目标名称,则省略这些参数(所有 EP 均会通过筛选)。

6-ALT. 单事件模式(当 MODE = SINGLE-INCIDENT 时)

从 QUERY 中提取事件 ID:

  • 从 URL 中提取:匹配 pagerduty\.com/incidents/([A-Z0-9]+) → 捕获组即为 ID
  • 从简写中提取:匹配 incident ([A-Z0-9]+) → 捕获组即为 ID

获取指定事件:

pd rest get --endpoint "/incidents/<INCIDENT_ID>" 2>&1 \
  | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js \
  > .pagerduty-oncall-tmp/incidents.json

从事件 JSON 中提取:

  • id、incident_number、title、status、urgency
  • created_at、resolved_at(如果事件仍未关闭,则为 null)
  • service.summary → SERVICE
  • escalation_policy.summary → EP

还要获取同一服务上,在 created_at 前后各 2 小时内的相关事件:

pd incident list --json --statuses=open --statuses=closed --statuses=triggered --statuses=acknowledged --statuses=resolved \
  --since=<created_at minus 2h, YYYY-MM-DD UTC> --until=<created_at plus 2h, YYYY-MM-DD UTC> 2>&1 \
  | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js \
  | node ${CLAUDE_SKILL_DIR}/scripts/filter-incidents.js .pagerduty-oncall-tmp/ep-list.json \
  > .pagerduty-oncall-tmp/related-incidents.json

然后按常规继续执行步骤 6(收集详情)和步骤 7(生成报告)。

报告顶部必须包含结构化元数据部分(使用 UTC ISO8601 格式,以便机器解析):

## Incident Metadata
- created_at: <ISO8601 UTC>
- resolved_at: <ISO8601 UTC or "ongoing">
- service: <name>
- title: <title>

其后附上本地时区的易读时间线(参见步骤 7)。

6. 获取并筛选事件(LIST 模式)

根据 QUERY 推导 SINCE_DATE 和 UNTIL_DATE(YYYY-MM-DD,UTC)。重要: pd CLI 中的 --until 不包含指定日期。

如果 SINCE 和 UNTIL 是以 UTC ISO8601 时间戳提供的,则直接将它们传给 pd incident list — pd CLI 的 --since / --until 支持 ISO8601:

pd incident list --json ... --since=<SINCE> --until=<UNTIL> ...

否则,根据 QUERY,使用 Agent 的本地时区将 SINCE 和 UNTIL 推导为 UTC ISO8601 时间戳。“今天”指本地日历日 — 即使某事件对应不同的 UTC 日期,只要它发生在本地时间上午 11 点,也属于“今天”。计算本地日界线,并将其转换为 UTC ISO8601,以供 pd API 使用。

对于相对时长,直接使用 pd CLI 的自然语言:

pd incident list --json ... --since "24 hours ago" --until "now" ...

对于指定日期和日历日期范围,将本地午夜计算为 UTC ISO8601:

# Start of local today as UTC ISO8601 (Linux / macOS)
date -d "$(date +%Y-%m-%d) 00:00:00" -u +%Y-%m-%dT%H:%M:%SZ          # Linux
date -jf "%Y-%m-%d %H:%M:%S" "$(date +%Y-%m-%d) 00:00:00" -u +%Y-%m-%dT%H:%M:%SZ  # macOS

# Start of local yesterday
date -d "$(date -d yesterday +%Y-%m-%d) 00:00:00" -u +%Y-%m-%dT%H:%M:%SZ       # Linux
date -jf "%Y-%m-%d %H:%M:%S" "$(date -v-1d +%Y-%m-%d) 00:00:00" -u +%Y-%m-%dT%H:%M:%SZ  # macOS

将这些 ISO8601 值直接作为 pd incident list 的 --since / --until 参数。对于“今天”:SINCE = 本地今天开始时刻对应的 UTC ISO8601,UNTIL = 省略(默认值为当前时刻)。对于“昨天”:SINCE = 本地昨天开始时刻,UNTIL = 本地今天开始时刻。对于明确指定的日期范围:SINCE = 本地首日开始时刻,UNTIL = 本地末日次日开始时刻。

然后获取事件、提取 JSON、根据 ep-list.json 中的服务 ID 进行筛选并保存。请将此操作作为两个单独的命令运行 — 不要将步骤 4 和步骤 5 串成一个管道,因为 filter-incidents.js 会从磁盘读取 ep-list.json,且必须在步骤 5 开始前完整写入该文件:

# Step 4 must be complete before running this
pd incident list --json --statuses=open --statuses=closed --statuses=triggered --statuses=acknowledged --statuses=resolved --since=SINCE_DATE --until=UNTIL_DATE 2>&1 > /tmp/pd-incidents-raw.json
node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js < /tmp/pd-incidents-raw.json | node ${CLAUDE_SKILL_DIR}/scripts/filter-incidents.js .pagerduty-oncall-tmp/ep-list.json > .pagerduty-oncall-tmp/incidents.json

读取 .pagerduty-oncall-tmp/incidents.json 检查结果。如果数组为空,则生成一份注明事件数量为零的报告并停止。

7. 收集事件详情

对于 .pagerduty-oncall-tmp/incidents.json 中的每个事件,按顺序获取详情(以避免触发 PagerDuty API 速率限制)。使用 id 字段(例如 Q1V3O5Q3JX39LJ),不要使用 incident_number — pd CLI 仅接受内部 ID。

日志条目:

pd incident log -i <INCIDENT_ID> --json 2>&1 | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js | node ${CLAUDE_SKILL_DIR}/scripts/parse-log.js > .pagerduty-oncall-tmp/logs/<INCIDENT_ID>.json

备注:

pd incident notes -i <INCIDENT_ID> --output=json 2>&1 | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js | node ${CLAUDE_SKILL_DIR}/scripts/parse-notes.js > .pagerduty-oncall-tmp/notes/<INCIDENT_ID>.json

分析数据:

pd incident analytics -i <INCIDENT_ID> --json 2>&1 | node ${CLAUDE_SKILL_DIR}/scripts/extract-json.js | node ${CLAUDE_SKILL_DIR}/scripts/parse-analytics.js > .pagerduty-oncall-tmp/analytics/<INCIDENT_ID>.json
8. 分析并生成报告

使用 Read 工具读取 .pagerduty-oncall-tmp/ 中所有已保存的 JSON 文件。生成结构化分析报告,并使用 Write 保存到 .pagerduty-oncall-tmp/report.md:

在 SINGLE-INCIDENT 模式下,报告开头须包含结构化元数据块(UTC ISO8601,供 PIR 编排器进行机器解析):

## Incident Metadata
- created_at: 2026-03-20T02:30:00Z
- resolved_at: 2026-03-20T04:15:00Z
- service: storefront
- title: High error rate on checkout

然后包含:

  1. 事件摘要表 — 每个事件列出:ID、标题、服务、升级策略、状态、紧急程度、创建/解决时间戳(使用本地时区,如果提供了 TZ_DISPLAY 则使用,否则根据系统时钟检测;格式:2026-03-20 15:30 <TZ>)、持续时间
  2. 跨团队关联 — 找出不同升级策略下时间重叠的事件。标记潜在的级联故障或共同根因
  3. 时间线 — 按时间顺序展示所有团队的事件,使用本地时区,并突出显示活动集群
  4. 主要发现 — 模式、反复出现的服务、重复触发因素或升级策略缺口
  5. 建议 — 根据分析提出可执行的建议

所有面向用户显示的时间戳都必须使用带时区缩写的本地时间。人类可读部分不得使用 UTC。如果提供了 TZ_DISPLAY,则使用它;否则通过系统时钟检测(date +"%Z")。

写入报告后,务必明确告知用户报告位置,并将其作为回复的最后一行:

报告已保存到 .pagerduty-oncall-tmp/report.md

评论

支持 Markdown