SuperAPI AI 工具集

course-builder-incident-forensics

部署与运维

查看项目

更新于 10-16 10:29

技能介绍

用途

course-builder-incident-forensics 用于诊断任意 course-builder 应用(如 ai-hero、epic-web 等)的生产事故。目标是从“某个 course-builder 应用出问题了”推进到有证据的明确根因:包括部署、接口、错误特征、抛错位置,以及数据库/配置前置条件状态。

需要的输入

  • <app>:Vercel 项目 slug(示例:ai-hero)
  • <dataset>:Axiom 数据集(通常与 app slug 相同)
  • <host>:生产域名(示例:www.aihero.dev)

前置条件

  • 仓库路径:/Users/joel/Code/skillrecordings/support
  • 具备对 scope skillrecordings 的 Vercel 访问权限
  • 已为 skill CLI 配置 Axiom token
  • 本地代码路径存在:/Users/joel/Code/badass-courses/course-builder/apps/<app>

快速分诊工作流

1)确认部署与范围/账号

vercel ls <app> --scope skillrecordings --non-interactive

需记录:

  • 当前生产部署 URL
  • 失败属于当前还是上一次生产部署

2)从 Axiom 拉取 API 失败分布

cd /Users/joel/Code/skillrecordings/support/packages/cli
bun src/index.ts axiom query "['<dataset>'] | where host == '<host>' and isnotnull(status) and status >= 400 | summarize count=count() by status, path, deploymentUrl | sort by count desc" --since 2h --json

然后拉取具体失败样本:

bun src/index.ts axiom query "['<dataset>'] | where host == '<host>' and isnotnull(status) and status >= 400 | sort by _time desc | limit 20 | project _time, status, method, path, deploymentUrl, requestId" --since 2h --json

3)拉取失败部署的结构化运行时日志

vercel logs https://<deployment>.vercel.app --project <app> --scope skillrecordings --non-interactive --no-follow --since 2h --limit 1200 --json 2>&1 \
  | rg '^\{' \
  | jq -c 'select((.level != "info") or ((.responseStatusCode // 0) >= 400) or (.requestPath == "/api/inngest") or (.requestPath == "/api/shortlinks")) | {ts:.timestamp, level, method:.requestMethod, path:.requestPath, status:.responseStatusCode, message, traceId}'

4)将错误特征映射到代码中的抛错位置

rg -n "NonRetriableError|/api/inngest|/api/shortlinks|Preference type or channel not found" /Users/joel/Code/badass-courses/course-builder/apps/<app>/src -g'*.ts'

5)直接验证数据库前置条件(不靠猜测)

cd /Users/joel/Code/badass-courses/course-builder/apps/<app>
set -a; source .env.production.local; set +a
node --input-type=module -e "import { Client } from '@planetscale/database'; const c=new Client({url:process.env.DATABASE_URL}); const q=c.connection(); const tables=(await q.execute('show tables')).rows.map(r=>Object.values(r)[0]); const typeTable=tables.find(t=>String(t).endsWith('CommunicationPreferenceType')); const channelTable=tables.find(t=>String(t).endsWith('CommunicationChannel')); if(!typeTable||!channelTable){console.log(JSON.stringify({error:'missing communication tables', typeTable, channelTable},null,2)); process.exit(1);} const t=await q.execute(`select id,name from ${typeTable}`); const ch=await q.execute(`select id,name from ${channelTable}`); console.log(JSON.stringify({typeTable,channelTable,types:t.rows,channels:ch.rows},null,2));"

已知特征:Inngest 400 NonRetriableError

如果日志出现:

  • POST /api/inngest 状态 400
  • NonRetriableError: Preference type or channel not found

则检查:

  • src/inngest/functions/user-created.ts
  • src/inngest/functions/email-send-broadcast.ts

这些函数通常需要通信种子数据行:

  • 名为 Newsletter 的 preference type
  • 名为 Email 的 channel

如果通信表为空,这就是根因。

报告模板

报告时始终使用以下结构:

  • 账号与项目(skillrecordings/<app>)
  • 活跃生产部署 URL 与时间窗口
  • Axiom 失败拆分:按 status + path + deploymentUrl
  • 代表性失败 request ID/时间戳
  • 精确抛错位置路径 + 行号引用
  • 数据库前置条件检查结果(存在/缺失)
  • 一句话根因陈述

护栏

  • 不要打印 env 文件中的秘密值。
  • 报告时所有时间戳保持 ISO UTC。
  • 将“当前生产部署失败”与“更早部署失败”分开。
  • 如果 Axiom 事件名稀疏/为空,依赖 status/path/deploymentUrl 字段和 Vercel JSON 日志。

AI Hero 示例

  • <app> = ai-hero
  • <dataset> = ai-hero
  • <host> = www.aihero.dev

限制

资料未提供该工作流以外的通用能力说明、收费或平台支持信息,相关项暂未提供。