行业资讯
📅 2026/9/7 18:51:38
CodeGraph 匿名遥测系统全解析:Schema 白名单、本地日聚合与 Cloudflare Worker 全链路
CodeGraph 匿名遥测系统全解析Schema 白名单、本地日聚合与 Cloudflare Worker 全链路【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraphCodeGraph 是一个本地优先的代码知识图谱工具其核心卖点是你的代码永远不离开你的机器。要在坚持这一承诺的前提下回答哪些 Agent、哪些语言、哪些命令真正驱动了使用这类问题遥测系统就必须被设计成一句可被证明的话只采集一小段可审计的匿名计数器列表、逐字段公开文档、随时可关、且无法悄悄扩张。本文以 docs/design/telemetry.md 这份工程契约为主体结合 src/telemetry/index.ts、telemetry-worker/src/index.ts、telemetry-worker/migrations/0001_init.sql 与 telemetry-worker/src/rollup.ts 的实际实现完整讲解从客户端内存计数、本地日聚合、fire-and-forget 发送到 Worker 端白名单校验、D1 存储、夜间 rollup 与 90 天保留期清理的全链路设计。一、设计目标与非目标先划清什么绝不采集设计文档首先给出要匿名、聚合地回答的问题多少台机器在日常使用日活/周活及其变化、哪些 Agent 在驱动使用通过 MCPclientInfo识别 Claude Code、Cursor、Codex、opencode 等、用户选择哪些安装目标local vs global、fresh vs upgrade、哪些 MCP 工具与 CLI 命令被使用及错误率、哪些语言被索引用于决定提取器/框架工作的优先级、以及版本普及速度与 OS/架构/Node 构成。文档特别注明SQLite 后端现在始终是内置的node:sqlite已不存在 native-vs-wasm 之分可测。绝不采集列表同样明确这构成整个系统的负面契约永远不采源代码无文件路径、文件名、仓库名、符号名、查询串、搜索词以及任何从被索引项目内容中派生的东西无 IP 地址在边缘edge从不读取且下游不存在任何能看到 IP 的后端无第三方分析厂商事件只存入自有数据库ingest Worker 不发出任何出站请求无硬件指纹机器 ID 是随机 UUID不派生自任何硬件信息无按键/逐调用事件流使用数据先在本地聚合成日 rollup之后才可能发送私有codegraph-profork 不发遥测见第六节。四条设计原则贯穿实现Schema 即白名单。客户端只发契约列出的事件ingest Worker 按同一白名单校验并丢弃其余。新增一个字段 同时修改设计文档、面向用户的TELEMETRY.md与 Worker 白名单的同一个 PR遥测永远不许让用户付出代价MCP 工具调用热路径上零额外延迟这是该仓库的核心不变量、零新增 npm 依赖全局fetchNode ≥18、stdout 零字节输出stdio 是 MCP 协议通道、零重试、零错误噪音。每一种失败模式都是静默关闭即真关闭禁用后任何进程都不打开指向遥测端点的套接字——连已退出ping 都没有第一方端点。客户端永远只与telemetry.getcodegraph.com通信。发布到 npm 的版本把该域名烧录进去域名必须归项目所有其后端可以随时更换而无需发客户端新版本。二、事件契约信封 四种事件每个批次共享一个公共信封每进程计算一次字段示例说明machine_idb3a8…UUIDv4随机生成首次运行时铸出存于全局配置codegraph_version0.9.12来自 package.jsonos/archdarwin/arm64process.platform/process.archnode_major22仅主版本号cifalse环境变量CI是否存在schema_version2Schema 变更时递增v2 移除了index.sqlite_backend在客户端源码 src/telemetry/index.ts 中可以看到这些常量的实际定义TELEMETRY_ENDPOINT指向https://telemetry.getcodegraph.com/v1/eventsSCHEMA_VERSION 2缓冲区硬上限MAX_BUFFER_BYTES 256 * 1024单请求最多MAX_EVENTS_PER_REQUEST 100个事件默认超时DEFAULT_FLUSH_TIMEOUT_MS 1500崩溃发送方留下的 claim 文件STALE_CLAIM_MS1 小时后合并回队列。四种事件类型install— 每次安装器运行一条。属性targets如[claude,cursor]、scopelocal/global、kindfresh/upgrade/reinstall。在 src/installer/index.ts 中通过getTelemetry().recordLifecycle(install, …)记录。index— 每次完整索引init/index而不是每次sync一条。属性languages仅语言名、file_count_bucket100、100-1k、1k-10k、10k、duration_bucket10s、10-60s、1-5m、5m。注意精确计数被刻意不采集——分桶函数bucketFileCount/bucketDuration就在 src/telemetry/index.tsrecordIndexEvent只提取filesByLanguage的键名绝不携带路径、文件名或精确数量。usage_rollup— 主力事件。每台机器每个(day, kind, name)一条本地聚合。属性kindmcp_tool/cli_command、name如codegraph_explore、affected、count、error_countMCP 场景另有client_name/client_version取自initialize握手src/mcp/session.ts并在每次recordUsage调用中透传。uninstall— 每次uninstall/uninit运行一条流失信号。属性targets。一个值得展开的细节Claude Code 提示词钩子会把它的闸门决策也聚合成cli_command计数器命名为prompt-hook-gate-outcomeoutcome 取值固定为high-keyword/high-token/medium-segment/nudge-projects/noop-shape/noop-no-index/noop-unverified/noop-explore-keyword/noop-explore-token/noop-vocab-empty——只记录决策名永远不记录提示词内容。这正是该闸门实测召回率/精确率漏斗noop-*相对high/medium档位占比上升就是关键词表或分段匹配漏掉真实问题的信号high-*表示上下文确实被注入——若对应的codegraph_explore出错或返回空则改记noop-explore-triggerMEDIUM 候选命中尚未回填的分段词表则记noop-vocab-empty。客户端源码 src/bin/codegraph.ts 中recordUsage(cli_command, \prompt-hook-gate-${outcome}, true) 印证了这一机制。此外有一个遗留字段sqlite_backendnative/wasm在install和index上仍被接受schema v2 之前的旧客户端会发送但当前客户端不再发送。它永远不是required待旧客户端占比可忽略后即可从 Worker 移除。量级数学由于是 rollup月事件量 ≈ 活跃机器数 × 活跃天数 × 使用的工具种类个位数——设计上就没有逐调用事件。文档给出的运算是约 97k 接受的 POST/天 ≈ 30M 行 D1 写入/月对 Workers Paid 包含的 50M保留期清理达到稳态后删除与插入同价约升至 48M。真正的约束是存储而非写入原始事件约 74 MB/天增长90 天窗口 ≈ 6.7 GB撞 D1 单库 10 GB 上限——这就是保留窗口定为 90 天的原因。完整算术写在 telemetry-worker/migrations/0001_init.sql 的尾部注释中。系统里不存在任何人的画像可退出machine_id是唯一标识符由客户端铸出的随机 UUID唯一机器数直接在 SQL 中从它计算。三、同意与控制优先级、配置面与 CLI解析顺序首个命中生效在 src/telemetry/index.ts 的getStatus()中逐条实现DO_NOT_TRACK1社区标准永远优先→ 关CODEGRAPH_TELEMETRY0|1→ 对该进程强制关/开注意实现中0/false视为关其余非空值视为开全局配置~/.codegraph/telemetry.json→ 存储的用户选择默认开由首次运行通知把关。三个交互面安装器交互式现有提示流中一个可见的 clack 开关——Share anonymous usage data? (no code, paths, or names — see TELEMETRY.md)——默认 yes。选择以consent_source: installer持久化重跑/升级尊重已存选择不再追问。无头路径npx codegraph init、MCP server——无 TTY绝不弹窗在第一次真正发送之前记录只是本地缓冲、保持静默因此安装器的显式开关永远先于任何通知出现向stderr打印一行并记录first_run_notice_showncodegraph collects anonymous usage stats (no code, paths, or names) — codegraph telemetry off or CODEGRAPH_TELEMETRY0 disables. Details: TELEMETRY.mdCLIcodegraph telemetry status|on|offstatus 打印机器 ID、当前状态及决策来源。删除~/.codegraph/telemetry.json可重置一切包括机器 ID。配置文件结构面向用户文档 TELEMETRY.md 与实现一致{ enabled: true, machine_id: uuid-v4, consent_source: installer | default-notice | cli, first_run_notice_shown: true, updated_at: 2026-06-12T00:00:00Z }~/.codegraph/目录是遥测引入的新全局目录此前不存在任何全局数据若用户索引$HOME本身它与按项目存放在project/.codegraph/的数据因文件名不同而互不冲突。从用户视角的操作方式见 TELEMETRY.mdcodegraph telemetry off存储选择并删除所有未发送数据export CODEGRAPH_TELEMETRY0做按 shell/按 CI 覆盖export DO_NOT_TRACK1是跨工具标准永远生效。codegraph telemetry status显示当前状态、决策来源与机器 ID。关就是关禁用后不记录、不连接、不发任何已退出ping。另外独立于遥测MCP server 每天至多一次在后台检查 GitHub 上的新版本号只取版本号不发送任何机器信息DO_NOT_TRACK1也会禁用它仅关更新检查可用CODEGRAPH_NO_UPDATE_CHECK1。四、客户端架构内存计数器 JSONL 缓冲 机会性 flush新模块 src/telemetry/index.ts 是单一小模块、零依赖围绕四条不变量文件头注释逐条列出零热路径开销、零 stdout、关即真关、失败静默实现1. 内存计数器。记录一次工具调用/CLI 命令就是内存自增。热路径上什么都不落盘、不碰网络。MCP 工具处理器调用telemetry.count(mcp_tool, name, ok)后继续。对应源码中 src/mcp/session.ts 的recordUsage(mcp_tool, toolName, !result.isError, this.clientInfo)与 CLI 侧 src/bin/codegraph.ts 的recordUsage(cli_command, name, true)。2. 缓冲。计数器防抖异步持久化到~/.codegraph/telemetry-queue.jsonl每行是一个压缩字段的小 JSONCountLined日、k类型、n名称、c次数、e错误数、cn/cv客户端名/版本或EventLine生命周期事件。硬上限约 256 KB溢出时丢最旧行appendLines中先截断再丢弃不完整的半行缓冲损坏 → 截断绝不抛错。3. Flush 策略——为process.exit()而设计。很多 CLI 动作以process.exit()结束此时beforeExit永不触发、异步发送必死。因此设计是在process.on(exit)上做一次微小的同步追加persistSync()可存活于process.exit真正的网络发送机会性发生——长运行命令init/index/sync/uninit/upgrade启动时、MCP server/daemon 上 unref 的 6 小时间隔startIntervalsrc/mcp/index.ts 中启动、以及install/init/index/uninit结尾处有上限的 await一秒不可见之处。发送 POST 已完成 UTC 天的 rollup 生命周期事件到https://telemetry.getcodegraph.com/v1/events带AbortSignal.timeout(1500)fire-and-forget任何响应或没有响应都是终局——不重试、不冒泡错误。实现上flushNow()只发送今天之前的计数行与全部生命周期事件当天的行留在队列队列通过原子 rename 抢占telemetry-queue.sending.pid.jsonl并发进程不会重复发送崩溃的发送方留下的 claim 在 1 小时后被recoverStaleClaims合并回队列。开发调试可用CODEGRAPH_TELEMETRY_DEBUG1把 payload 回显到 stderr。4. 离线/隔离网环境。flush 静默失败缓冲保持在容量内稳态是一个有界文件 零噪音。同意闸门的一个精妙之处firstRunNotice()上方注释一次性通知严格先于离开机器的第一个字节并在那里铸出机器 ID。由于记录只是本地缓冲保持静默——这保证安装器能先展示其显式同意开关而不是让 preAction 使用计数抢先触发通知显式的安装器/CLI 选择会置first_run_notice_shown并永久抑制该通知。五、Ingest Worker白名单校验、无出站请求、fail-silent 写入telemetry.getcodegraph.com背后是仓库内的 telemetry-worker/——刻意公开让任何人都能审计端点到底存了什么。它不随 npm 包分发被files白名单排除部署配置见 telemetry-worker/wrangler.jsonc路由绑定telemetry.getcodegraph.com自定义域名workers_dev: false唯一公开面就是文档里那个域名D1 数据库codegraph-telemetry绑定为env.DBcron 触发器30 0 * * *00:30 UTCRETENTION_DAYS: 90以及每分钟每machine_id6 次的MACHINE_RATE_LIMITER合法客户端每天只 flush 几次6/min 吸收 installindex 突发同时压住滥用。POST /v1/events的处理流程telemetry-worker/src/index.ts白名单校验EVENTS表是那份白名单与设计文档逐条镜像——未知事件整体丢弃未知属性剥离每个属性带 sanitizertokenArraytargets/languages条目数与字符集受限、oneOfscope/kind/分桶枚举、nonNegIntcount ≤ 1,000,000、label客户端名/版本可含空格与/。时间戳经过clampTimestamp钳制未来超过 10 分钟、过去超过 30 天的一律拒绝离线缓冲会迟到但不接受不可信时间。边界machine_id必须匹配 UUIDv4 正则body 上限 64 KB、单批最多 100 事件按machine_id做最佳努力限流限流器不可用时 fail-open——丢数据点优于丢可用性。永不读取客户端 IP——源码中不存在任何读取 request IP 的路径。写入在响应路径之外ctx.waitUntil(writeToD1(...))一次batch() 一个隐式事务 一次往返。每条事件一行events外加machine_daysmachine × day 活动矩阵prod列用max语义只有当天该机器所有事件都带ci1才为 0与machine_first_seen离线迟到缓冲可把首见日推早min语义绝不推晚。刻意 fail-silentD1 错误只以计数记日志绝不记 payload客户端照样收到 204。因为客户端从不重试丢一个数据点优于牺牲可用性。响应接受即 204包括全部事件被白名单丢弃的情况格式错误/超大/限流返回诚实的 4xx。客户端把任何响应视为终局从不重试。存储 Schema 全量公开在 telemetry-worker/migrations/0001_init.sql每列带注释。核心表events原始事件。刻意不加CHECK (event IN (...))约束——Worker 的白名单才是唯一真相来源而写入路径按设计 fail-silent被拒绝的 INSERT 会静默丢数据而非显式报错。索引只有(day, event)与(machine_id, day)两个注释明确警告 D1 按每触碰一个索引多计一次行写入计费所以每个索引约等于 97k 写入/天加第三个前必须重查量级注释daily_machines/daily_event_counts/daily_dim_counts夜间 cron 写入、dashboard 读取的 rollup 表永久保留。daily_dim_counts是通用(dim, value)表——新增一个 breakdown 是改一行 cron而不是迁移。注释列出了每个dim服务的图表os、arch、version、language、target、scope、kind、name、client_name 等machine_days/machine_first_seen永不清理——留存队列需要完整历史且比原始行小两个数量级。夜间 crontelemetry-worker/src/rollup.ts00:30 UTC 由 wrangler.jsonc 触发做两件事Roll up把刚完成的 UTC 日以及前两天的——离线客户端会迟到地发送已完成天的 rolluproll 进daily_machines、daily_event_counts、daily_dim_counts。全部聚合是 D1 内部的INSERT … SELECT … ON CONFLICT DO UPDATE——没有事件行跨网络传输重跑某天是幂等 no-op 而非双计。一个关键细节usage_rollup行本身是客户端预聚合的计数器所以count维度必须SUM(json_extract(props,$.count))而不是数行——数行会把量级低估一个数量级Purge删除超过RETENTION_DAYS90 天的原始events按 5000 行/批、单晚最多 60 批的有界 keyset 删除推进。Rollup 与machine_days/machine_first_seen永久保留所以缩短窗口只损失 ad-hoc 回溯从不损失图表。此外还有POST /admin/rollup回填补丁口仅在ADMIN_TOKENsecret 配置时存在否则直接 404用 SHA-256 摘要 timingSafeEqual做常量时间 token 比较支持?dayYYYY-MM-DD[daysN][reset1]最多 31 天。reset1会先删除当日事件派生的 rollup 行再重算用于维度列表变更时的修复但越过保留窗口的日期会忽略 reset——那会是这个文件唯一不可逆的错误操作。部署、迁移、cron 与 D1 配额算术的运维细节在 telemetry-worker/README.md。六、Admin Dashboard 与 codegraph-pro 规则stats.getcodegraph.com是第二个 Workertelemetry-dashboard/读侧同样是公开源码——接触遥测的代码应能被采集它的人读懂。要点同一 D1 数据库只读从不迁移、从不写两个 Worker 是独立部署仅按约定共享一份维度名清单——这正是 telemetry-worker/scripts/smoke-cutover.sh 存在的原因那边不匹配是静默的表现为某个面板永远读零而非报错读 rollup 而非原始事件所以对原始行已被清掉的日期图表依然正确。唯一例外是/api/activation——这台机器是否运行过 index不是日聚合因此读原始events受保留窗口约束并以raw_events_from报告这一点认证是共享密码 签名 cookie规模按恰好两个人设计ADMIN_PASSWORDSESSION_SECRET作为 Worker secrets常量时间比较、HMAC 签名 cookie、无 session 存储、除/login与robots.txt外全部拦截。轮换密码即全员登出——这就是撤销机制这个 Worker 会读客户端 IP唯一用途是登录限流 key从不存储、从不记录——与 ingest Worker根本不读 IP的唯一刻意差异。codegraph-pro 规则不要在上游合并中丢失这一条私有codegraph-profork 随客户容器分发其保证是什么都不离开盒子——包括遥测。在 fork 中遥测必须默认关闭且安装器无法开启编译期常量或剥离模块容器另设CODEGRAPH_TELEMETRY0双保险。该规则写进 fork 的 CLAUDE.md且必须存活于每次上游合并。七、灰度路径与测试基线文档给出的上线顺序(1) 设计文档 仓库根TELEMETRY.md逐字段用户列表 README 章节(2) Worker DNS 先上线保证第一个发货的客户端永不 404随后 dashboard Worker 接同一 D1周活机器、按目标的安装、按工具 × 客户端的使用、版本普及、被索引语言(3) 客户端模块 配置 codegraph telemetry子命令 MCPclientInfo管道(4) 安装器开关 首次运行通知CHANGELOG 在[Unreleased]下公告遥测、默认值与每一个关闭开关发布。测试约定不 mock 数据库fetch 在globalThis.fetch处 mock覆盖同意优先级env config default、off ⇒ 零 fetch 调用、跨天 rollup 聚合、缓冲上限 损坏缓冲恢复、MCP 传输下无 stdout 不变量、flush abort 遵守超时、安装器开关持久化 重跑不追问。仓库内对应tests/telemetry.test.ts——其文件头直接声明固定 docs/design/telemetry.md 的四条不变量零 stdout、关即真关无 socket 无文件、失败静默、仅发送已完成天的本地 rollup全部注入缝dir、fetch、时钟、env、stderr不触网、不碰真实 home 目录另按仓库惯例安装器开关持久化测试在tests/installer-targets.test.ts。八、遗留问题文档末尾保留了三个开放问题可视为该契约的演进方向安装器文案/通知措辞的最终定稿发布前维护者拍板uninstall事件去留诚实的流失信号 vs. 临走还要 ping 一下的观感CI 事件保留ci: true打标因为引擎跑在 CI 里是真实使用模式——若其占比主导量级则重议。小结这套设计可复用的几条原则以 docs/design/telemetry.md 为契约、以 src/telemetry/index.ts 与 telemetry-worker/ 为两端实现CodeGraph 的遥测给出了一个隐私友好遥测的完整参考样本白名单而不是黑名单schema 同时是客户端契约与服务端校验器新增字段必须一次 PR 改三处本地预聚合逐调用事件在客户端就坍缩为(day, kind, name)计数器量级从调用数降到机器数 × 天数 × 工具数为process.exit()设计持久化同步小写在exit钩子、机会性发送、原子 rename 抢占、陈旧 claim 回并——离线与并发都不出错端到端 fail-silent客户端任何失败是静默Worker 写入失败只记计数客户端从不重试——丢数据点优于丢可用性是显式取舍可审计 承诺Worker 源码、存储 Schema、rollup 与清理逻辑全部在仓库内公开保留什么由 telemetry-worker/migrations/0001_init.sql 逐列注释回答而不是靠口头保证让保留期由数学决定74 MB/天 × 90 天 ≈ 6.7 GB 撞上 D1 的 10 GB 单库上限于是 90 天窗口被写下rollup 永久保留使缩短窗口只损失回溯、不损失图表。读者可以按 TELEMETRY.md 用codegraph telemetry status|off验证自己机器上的状态也可以直接阅读 ingest Worker 与迁移 SQL逐字段核对到底存了什么——这正是该文档要求系统做到的可证明。【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考