恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Claude Code 插件遥测实践:内置 telemetry mod 与 `$.telemetry` 接口完全解析

  • 首页
  • 资讯中心
  • /
  • Claude Code 插件遥测实践:内置 telemetry mod 与 `$.telemetry` 接口完全解析

相关资讯

YOLOv11多任务联合训练实战:检测、分割与计数的平衡艺术 2026/9/18 21:02:22
Jaspersoft Studio 6.20.0 免注册下载安装与配置避坑指南 2026/9/18 21:02:22
YuE整曲生成实战:从歌词到完整歌曲的部署与调优 2026/9/18 21:02:22

最新资讯

条件控制与循环控制:Move 语言 `if`、`match`、`while`、`for` 与 `loop` 完全指南(aptos-core 实战版)
Node.js 18.19.0 “Hydrogen“ LTS 发布全解析:npm 10 回溯、ESM 定制钩子体系重构与测试运行器增强
AI辅助专利撰写的5大人机协同把关环节
Cursor 3 跑 Background Agent:Key 用 TaoToken
冈萨雷斯数字图像处理答案解析:从手算推导到Python验证的高效学习法
jQuery hide()与show()方法深度解析与应用实践

今日推荐

2026年AI设计工具在PPT制作中的核心应用与评测
Matlab手写逻辑回归:从数学原理到多变量概率预测模型实现
高值医用耗材研报PDF:用Python完成字段抽取、清洗与趋势预测

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

Claude Code 插件遥测实践:内置 telemetry mod 与 `$.telemetry` 接口完全解析

发布时间:2026/9/18 21:02:22
Claude Code 插件遥测实践:内置 telemetry mod 与 `$.telemetry` 接口完全解析 Claude Code 插件遥测实践内置 telemetry mod 与$.telemetry接口完全解析【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code本篇文章以 mods/telemetry/README.md 为骨架深入 Claude Code 仓库中内置的 telemetry 插件mod讲解它如何在engine.create折叠中为插件注入$.telemetrylog/mark这一分析接口单次调用即产生一行第一方遥测事件、每次调用都会重新读取环境开关与会话凭证、严格拒绝自由文本进入数据行。读完本文你将掌握$.telemetry的完整 API 契约、事件命名与数据校验规则、发送链路与关闭条件并能通过仓库源码与测试用例验证每一个行为细节。一、telemetry mod 是什么把插件分析做成一个插件Claude Code 本身内置了若干 modsec-default、diff、telemetry它们都是行为位于 hooks 模块中的完整插件随二进制一起发布见 mods/README.md。其中 telemetry mod 的职责只有一个把插件想要上报的分析事件以第一方数据行的形式接入 CLI 自身的遥测体系。它的实现方式非常克制——只做一件事一个engine.create步骤为折叠fold之上所有插件拿到手的引擎接口$添加$.telemetry它建立在底下的$.session与$.http名词之上。对应源码是 hooks/register.tsexport function register(on: On) { on(engine.create, async ($, e, next) { const beneath await next(e) const telemetry: EngineInterface[telemetry] telemetryOf({ authorize: () beneath.session.authorize(), id: () beneath.session.id(), model: () beneath.session.model(), environment: async () ({ /* 各开关环境变量 */ }), fetch: (url, init) beneath.http.fetch(url, init), }) return { ...beneath, telemetry } }) }关键点在于{ ...await next(e), telemetry }先让折叠继续向下执行得到beneath再原样展开并追加telemetry名词——底下的任何东西都不被替换$.session、$.http、$.env仍以折叠传给它的接口形式存在。telemetry mod 的清单 hooks/hooks.json 也只声明了一个模块./register.ts描述信息与 README 完全一致。它依赖$上的哪些能力README 的 What it calls on$ 一节列出了全部依赖均由折叠传下的接口提供被调用的名词用途session.authorize解析会话持有的第一方凭证每次调用重新解析session.id会话 id写入数据行session.model会话使用的模型写入数据行http.fetch将批次 POST 到事件日志采集端点env.get按字面名读取上文的开关变量以及USER_TYPE这些依赖被收拢成 hooks/telemetry-deps/telemetry-deps.ts 中定义的TelemetryDeps类型——telemetryOf只通过这五个函数接触外部世界测试也正是靠替身mock这五个函数来驱动行为的。二、$.telemetry的 API 契约log与mark$.telemetry的完整契约由 types/index.d.ts 唯一声明并通过declare module claude-code挂到EngineInterface上。README 明确指出这份声明文件是这个名词的唯一契约mod 自身的 hooks、调用该名词的其他 mod、以及应答它的测试读的都是同一份文件——实现无法与调用方看到的内容漂移。接口只有两个方法log: (entry: TelemetryLogEntry) Promisevoid mark: (entry: TelemetryMarkEntry) Promisevoid2.1$.telemetry.log({ event, props })发送一个事件每次调用发送一个事件形成一行第一方数据事件名为tengu_plugin_event。签名如下export type TelemetryLogEntry { event: string props?: ReadonlyRecordstring, TelemetryProp }契约文档给出了可直接照抄的示例await $.telemetry.log({ event: suggest_learning_survey_answered, props: { answer: 2, page: { value: ready, of: [ready, later] }, }, })调用方通常是某个内置功能模块在event中自报家门若事件名已经以tengu_开头则按原名发送不追加tengu_plugin_前缀。前缀逻辑位于 hooks/entries/fields-of/fields-of.tsname: event.startsWith(CORE_EVENT_PREFIX) ? event : EVENT_PREFIX event,其中CORE_EVENT_PREFIX tengu_core-event-prefixEVENT_PREFIX tengu_plugin_event-prefix。这保证了一个内置模块若把已有事件改名上报仍会落回它原本所在的行。2.2$.telemetry.mark({ feature, kind, reason?, props? })标记一次功能使用mark与 CLI 自身的功能事件feature event采用同一种记法事件名为tengu_feature_kind前缀由 feature-prefix 定义为tengu_feature_——这使插件打的标记与产品里所有功能进入同一张表因此不加任何前缀。export type TelemetryMarkEntry { feature: string kind: TelemetryMarkKind // ok | sad | bad reason?: string props?: ReadonlyRecordstring, TelemetryProp }契约文档中的示例await $.telemetry.mark({ feature: learn_page, kind: ok }) await $.telemetry.mark({ feature: learn_page, kind: sad, reason: blocked, })三种kind的语义在 types/index.d.ts 中有精确定义序列见 mark-kindskind含义ok功能被用上了用户得到了他想要的sad降级fallback 或部分达成用户仍得到了一些东西bad失败用户什么都没得到reason的规则是sad/bad必须带reason用 snake_case 令牌说明原因ok则禁止携带reason。行内会写入feature_namesad/bad行还会写入error_code即reason的值。这一拼装逻辑在 hooks/entries/mark-fields-of/mark-fields-of.tsname: FEATURE_PREFIX kind, props: reason undefined ? { feature_name: feature, ...props } : { ...props, feature_name: feature, error_code: reason },注意sad/bad时props被展开在feature_name、error_code之前即二者的键会覆盖同名 propsok时feature_name在最前。三、数据校验没有自由文本能到达数据行README 用一整段强调本 mod 最重要的安全属性Nothing free-form reaches a row.事件的名称与每个属性的键都必须是 snake_case 令牌属性的值只能是有限数字、布尔值或 Choice与备选列表一起声明的字符串log与mark一视同仁。任何违反规则的条目在发送之前就被拒绝refuse。3.1 名称令牌TOKEN事件名与属性键共用 hooks/entries/token/token.ts 中的规则export const TOKEN /^[a-z][a-z0-9_]{0,63}$/即以小写字母开头、仅含小写字母/数字/下划线、最长 64 字符的 snake_case 令牌。checkedFieldschecked-fields.ts与checkedMarkchecked-mark.ts分别在入口处校验event/feature/reason是否匹配该正则。3.2 属性值数字、布尔、Choice三选一checked-props 先校验props是对象且数量不超过PROP_LIMIT 16prop-limit再逐键逐值检查每个值由 checked-value 决定去留布尔值原样保留数字必须有限Number.isFinite否则拒绝——测试里专门用Number.NaN验证了这一点见 register.test.ts裸字符串直接拒绝提示free text is refused; a string is a Choice,{ value, of: [...] }Choice 对象{ value, of: [...] }of必须是 1 到CHOICES_LIMIT 32choices-limit个小写令牌choice-token 的CHOICE_TOKEN /^[a-z0-9][a-z0-9_-]{0,63}$/允许数字开头与连字符如110_to_143、merge-base且value必须是of的成员之一。拒绝抛出的错误统一由 refusal 构造格式为$.telemetry.log|mark: 原因并且只携带通过 TOKEN 校验的键名或状态码绝不回显调用方写入的自由文本export const refusal (what: string, method: Method log): Error new Error($.telemetry.${method}: ${what})3.3 拒绝即拦截不发任何东西checkedFields/checkedMark的注释写得很明确被拒绝的条目不会发送任何内容——Nothing is sent from an entry refused here: the row reaches the ingest as written, so this check is the gate between the argument and the wire. 测试 register.test.ts 用一连串非法输入非法 kind、缺 reason、ok 带 reason、非令牌名、裸字符串、非法 Choice 值、非有限数字等验证了所有拒绝路径且断言posts始终为空。四、发送链路一次调用 一次 POST4.1 核心实现telemetryOfhooks/telemetry-of/telemetry-of.ts 是发送链路的实现核心。它的post流程是读环境await deps.environment()读取用户类型与全部关闭开关每次调用都读见下文关则静默isAnalyticsOff(environment)为真时直接return——注意这里不拒绝只是不发组批次Entries.batchOf(fields, { sessionId, model, userType })组出第一方事件批次 JSON重新授权await deps.authorize()取会话凭证无凭证则拒绝throwPOSTdeps.fetch(INGEST_URL, { method: POST, headers, auth, body })响应不 ok 则拒绝。4.2 数据行形态批次由 hooks/entries/batch-of.ts 组出与 CLI 自身事件导出器exporter的批次形态完全一致——每条 POST 只含一个事件{ events: [{ event_type: ClaudeCodeInternalEvent, event_data: { event_name: fields.name, client_timestamp: new Date().toISOString(), session_id: session.sessionId, model: session.model, user_type: session.userType, additional_metadata: btoa(metadata), // props 以 base64 JSON 编码 }, }], }属性通过additional_metadatabase64 后的 JSON携带这正是导出器使用的字段。user_type取环境变量USER_TYPE为ant时记ant否则一律external见 telemetry-of.ts。采集端点硬编码于 hooks/entries/ingest-url.tsexport const INGEST_URL https://api.anthropic.com/api/event_logging/v2/batchREADME 解释了这个硬编码的缘由没有任何$名词能读会话的 API base因此生产主机名直接写在这里会话若处于其他 base 则什么都记不了——而授权门authorize gate早已让这种情况发不出去。测试 register.test.ts 断言了 POST 的地址、方法与auth句柄并用rowOffixture 逐字段核对数据行内容fixtures/row-of.ts。4.3 串行队列与每次调用重新授权README 特别强调三点运行时行为nothing batched每次调用只发一次 POST事件之间没有任何攒批rows go one after anothertelemetryOf内部用一条 promise 链queue turn.catch(() undefined)把多次调用串行化同一时刻至多一个 POST 在途credential is authorized afresh right before each POST凭证在每次 POST 之前通过$.session.authorize()重新解析绝不缓存。后一点带来一个重要的安全性质如果一个会话后来切换到了第三方 provider 或云端网关或者关掉了分析那么从那一刻起它不会再发送任何数据。测试 register.test.ts 专门验证了失败的 authorize 不会被记忆化重试即可发送——第一次授权被拒、第二次授权成功第二次调用就正常发出。反过来无第一方凭证或采集端拒绝都会让调用方的 promise 被 reject无凭证时抛this session has no first-party credential to authorize采集端返回非 ok 时抛the ingest answered status见 telemetry-of.ts 与对应测试 register.test.ts。五、什么时候什么都不发分析关闭开关全览README 明确只要 CLI 自身的分析关闭本 mod 也什么都不发。isAnalyticsOff的判定在 hooks/is-analytics-off/is-analytics-off.tsconst isPrivate isEnvSet(environment.disableTelemetry) || isEnvSet(environment.disableNonessentialTraffic) || isEnvTruthy(environment.doNotTrack) const isThirdParty [useBedrock, useVertex, useFoundry, useAnthropicAws, useAnthropicGoogleCloud, useMantle].some(isEnvTruthy) const isCustomDeployment isEnvSet(environment.customOauthUrl?.trim()) return isPrivate || isThirdParty || isCustomDeployment环境读取面在 hooks/environment/environment.ts 定义并在register.ts中按字面名逐一env.get。各类开关语义如下5.1 隐私开关任一命中即关闭DISABLE_TELEMETRY只要被设置成任意非空值就关闭0也算——isEnvSetis-env-set的定义是value ! undefined value ! 与 CLI 隐私级别读取该变量的方式一致CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC同样设置了即关闭DO_NOT_TRACK按真值判断——isEnvTruthyis-env-truthy接受1、true、yes、on四种拼写大小写不限、忽略首尾空格。5.2 第三方 provider没有第一方凭证可乘任何第三方 provider 开关为真即关闭包括CLAUDE_CODE_USE_BEDROCK、CLAUDE_CODE_USE_VERTEX、CLAUDE_CODE_USE_FOUNDRY、CLAUDE_CODE_USE_ANTHROPIC_AWS、CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD、CLAUDE_CODE_USE_MANTLE。README 的理由是这些 provider 上根本不存在第一方凭证。5.3 自定义部署CLAUDE_CODE_CUSTOM_OAUTH_URL被设置为非空值trim 后即视为自有 OAuth 部署同样关闭。测试 fixture analytics-off-environments.ts 把上述每种开关各配了一种拼写含DISABLE_TELEMETRY: 0这种容易被误认为关闭0的写法register.test.ts的对应用例L75-L107逐一验证任一开关生效期间零 POST全部清除后恢复发送。由于环境是每次调用通过$.env重新读取的开关的切换即时生效无需重启会话。六、运行位置与不可独立安装的定位README 的 Where it runs 一节给出了这个 mod 的部署边界理解它有助于避免误用本插件由 CLI 自身安置只出现在自身分析开启的内部构建internal builds上——session.authorize只在那里存在它写入的行也只进入 CLI 自身事件到达的那些表不要用--plugin-dir安装或加载它。目录里带有清单manifest只是为了让它读起来像其他插件而不是让它能独立运行对调用方而言在一个没有本 mod 的环境里调用$.telemetry会发现根本没有这个名词此时应当把这种情况当作这里没有分析no analytics here而不是崩溃或重试。从类型层面看types/index.d.ts 把telemetry声明为EngineInterface的成员同样注明仅存在于安置了 telemetry mod 的内部构建其余环境一律缺失。调用方若不确定环境应先做能力探测如检查名词是否存在再使用。七、测试验证行为即契约telemetry mod 的测试位于 mods/telemetry/tests/register.test.ts以tier(builtin)运行fixtures 放在 tests/fixtures。核心测试夹具firstPartySessionfixtures/first-party-session.ts替身式地应答session.id、session.model、session.authorize与http.fetch并收集每一次 POST 供断言recording/markingfixtures/recording.ts、fixtures/marking.ts是两个内联插件分别通过/record entry与/mark entry命令触发$.telemetry.log/$.telemetry.mark。主要覆盖场景一次log调用恰好发一行第一方数据URL、方法、auth 句柄、行内字段全部断言见 register.test.ts已以tengu_命名的事件按原名发送user_type缺省为external任一关闭开关生效期间零发送、清除后恢复第三方 provider如CLAUDE_CODE_USE_BEDROCK1不发送mark的三种 kind 各产生tengu_feature_ok/tengu_feature_sad/tengu_feature_bad行并携带feature_name与error_code非法 kind、缺失/多余的 reason、自由文本、非有限数字等全部被拒且零发送无第一方凭证被拒采集端拒绝500会让调用方 promise 被 reject失败的 authorize 不缓存重试成功即发送。运行方式遵循 mods/README.md 的通用约定claude plugin test mods/telemetry类型层面则可用tsc -p mods/tsconfig.json对全部 mod 的 hooks 与测试做类型检查——mods/tsconfig.json通过 include*/types/**/*.d.ts让其他 mod如diff里的$.telemetry.log(...)直接对照 telemetry 的契约做类型校验这正是名词契约单一来源设计的具体落地。八、小结给插件作者的三条实践要点只上报结构化数据事件名、feature、reason、属性键一律 snake_case 令牌值只能是有限数字、布尔或{ value, of }Choice自由文本会被当场拒绝且不发送。这保证了进入分析表的数据可直接聚合不携带任何用户输入的自由内容。按每次调用理解副作用环境开关、会话凭证都在每次调用时重新读取/授权调用之间串行、绝不攒批。会话中途切到第三方 provider、关掉分析或失去凭证后续调用要么静默要么拒绝。把名词缺失当作正常情况telemetry mod 只由 CLI 在内部构建上安置外部构建或未安置的环境没有$.telemetry。插件应把没有这个名词理解为此处无分析而不是依赖它必然存在需要类型时引用本 mod 的 types/index.d.ts 作为唯一契约即可。【免费下载链接】claude-codeClaude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号