ARTICLE DETAIL

资讯详情

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

Penpot Error Reports CLI 实战:基于 RPC API 的错误报告查询、统计与排查指南

Penpot Error Reports CLI 实战:基于 RPC API 的错误报告查询、统计与排查指南 Penpot Error Reports CLI 实战基于 RPC API 的错误报告查询、统计与排查指南【免费下载链接】penpotPenpot: The open-source design platform for Product teams that need scalable collaboration.项目地址: https://gitcode.com/GitHub_Trending/pe/penpotPenpot 在仓库中内置了一款 Node.js 命令行工具 scripts/error-reports.mjs可通过后端 RPC 接口查询服务端记录的错误报告server error report支持时间范围、来源、租户、版本等多维过滤、游标分页、以及签名/突发/热力图等统计聚合。本文以官方说明文档为核心结合脚本源码与后端 RPC 实现完整讲解该工具的配置、三大子命令list/get/stats的每一个参数、输出格式、分页原理、Hint 归一化机制与排障要点帮助读者用它快速定位生产环境中的异常聚集与回归问题。关联文档.serena/memories/scripts/error-reports.md工具实现scripts/error-reports.mjs后端实现backend/src/app/rpc/commands/error_reports.clj。一、工具定位与适用场景error-reports是面向 Penpot 服务端运维与排障场景的专用 CLI。它直接调用后端 RPC 方法get-error-reports/get-error-report读取数据库server_error_report表中的错误日志不经过任何 Web UI。它的典型用途包括从数据库中查询错误报告用于 Debug 与事后分析按source来源、kind类型、tenant租户、version后端版本过滤错误将错误数据导出为 JSON、NDJSON 或终端表格计算错误统计Top 签名、版本分布、来源分布、audit-log 类型分布、小时分布、5 分钟突发窗口、星期×小时热力图按 ID 调查单条错误报告的完整上下文与调用栈。从源码结构看该工具在后端侧依赖的 RPC 端点自 2.20 版本开始提供见 error_reports.clj 中::doc/added 2.20标记因此在调用前需确认后端版本包含对应端点。二、前置条件与配置2.1 环境要求Node.js脚本使用 Node 原生fetch发起请求需要支持 Fetch API 的运行时依赖包commanderCLI 参数解析与dotenv读取 .env。两者已声明在仓库根目录 package.jsoncommander: ^15.0.0、dotenv: ^17.4.2在仓库根目录执行pnpm install或npm install即可获得运行中的 Penpot 后端且已包含 error-reports RPC 端点带error-reports:read权限的访问令牌access token。2.2 创建 .env 配置文件在仓库根目录创建.env文件写入两行配置PENPOT_API_URIhttp://localhost:3450 PENPOT_ACCESS_TOKENyour-token其中PENPOT_API_URI指向后端公开 API 地址。脚本中的rpcCall见 error-reports.mjs实际拼接的请求为POST ${PENPOT_API_URI}/api/main/methods/${method}即默认 3450 端口对应本地开发后端PENPOT_ACCESS_TOKEN为访问令牌请求头为Authorization: Token accessToken。若缺失任一项脚本会打印 .env 配置提示并退出对应 loadConfig 的校验逻辑。2.3 为令牌授予error-reports:read权限令牌权限并非通过 UI 就能直接授予。查看 access_token.clj 的实现可知通过公共 API 创建的令牌默认只有空权限数组提升类权限如error-reports:read不能通过公开 API 分配只能借助 SQL 或 REPL 辅助函数。方式一直接更新数据库UPDATE access_token SET perms ARRAY[error-reports:read]::text[], updated_at now() WHERE id token-uuid;方式二使用 REPL 辅助函数同样定义在 access_token.clj(repl:grant-access-token-perm cfg token-id error-reports:read)权限校验在后端 RPC 定义中强制声明::rpc/auth-type :token、::rpc/perms #{error-reports:read}见 error_reports.clj没有该权限时请求会被拒绝HTTP 403。三、底层协议CLI 与后端 RPC 的对应关系为了用好工具值得先了解脚本背后真正调用的两个 RPC 方法源码见 error_reports.cljCLI 命令实际 RPC 方法URL 形态基于rpc.clj路由用途list::get-error-reports/api/main/methods/get-error-reports分页列出错误摘要get::get-error-report/api/main/methods/get-error-report按 ID 取单条完整报告路由在 rpc.clj 中定义/api/main/methods/:method-name走mainAPICORS 会话/令牌鉴权方法注册表通过 rpc.clj 加载app.rpc.commands.error-reports命名空间。值得注意的分页语义list --from会映射为服务端参数since最旧边界--to映射为服务端参数until最新边界脚本注释与代码明确标注了这一映射关系见 error-reports.mjs。3.1 服务端过滤与排序的 SQL 实现后端 build-list-query 揭示了几条影响过滤行为的细节表为server_error_reportcontent是 Transit JSONB 字段kind取自content-~:kind缺省时回退~:origin--hint过滤实际是 SQLILIKE %text%不区分大小写的模糊匹配因此支持部分匹配--source会先由名称映射回整数编码source-names共 5 种见下节查询恒定为ORDER BY created_at ASC, id ASC配合LIMIT n即升序最旧在前返回判断是否还有下一页多取 1 条inc limit若实际返回行数超过 limit 即生成游标见 get-error-reports 方法体。3.2 五个合法 Source 名称文档中列出的来源名为logging、audit-log、rlimit从后端 source-names 的完整映射看--source实际接受以下5 个值名称数据库编码含义legacy-v11旧版 v1 记录legacy-v22旧版 v2 记录logging3常规日志上报audit-log4审计日志条目rlimit5资源限制触发rate limit 等CLI 的--source帮助文本也同步列出了这 5 个候选值见 error-reports.mjs。四、命令总览与通用说明./scripts/error-reports.mjs command [options]三个子命令list分页列出错误报告支持过滤与多种输出格式get按 ID 获取单条错误报告stats读取 API/文件/stdin 数据并计算统计。通用要点所有过滤项可任意组合AND 语义同时支持--optionvalue与--option value两种写法默认读取仓库根目录.env可通过--env path指定其它配置文件如需跨目录执行可写为node /data/web/disk1/git_repo/GitHub_Trending/pe/penpot/scripts/error-reports.mjs或先进入仓库根目录再运行。五、list列出与过滤错误报告./scripts/error-reports.mjs list [options]5.1 参数表Flag说明默认-l, --limit n每页条数上限服务端硬上限 200后端 schema 校验 1..20050--from dateISO 时间戳最旧边界取该时间之后的数据—--to dateISO 时间戳最新边界取该时间之前的数据—--since dateISO 时间戳手动分页的显式游标—--since-id uuid取该 ID 之后的错误游标分页—-s, --source name按来源过滤见“五个合法 Source 名称”一节—-p, --profile-id uuid按 Profile ID 过滤—-k, --kind kind按类型过滤字符串—-t, --tenant tenant按租户过滤—--version version按后端版本过滤—--hint text按 hint 模糊匹配ILIKE—-a, --all自动抓取所有分页流式输出false-f, --format type输出格式json、table或ndjsontable--normalize-hints归一化 hint剥离动态值false-o, --output file写入文件而非 stdout—--env path自定义 .env 路径.env-h, --help帮助—流式行为说明--all模式下输出必须为ndjson或table--all --format json会被明确拒绝见 cmdList 中的校验逻辑因为--all的本质是边拉取边输出。--all --format table会先打印表头再逐行输出--format ndjson则总是逐行流式输出一个 JSON 对象。表格模式下hint列会被截断到 60 字符truncateHint单页列表会显示“Found N error reports”当还有更多数据时会在末尾提示More results: use --since nextSince --since-id nextId六、get按 ID 查询单条错误报告./scripts/error-reports.mjs get [options]Flag说明必填--id uuid错误报告 ID是--error-id id错误的 error-id备选标识否-f, --format typejson或table否默认table--env path自定义 .env否默认.env-h, --help帮助否注意CLI 定义中--id为requiredOption见 get 命令注册实际取值逻辑是args.id优先、否则回退到args.errorId。get返回的是完整的单条报告。表格模式formatGetTable会输出这些字段ID、Created At、Source、Profile ID、Kind、VersionHint归一化错误提示HREF关联链接Context上下文信息逐行缩进展示Params/Props若存在且非{}Report取trace或report字段的完整调用栈/报告正文。若报告不存在后端会返回code: report-not-found的 RPC 错误见 error_reports.clj。七、stats错误统计与异常检测./scripts/error-reports.mjs stats [options]stats有三种数据来源cmdStats--input file从本地 JSON / JSON 数组 / NDJSON 文件读取stdin 管道当 stdin 不是 TTY 时自动读取同样支持 JSON、数组、NDJSON 三种形态直接访问 API无输入文件且 stdin 为空时用--from/--to/--limit自动翻页抓取。Flag说明默认--from date统计区间起点ISO 时间戳—--to date统计区间终点ISO 时间戳—--limit n从 API 抓取时每页条数200--input file从本地 JSON/NDJSON 文件读取—--burst检测超过平均速率 3 倍的 5 分钟突发窗口false--heatmap展示星期×小时的密度热力图false-f, --format typejson或tabletable--env path自定义 .env.env7.1 聚合维度所有参与统计的 hint 都会先归一化再分组见第八节由此实现“同签名错误合并”。表格模式输出 6 组统计cmdStatsTotal / Unique profiles总量与去重后的 Profile 数By Signature (normalized hint)按归一化 hint错误签名降序By Source按来源分布By Kind (audit-log only)仅对source audit-log的子集按 kind 统计代码中kindScope: audit-logBy Version按版本分布By Hour (UTC)按小时分布。每个维度都带数量、百分比、以及长度归一化的条形图便于肉眼比较占比。JSON 模式下结构为{ total: 123, uniqueProfiles: 5, byHint: [{key: ..., count: 30}], byVersion: [], bySource: [], byKind: [], byHour: [], kindScope: audit-log }开启--burst后追加bursts数组开启--heatmap后追加heatmap对象。7.2 Burst突发检测原理--burst的实现见 buildBurstWindows以全部有效时间戳覆盖的区间按 5 分钟5 * 60 * 1000ms切窗计算每窗口平均数量averagePerWindow凡单窗口数量超过max(1, average * 3)即判为突发。输出每个突发窗口的start/endISO 时间区间count窗口内错误数、averagePerWindow、ratio相对平均值的倍数ids最多 12 个样本错误 ID便于直接跟进get。7.3 Heatmap热力图原理--heatmap由 buildHeatmap 实现按 UTC 计算每条记录落在「周一~周日 × 00~23 时」的哪个桶。表格输出将 24 小时压缩成十位数字一行如0 0 1 1 ...单元格分 4 级密度·0、1低、2中、3高、4峰值。热力图对发现“每天固定时段集中报错”这类周期性规律尤其有效。八、Hint 归一化机制--normalize-hintslist以及在stats中总是执行的 hint 归一化目标是把含动态值文件 ID、UUID、耗时等的 hint 收敛为“错误签名”从而正确聚合同类错误。以源码 normalizeHint 为准实际替换规则包括引号与空白规范化弯引号“”‘’转为直引号、转义引号还原、连续空白折叠为单空格并 trimURI 替换https?://...→urifile-id 上下文替换形如file-id: uuid、file_iduuid等关联位置 →file-idUUID 替换匹配8-4-4-4-12十六进制形态的 UUID →uuid括号内数字 ID 替换(12345)→(id)耗时替换7.5s、2m3.027s等多段带单位时间 →elapsed空结果兜底归一化后为空串时返回(empty)便于对无 hint 记录单独归组。九、输出格式详解9.1 table默认面向终端的可读表格。list的列固定为ID | Created At | Source | Profile ID | Kind | Hint见 TABLE_HEADERShint 超过 60 字符会截断。--all时表头先行打印、数据行到达即输出无需缓冲。9.2 json单页模式的结构化输出形如{ items: [ { ...: ... } ], nextSince: ..., nextId: ... }其中nextSince/nextId仅在还有下一页时存在是手动分页的游标。--all不能与--format json组合会报错退出流式场景请用ndjson。9.3 ndjson每行一个 JSON 对象始终流式输出。适合管道处理例如配合jq抽取字段或wc -l计数。./scripts/error-reports.mjs list --all --format ndjson | jq -c {id, hint} ./scripts/error-reports.mjs list --all --format ndjson | wc -l十、分页机制详解服务端按升序返回最旧在前游标为(created_at, id)复合游标。这与部分旧实现的 DESC 排序不同文档与后端ORDER BY created_at ASC, id ASC见 error_reports.clj互相印证。10.1 手动分页用响应中的nextSince与nextId作为下一请求的--since/--since-id./scripts/error-reports.mjs list --limit 50 # 从上一响应取 nextSince / nextId ./scripts/error-reports.mjs list --limit 50 --since 2026-01-20T10:29:00Z --since-id next-uuid注意--since与--since-id是一对游标值通常应一起传服务端以(since, since-id)或(since, 全零 uuid)构造复合比较条件见 error_reports.clj。10.2 自动分页--all让 CLI 自动循环翻页直到服务端不再返回游标./scripts/error-reports.mjs list --all10.3 时间范围查询--from/--to用于界定时间窗口映射为服务端since/until./scripts/error-reports.mjs list --from 2026-07-20T00:00:00Z --to 2026-07-23T23:59:59Z --all10.4 分页与单页模式的实现细节阅读 cmdList 可见非流式单页模式下脚本仍会循环抓取仅在--all时继续翻页并把最后一次响应的nextSince/nextId附在 JSON 结果的items之外流式模式下每收到一页即逐条写出并更新内部游标。十一、完整实战示例以下示例均以仓库根目录为工作目录、scripts/error-reports.mjs具备执行权限为前提无执行权限时用node scripts/error-reports.mjs等价替代。列出最近 10 条错误./scripts/error-reports.mjs list --limit 10时间窗口查询某一天全部./scripts/error-reports.mjs list --from 2026-07-23T00:00:00Z --to 2026-07-23T23:59:59Z --all全量流式导出为 NDJSON./scripts/error-reports.mjs list --all --format ndjson errors.ndjson用 --output 直接写文件免 shell 重定向./scripts/error-reports.mjs list --all --format ndjson -o errors.ndjson ./scripts/error-reports.mjs list --format json -o errors.json按来源过滤./scripts/error-reports.mjs list --source audit-log --limit 20按类型过滤./scripts/error-reports.mjs list --kind exception-page按租户过滤./scripts/error-reports.mjs list --tenant production按后端版本过滤./scripts/error-reports.mjs list --version 2.1.0按 hint 模糊搜索./scripts/error-reports.mjs list --hint NullPointerException自动翻页抓取全部./scripts/error-reports.mjs list --all按 ID 查询单条报告./scripts/error-reports.mjs get --id 550e8400-e29b-41d4-a716-446655440000输出为 JSON./scripts/error-reports.mjs list --limit 5 --format json组合过滤来源 类型 租户./scripts/error-reports.mjs list --source audit-log --kind exception-page --tenant production --limit 50统计 突发检测 热力图./scripts/error-reports.mjs stats --from 2026-07-23T00:00:00Z --to 2026-07-23T23:59:59Z --burst --heatmap从文件做统计./scripts/error-reports.mjs stats --input errors.json从管道做统计./scripts/error-reports.mjs list --all --format json | ./scripts/error-reports.mjs stats ./scripts/error-reports.mjs list --all --format ndjson | ./scripts/error-reports.mjs stats十二、错误处理与常见问题脚本对常见失败给出了可读提示实现集中在 rpcCall现象含义应对提示创建.env并给出示例缺少PENPOT_API_URI或PENPOT_ACCESS_TOKEN按“前置条件与配置”一节补齐配置Cannot connect to server (connection refused)后端未启动或地址不可达启动后端核对PENPOT_API_URICannot resolve server hostnameENOTFOUND域名无法解析检查PENPOT_API_URI主机名HTTP 401令牌无效或已过期重新签发/刷新 tokenHTTP 403缺少error-reports:read权限执行 2.3 节的 SQL 授权语句HTTP 502 / 503 / 504后端宕机、暂不可用或网关超时确认服务状态与 URI 可达性RPC error [report-not-found]: ...指定 ID 的报告不存在核对 ID确认租户/环境正确十三、与其它脚本/命令的集成工具的管道友好性使其能无缝接入日常 shell 工作流jq 抽取字段./scripts/error-reports.mjs list --all --format ndjson | jq -c {id, hint}拉取一次、多角度统计./scripts/error-reports.mjs list --all --format ndjson | ./scripts/error-reports.mjs statsgrep / 文本搜索对表格或 NDJSON 输出做二次模式过滤--output 落盘避免大结果集在终端阻塞或丢失。十四、核心设计原则速览文档与源码共同强调了以下关键约定使用时可对照排查必须鉴权使用带error-reports:read权限的 access tokenAPI 地址可配置由.env的PENPOT_API_URI决定默认开发端口 3450默认表格输出结构化用--format json流式用--format ndjson--all必然流式只能搭配ndjson或table--all --format json会被拒绝过滤器可自由组合所有过滤参数可叠加AND 语义两种参数写法均可--optionvalue与--option value升序返回服务端按最旧在前返回与历史 DESC 行为不同翻页靠nextSince/nextId游标。十五、进一步探索仓库如需深入理解数据模型与上报链路可继续阅读以下文件工具源码与全部实现细节scripts/error-reports.mjs后端 RPC 方法、SQL 过滤与游标实现backend/src/app/rpc/commands/error_reports.clj主 API 路由注册/api/main/methods/:method-namebackend/src/app/rpc.clj访问令牌权限模型与 REPL 授权函数backend/src/app/rpc/commands/access_token.clj表结构演进相关迁移脚本0040-add-error-report-tables.sql、0101-mod-server-error-report-table.sql、0105-mod-server-error-report-table.sql、0144-mod-server-error-report-table.sql、0152-rename-version-and-add-indexes-to-server-error-report.sql依赖声明commander / dotenvpackage.json。【免费下载链接】penpotPenpot: The open-source design platform for Product teams that need scalable collaboration.项目地址: https://gitcode.com/GitHub_Trending/pe/penpot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表