关于 pagerduty-oncall
pagerduty-oncall 是通过 pd CLI 调查 PagerDuty 事件并生成结构化分析报告的 skill。它支持事件列表和单个事件调查,并可按升级策略与时间范围筛选。
主要功能
- 01列出事件或调查指定事件
- 02按升级策略和时间筛选
- 03收集事件日志、备注和分析数据
- 04生成结构化事件报告
适用场景
- 01回顾指定时间范围内的事件
- 02调查 PagerDuty 事件及相关活动
- 03查找跨团队事件的时间关联
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ delexw/ claude-code-misc --skill pagerduty-oncall安装后在 Claude Code 中输入/pagerduty-oncall确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.jsonscripts/extract-json.jsfilter-eps.jsfilter-incidents.jsparse-analytics.jsparse-log.jsparse-notes.js详细介绍
PagerDuty 值班事件调查员
进行身份验证,列出升级策略,获取所有事件及其详情,然后分析这些事件与值班团队的相关性。
输入
原始参数:$ARGUMENTS
根据参数推断:
- QUERY:要调查的内容。默认为“今天的事件”。根据时间范围推导
--since和--until日期(YYYY-MM-DD),使用 UTC(而非本地时区)。参见步骤 5 中的日期推导表。 - MODE:根据 QUERY 推断。
- 如果 QUERY 以“incident ”开头,或包含 PagerDuty URL(匹配
pagerduty\.com/incidents/([A-Z0-9]+))→ 单个事件模式 - 否则 → 列表模式(现有行为)
- 如果 QUERY 以“incident ”开头,或包含 PagerDuty URL(匹配
- SINCE:(可选)分析时间窗口的 UTC ISO8601 起始时间。在列表模式下,优先于从 QUERY 推导的日期。
- UNTIL:(可选)分析时间窗口的 UTC ISO8601 结束时间。在列表模式下,优先于从 QUERY 推导的日期。
- TZ_DISPLAY:(可选)用于报告显示的时区缩写(例如调用机器上
date +"%Z"的输出)。提供此值时,报告中的所有时间戳均使用该值,而非通过系统时钟检测时区。
目标升级策略
按以下顺序确定要调查的升级策略列表:
config.json— config.json 中的escalation_policies数组PD_ESCALATION_POLICIES— 以逗号分隔的环境变量(例如"On Call, Platform Engineering On-Call")- 如果两者均为空,则包含所有升级策略
系统要求
- 已安装
pdCLI(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、urgencycreated_at、resolved_at(如果事件仍未关闭,则为 null)service.summary→ SERVICEescalation_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
然后包含:
- 事件摘要表 — 每个事件列出:ID、标题、服务、升级策略、状态、紧急程度、创建/解决时间戳(使用本地时区,如果提供了 TZ_DISPLAY 则使用,否则根据系统时钟检测;格式:
2026-03-20 15:30 <TZ>)、持续时间 - 跨团队关联 — 找出不同升级策略下时间重叠的事件。标记潜在的级联故障或共同根因
- 时间线 — 按时间顺序展示所有团队的事件,使用本地时区,并突出显示活动集群
- 主要发现 — 模式、反复出现的服务、重复触发因素或升级策略缺口
- 建议 — 根据分析提出可执行的建议
所有面向用户显示的时间戳都必须使用带时区缩写的本地时间。人类可读部分不得使用 UTC。如果提供了 TZ_DISPLAY,则使用它;否则通过系统时钟检测(date +"%Z")。
写入报告后,务必明确告知用户报告位置,并将其作为回复的最后一行:
报告已保存到
.pagerduty-oncall-tmp/report.md