ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Studio Radar:用 Sanity Studio 构建仓库性能健康仪表盘与基准数据查询指南

Studio Radar:用 Sanity Studio 构建仓库性能健康仪表盘与基准数据查询指南 Studio Radar用 Sanity Studio 构建仓库性能健康仪表盘与基准数据查询指南【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanitySanity 开源仓库GitHub_Trending/sa/sanity内置了一套名为Studio Radar的仓库健康仪表盘源码位于 dev/radar部署于radar.sanity.dev它把 CI 每天写入的基准测试数据变成可交互、可分享、可实时更新的性能趋势图、漂移告警、发布标记和二分定位工具。本文以 .agents/skills/sanity-radar/SKILL.md 为骨架结合仓库源码与配置系统讲解 Radar 的六大工具、数据模型、GROQ 查询配方、本地开发与运维流程读完你既能用 GROQ 直接查询benchRun/gitCommit/gitTag/bisectSession数据也能独立运行、测试并扩展这套仪表盘。一句话理解 RadarRadar 回答的是不开 CI 日志也能知道的仓库健康问题main 分支上的 Studio 性能是否在漂移Trends、某次运行长什么样run 详情、哪个提交搞坏了性能Bisect、什么东西在什么时候发布、有没有回归Releases。它本身就是一个 Sanity Studiodev/radar读取的是 CI 写入的bench数据集——设计记录在 dev/radar/SPEC.md回归排查用sanity-radar-investigate数据生产用sanity-bench。六大工具URL 路径即工具名工具路径展示内容Trends/trends按 scenario·metric 排列的小多图small multiplesmain 分支上的 p50 折线、p75–p90 阴影带、主机校准线点线、漂移基线叠加虚线之前/实线之后、发布刻度。默认视图。Releases/releases所有已同步的v*标签dist-tags、周下载量、changelog 链接、归因到该版本的回归bisect 结果。Bisect/bisect基于gitCommit的一分法first-parent二分定位每一步都用对应提交的 test-studio 预览构建来验证。Diagnostics/diagnostics粘贴一份 Studio 诊断 JSON 并渲染dev/studio-diagnostics-viewer的 Studio 内孪生版本。Structure/structure原始文档浏览。Comparisons/comparisons来自 A/B 分发的已存储mode: ab运行按指标给出判定verdict。工具注册顺序在 dev/radar/sanity.config.ts 中可见Trends 排在第一位默认落地页随后是 Releases、Bisect、Diagnostics、Structure最后是访问最少的 Comparisons。配置还显式关闭了releases与scheduledDrafts插件releases: {enabled: false}避免与自定义工具语义冲突。Trends 的可分享 URL 状态Trends 的全部视图状态都编码在 URL 里可以随时分享?range30|90|all—— 时间范围30 天 / 90 天 / 全部?branchesmain,branch—— 参与比较的分支?layers-band,-calibration—— 隐藏图层如-band去掉 p75–p90 带?tabmetric group—— 指标分组页签Web Vitals / Editing responsiveness / Load / Bundle size / Soak / Settle / Calibration?maxseries key—— 最大化单张图表Releases 还支持?pathtest-studio path头部路径框里的值会拼到每个 release 的 Test Studio 链接上便于跨版本逐个检查同一个复现路径。点击数据点的运行弹窗run popover点击任意数据点弹出该次运行的详情数值、百分位、主机、发布上下文、各类链接在 Suspect a regression? 区域还提供两个调查交接工具Copy A/B vs previous run一条可直接粘贴的gh workflow run bench.yml … ab_from/ab_to命令GitHub 没有能预填 dispatch 输入的 URL所以这里是命令而非链接Copy investigation prompt同一命令包装成的、可直接投喂给编码 Agent 的排查简报实现见 dev/radar/tools/trends/investigationPrompt.ts。数据层项目、数据集与文档模型Radar 读取 Sanity 项目mhfozd0z的bench数据集私有。读取需要具备该项目访问权限的 token——本地可用sanity debug --secrets查看 CLI token或到 sanity.io/manage 申请 viewer token部署后的 Studio 通过你的登录态认证。写入需要RADAR_SANITY_WRITE_TOKEN且只有 CI 持有该 token绝不要从笔记本上写数据。文档 ID 规则一处定义全员遵守ID 的生成集中在 packages/repo/utils/src/radarIds.ts该模块是repo/utils/radar-ids的单一事实来源perf/bench 存benchRun、dev/radar 同步 git 历史、dev/radar 工具写 ack 和 bisect 会话都从这里取 ID。规则只有两条不能有.点号会让 ID 变成路径段如drafts.x、versions.r.xAPI 会以不同的作用域和权限处理它们——gitTag-v6.10.1就曾因此踩过坑不能用 camelCase全部小写、横线分隔让 ID 在 URL、日志和查询里读起来一致。确定性文档提交、标签、ack、运行的 ID 是派生的因此createOrReplaceupsert 天然幂等gitCommit→git-commit-shagitTag→git-tag-v6-10-1v6.10.1被 slug 化为v6-10-1benchRun→bench-run-sha-run idmain/AB 运行或bench-run-pr-nPR 运行每个 PR 覆盖一个文档最新推送生效driftAck→drift-ack-metricKey:branch 的 slugbisectSession→bisect-session-uuid用户创建用随机 uuid五种文档类型类型写入方ID关键字段benchRun.github/workflows/bench.yml 中的bench storebench-run-sha-run id/bench-run-pr-nmodeabsolute时间序列点、ab调查记录、triggercron/release/backfill/dispatch/pr缺省cron、git{sha, branch, committedAt, mergeBaseSha, prNumber}、runner{calibrationMs, cpuModel, runId…}、scenarios[]{scenario, mode, runner{calibrationMs, cpuModel}, metrics[]{label, unit, experiment/reference{summary{median,p75,p90}}, comparison{diff,lo,hi,verdict}}, resources, soak}、bundle{initialJsBytes, totalJsBytes}gitCommitsync-git-metrics.yml每次 push 到 maingit-commit-shasha、parentShafirst-parent 链、committedAt、subject、prNumber、作者、testStudioUrlgitTag同上releases 与每日 npm 下限git-tag-v6-10-1tag、sha、taggedAt、major/minor/patch/prerelease、npm{distTags, weeklyDownloads, publishedAt}bisectSessionBisect 工具用户所有liveEditbisect-session-uuidgood/bad{sha}、releasesOnly、reproPath追加到每个预览 URL 的 test-studio 路径、marks[]、result{firstBadSha, suspectShas, regression}driftAckTrends 漂移 feed用户所有drift-ack-metricKey:branch 的 slugstatesilenced/snoozed/fixed、baselineValue、untilSchema 定义见 dev/radar/schemaTypes/index.tsbenchRun的 schemadev/radar/schemaTypes/benchRun.ts明确注明文档由机器写入the studio presents, it does not edit其形状镜像perf/bench/report/storeShape.tssummary 字段覆盖n/median/p75/p90/p99/min/maxmetric 的comparison.verdict枚举为regression/improvement/neutral/inconclusive与 perf/bench/stats/gate.ts 的Verdict类型一致。每个数据消费者都必须遵守的规则仪表盘的查询tools/*/data.ts是这些规则的参考实现只投影永不抓sessions文档携带 per-session 采样数组一条裸的*[_type benchRun]就是数兆字节。dev/radar/tools/trends/data.ts 的TREND_QUERY是严格投影的范例时间序列 mode absolute按coalesce(git.committedAt, startedAt)排序backfill 运行有历史的committedAt与最近的startedAt用runDate()取被测提交的提交时间而不是运行时间PR 分支运行共享同一类型过滤git.branch main得到主线同一 sha 的多条运行合并为一个点CI 会重测提交图表按中位数合并buildSeries合并点保留真实运行的 ID 以便点击穿透绝对值是主机相关的读任何数值都要同时看runner.calibrationMs越高 主机越慢和runner.cpuModel只有 A/B 的comparison.verdict是主机无关的git.sha是与gitCommit的 join 键benchRun.git.commit是弱引用对 PR 分支运行会悬空。GROQ 查询配方直接问数据现成的查询配方集中在 .agents/skills/sanity-radar/references/groq-recipes.md所有配方都做投影、都不取sessions。项目mhfozd0z、数据集bench是私有的每条查询都需要读取 token$SANITY_AUTH_TOKENsanity debug --secrets里的 CLI token 即可qgroq curl -sG https://mhfozd0z.api.sanity.io/v2025-02-19/data/query/bench \ -H Authorization: Bearer $SANITY_AUTH_TOKEN --data-urlencode query$q | jq .result范围参数start/end可用 ISO 日期或 sha也可以作为$params传入--data-urlencode $sha…。主线序列健康度// 最近 10 个日更点 主机上下文 —— 读任何 ms 值之前先看 calibration *[_type benchRun mode absolute git.branch main] | order(coalesce(git.committedAt, startedAt) desc)[0...10]{ _id, startedAt, trigger, releaseTag, sha: git.sha, committedAt: git.committedAt, calibrationMs: runner.calibrationMs, cpuModel: runner.cpuModel, runId: runner.runId }// 自 $start 以来有存储运行的日期 —— 在 GROQ 外与日历做差集即可找出缺口 array::unique(*[_type benchRun mode absolute git.branch main startedAt $start]{day: string::split(startedAt, T)[0]}.day)单一指标随时间变化// 每个运行的某指标 p50/p75/p90带分片自身的主机校准 *[_type benchRun mode absolute git.branch main] | order(coalesce(git.committedAt, startedAt) asc){ date: coalesce(git.committedAt, startedAt), sha: git.sha, runCalibrationMs: runner.calibrationMs, shard: scenarios[scenario $scenario][0]{ calibrationMs: runner.calibrationMs, cpuModel: runner.cpuModel, metric: metrics[label $label][0].experiment.summary{median, p75, p90, n} } }指标标签的语义配方文档中有详细说明interaction 场景的kind是interaction或pageloadmode只对额外的日更模式inp、soak设置interaction 的指标标签就是实际输入的字段名stringField、title、body、simple-en…每个都携带击键延迟pageload 标签形如condition · metricboot-cold · time to editable、open-doc-warm · LCP、boot-cold · auth round trips…INP 场景携带INP与INP interactions。场景 ID 来自pnpm bench scenarios。Bundle 大小是每侧的顶层字段bundle.experiment{initialJsBytes, totalJsBytes, chunkCount}soak 数据在scenarios[mode soak][0].soak资源请求数、DOM 节点、监听器、堆挂在 interaction 场景上scenarios[kind interaction]{scenario, r: resources.experiment{requestCount, domNodes, listeners, heapMb}}。特定提交的运行// 所有测量过该 sha 的运行重跑会落在不同主机上——对比 calibration *[_type benchRun git.sha $sha]{ _id, mode, trigger, startedAt, branch: git.branch, calibrationMs: runner.calibrationMs, cpuModel: runner.cpuModel, runId: runner.runId }A/B 对比调查记录// 新的优先每个运行的判定计数 *[_type benchRun mode ab] | order(startedAt desc){ _id, startedAt, from: git.mergeBaseSha, to: git.sha, runId: runner.runId, regressions: count(scenarios[].metrics[comparison.verdict regression]), improvements: count(scenarios[].metrics[comparison.verdict improvement]), inconclusive: count(scenarios[].metrics[comparison.verdict inconclusive]) }// 某一次对比中被判定的指标 *[_type benchRun mode ab _id $id][0].scenarios[]{ scenario, mode, metrics: metrics[defined(comparison)]{ label, unit, reference: reference.summary.median, experiment: experiment.summary.median, comparison{diff, lo, hi, verdict} } }Git 历史与发布// 两次运行 sha 之间的提交按 committedAt 窗口精确 first-parent 链需从 $to 沿 parentSha 走到 $from *[_type gitCommit committedAt *[_type gitCommit sha $from][0].committedAt committedAt *[_type gitCommit sha $to][0].committedAt] | order(committedAt desc){sha, subject, prNumber, authorLogin, committedAt, testStudioUrl}// main 上的稳定发布 npm 当前口径 *[_type gitTag !defined(prerelease) defined(*[_type gitCommit sha ^.sha][0])] | order(taggedAt desc)[0...20]{tag, sha, taggedAt, distTags: npm.distTags, downloads: npm.weeklyDownloads}// 哪个发布最先包含某提交sha 的 committedAt 之后最早的 tag *[_type gitTag !defined(prerelease) taggedAt *[_type gitCommit sha $sha][0].committedAt] | order(taggedAt asc)[0]{tag, taggedAt}注意最后一条是按日期和仪表盘的发布括号一致它说的是shipped after而非contained in要证明包含需要走 first-parent 链。Bisect 会话与漂移确认*[_type bisectSession defined(result.firstBadSha)] | order(createdAt desc){ title, firstBad: result.firstBadSha, regression: result.regression, suspects: result.suspectShas, createdBy }*[_type driftAck]{metricKey, branch, state, until, note, ackedBy, ackedAt}在仪表盘上开发命令、架构约定与调试数据pnpm radar # sanity dev跑在 http://localhost:3399需要 Sanity 登录读实时数据 pnpm vitest run --projectradar # 纯模块测试趋势数学、漂移、二分、git 解析器 pnpm build:radar # 生产构建turbo pnpm --filter radar sync-git -- --dry-run # 预览 git 历史同步需要 GITHUB_TOKEN对应的脚本定义在 dev/radar/package.jsondev为sanity dev --port 3399另有sync-git走scripts/syncGitHistory.ts与backfill-benchrun-refs回填benchRun.git.commit弱引用。开发时必须遵守的约定全链路实时所有视图数据走useDocumentStore().listenQueryuseObservable绝不用一次性client.fetch——新的 cron 运行必须无需刷新就出现SPEC 明确no rollup documents每天 ≤1 个文档时投影查询足够快图表用 visx 原语visx/scale|shape|group|axis|responsive组合在sanity/ui布局里不引入图表库依赖见 dev/radar/package.json调试数据源仅 dev server工具栏选择器见 dev/radar/tools/trends/debugData.ts渲染 steady / drift / step / host-correlated / sparse / empty 数据集和合成发布标签——用它们在没有实时数据时演练每一层编码和漂移 feedUI 靠这些数据验证而不是单测值得关注的单一事实来源漂移阈值从 perf/bench/stats/gate.ts 导入不要自造第二个统计量SPEC.md 记录了尝试过又被否决的基线方案step 基线、按星期匹配及原因诚实性约束任何展示 ms 数值的面都必须让主机校准可见CALIBRATION_EXPLAINER是唯一的共享措辞定义于 dev/radar/tools/trends/data.ts主机校准是 CI 机器在基准测试前在浏览器里无节流执行的一个固定 CPU 工作负载整数哈希循环、5 次中位数越高 主机越慢Studio 通用约定同样适用AGENTS.md不用forwardRef、use-effect-event不用内联 Translate 组件。漂移检测的数学内核dev/radar/tools/trends/drift.ts 实现了指标移动是否值得关注的三重判定单一基线 最近 7 次运行的中位数 vs 之前 21 次运行的中位数按运行数而非天数计数UI 明确写 vs prior 21 runs绝对下限按单位ms 用 16ms 两次 Event Timing 8ms 量化步即 gate 的 interaction 下限、MB 用 1、bytes 用 10KB、CLS 用 0.02、count 用 1相对下限基线的 5%gate 的 interaction 数值load 指标的 100ms/8% 宽松对不镜像——漂移无法按单位区分 load 与击键指标且能过 8% 必能过 5%噪声检验至少NOISE_Z 2.5个标准误噪声由序列自身估计noiseSigma跨两窗的相邻差 MAD、仅最近窗的相邻差 MAD、前窗残差 MAD三者取最大中位数标准误用 √(π/2) 效率系数修正。第三个检验是 feed 可审查的关键击键延迟的运行间噪声有 11–22%仅靠固定 5% 下限会在存储历史上误报约 68% 的窗口纯噪声模拟约 57%加入噪声检验后同一历史只误报 6% 的击键窗口纯噪声模拟 1%。classify()里最小效应取max(absolute, relative * |baseline|)使基线为 0 的指标如 tripwire 计数 0 → 4也能靠绝对下限触发。判定结果排序为 regression improvement neutralworstBySeriescomputeDrift为每个足够历史的序列都产出对比包括未越线的neutral供图表叠加基线参考线但 feed 与页签徽章只统计真正的 flag。发布标记的诚实性设计发布标记release markers只画从 main 切出的稳定版本TAGS_QUERYdev/radar/tools/trends/data.ts过滤!defined(prerelease)并且要求存在 sha 等于该 tag 的gitCommit文档这些文档按构造只覆盖 main因此排除了从 release 分支切出的维护版本如 v5.31.2。标记优先锚定到真正测量过该发布的运行trigger: release的运行resolveTagPositions否则回退到 tag 日期两种位置渲染一致区别只由文案承载measured release vs release且按时间而非 sha 的 fallback 刻意保持谨慎这个发布从这里出货绝不声称这次运行测量了这个发布。相距过近的标记会被合并clusterTags6.8 小时内的两个发布在卡片上只有约 1px标签按大小自适应抽稀最大化视图才画旋转标签。运维定时任务、回填与告警日更 main 运行bench.yml的 cron 在05:00 UTC见 .github/workflows/bench.yml 的schedulegit 同步在05:30sync-git-metrics.yml。错过的日子用 backfill dispatch 修复详见sanity-benchskill提交出现缺口则执行gh workflow run sync-git-metrics.yml -f backfilltrue发布标记只出现在其提交有gitCommit文档的 tag 上按构造仅 main从分支切出的维护版本正确地不显示cron 失败会告警到 CI Slack 频道序列出现空洞却无告警意味着是 store 步骤被跳过而非运行失败bench.yml的workflow_dispatch输入定义了完整的操作面run_suite完整 absolute 套件并存储等同日更 cron、self_test构建自比对、backfill_sha回填历史提交、release_tag测量已发布 tag如v6.10.1、ab_from/ab_toA/B 对比并发组保证同一 PR 同时只有一个运行避免旧结果覆盖新评论。延伸阅读设计记录与决策史dev/radar/SPEC.mdTrends、run 详情、漂移 feed、图层切换、发布标记、最大化图表、Bisect、Studio releases 各视图的完整设计论证数据生产侧perf/bench的 store 形状perf/bench/report/storeShape.ts与判定门限perf/bench/stats/gate.tsINTERACTION_THRESHOLDS16ms/5%、PAGELOAD_THRESHOLDS100ms/8%gate()的 verdict 规则配套技能sanity-bench数据生产、sanity-radar-investigate回归调查数据结构化入口dev/radar/schemaTypes 与 ID 约定 packages/repo/utils/src/radarIds.ts【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表