# ldesign-cli-telemetry **Repository Path**: ldesign/ldesign-cli-telemetry ## Basic Information - **Project Name**: ldesign-cli-telemetry - **Description**: LDesign CLI telemetry package - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-13 - **Last Updated**: 2026-08-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # @ldesign/cli-telemetry > 隐私优先、尽力而为(best-effort)的 LDesign CLI 遥测客户端库。 ## 概述 `@ldesign/cli-telemetry` 是 LDesign 工具链(`packages/tool`)中的遥测客户端包,负责采集一次 CLI 命令运行的设备快照与运行日志,在上报前完成脱敏,并以「尽力而为」的方式发送给遥测服务端(`@ldesign/cli-telemetry-server`)。它默认开启,但所有网络路径都吞掉超时与异常,**绝不影响命令本身的退出码**。 - 纯 ESM(`type: module`)、零运行时依赖(仅使用 Node 内置模块),要求 Node >= 20.19.0。 - 本包是**库**,不注册 bin 命令;`ldesign telemetry:*` 开关命令由上游 `@ldesign/cli` 提供。 ## 安装 ```bash pnpm add -D @ldesign/cli-telemetry ``` 本包没有 bin 命令。作为 `@ldesign/cli` 的内置依赖(`workspace:*`)使用时无需单独安装;仓库内构建:`pnpm -C packages/tool/telemetry build`。 ## 特性/核心能力 - **隐私优先采集**:设备快照包含主机名、用户名、平台/内核版本/架构、CPU 核数、总内存、本地与私有网络接口;公网 IP 通过 `api.ipify.org` 探测,仅一次、500ms 短超时,失败即放弃。 - **日志脱敏**:`sanitizeLogText` 先移除 ANSI 转义序列,再把 Bearer 令牌、URL 查询参数中的密钥(token/access_token/password/secret/api_key 等)、数据库连接串密码、PEM 私钥块、`password/secret/token/api_key/authorization` 赋值统一替换为 `[REDACTED]`;超过 `maxBytes`(默认 256 KiB)截断并追加 `[TRUNCATED]`。 - **仓库地址脱敏**:`sanitizeRepositoryUrl` 只保留 http/https/ssh 形式,清除用户名、密码、查询串与锚点;`git@host:path` 转写为 `ssh://host/path`,`file:` 等形式直接丢弃。 - **尽力而为传输**:`BestEffortTransport` 默认 600ms 超时;禁用、超时、异常一律返回 `undefined`/`false`,绝不抛错。底层使用 `node:http/https` 直连(`agent: false` 禁用 keep-alive 连接池、固定 IPv4 并关闭 Happy Eyeballs 地址轮换),socket 与超时计时器均 `unref`——遥测请求无论成功、挂起还是端点不可达,都**绝不延迟宿主进程退出**。 - **会话模型**:`TelemetrySession` 生成 `runId`,依次上报 `runs/start`、`logs`、`runs/finish`;`isLongRunning: true` 时自动监听 SIGINT/SIGTERM 与 beforeExit,分别以 terminated(130/143)或 success 收尾。 - **设备注册**:本地无 `ingestToken` 时先向 `/v1/ingest/devices/register` 注册,取得的写入令牌落盘复用。 - **快速路径上报**:`notifyFastPathInvocation` 为 CLI bin 快速路径(version/help 等不加载完整 CLI 的入口)提供 fire-and-forget 记录。 - **默认开启、随时可退**:`DO_NOT_TRACK=1`、`LDESIGN_TELEMETRY=0` 或持久化 `enabled: false` 即关闭。 ## 快速上手 本包为库包,无 CLI 子命令。典型用法(在宿主工具中包裹一次命令运行): ```ts import { TelemetrySession } from '@ldesign/cli-telemetry' // 创建一次命令运行会话 const session = new TelemetrySession({ command: 'build', // 规范化命令名(必填) invokedName: 'run', // 用户实际输入的别名(可选) isLongRunning: false, // 长驻进程传 true,自动挂接信号处理 }) session.start() // 采集设备快照并上报 runs/start session.log('stdout', '开始构建...') // 日志先脱敏再上报 // ...执行你的构建逻辑... session.finish('success', 0) // 上报结束状态与退出码 ``` CLI 快速路径(如 version、help)可用: ```ts import { notifyFastPathInvocation } from '@ldesign/cli-telemetry' notifyFastPathInvocation('version', process.argv.slice(2)) ``` 关闭遥测(任一方式即可): ```bash # 方式一:@ldesign/cli 提供的命令,持久化写入本地配置 ldesign telemetry:disable # 方式二/三:环境变量(CI 中推荐) LDESIGN_TELEMETRY=0 DO_NOT_TRACK=1 ``` ## API 参考 入口 `@ldesign/cli-telemetry`(`src/index.ts` 以 `export *` 聚合四个模块)的全部导出: | 导出名 | 类型 | 说明 | | --- | --- | --- | | `TelemetrySession` | class | 一次命令运行的遥测会话;方法 `start()`、`log(stream: 'stdout'\|'stderr'\|'system', text)`、`finish(status: 'success'\|'failed'\|'aborted'\|'terminated'\|'unknown', exitCode?)`、`markReady()`;只读属性 `runId`、`startedAt` | | `TelemetrySessionOptions` | interface | 会话选项:`command`(必填)、`invokedName`、`startedAt`、`cwd`、`args`、`isLongRunning`、`endpoint`、`enabled`、`onFinish` | | `notifyFastPathInvocation` | function | `(kind: 'version'\|'root-help'\|'command-help'\|'unknown', argv?: string[]) => void`,内部 try/catch 保证快路径安全 | | `BestEffortTransport` | class | 尽力而为 HTTP 传输;`post(path, body, token?)` 返回是否成功,`postJson(path, body, token?)` 返回解析后的 JSON 或 `undefined` | | `TelemetryTransportOptions` | interface | 传输选项:`endpoint`(必填)、`enabled`(默认 true)、`timeoutMs`(默认 600) | | `resolveTelemetryConfig` | function | `(env?, configPath?) => TelemetryConfig`,合并环境变量与本地配置文件 | | `saveTelemetryConfig` | function | `(config, path?) => void`,将配置以 0600 权限写入磁盘(目录不存在则递归创建) | | `TelemetryConfig` | interface | `{ enabled, endpoint, profile, consentVersion?, installationId, ingestToken? }` | | `sanitizeLogText` | function | `(input, maxBytes = 256 * 1024) => SanitizedLog`,去 ANSI、脱敏、超长截断 | | `sanitizeRepositoryUrl` | function | `(value?: string) => string \| undefined`,清洗 git 仓库地址 | | `SanitizedLog` | interface | `{ text, redactionCount }` | ## 配置 配置文件:`~/.ldesign/runtime/telemetry-runtime.json`(由 `resolveTelemetryConfig` 读取、`saveTelemetryConfig` 以 0600 权限写入)。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `enabled` | boolean | 是否上报;缺省视为开启 | | `endpoint` | string | 上报端点;缺省 `http://home.swimly.cn:4320` | | `profile` | `'standard' \| 'enhanced'` | 采集档位;非 `'enhanced'` 一律按 `standard` 处理 | | `consentVersion` | number(可选) | 隐私同意版本 | | `installationId` | string | 安装标识;首次生成 UUID 并落盘 | | `ingestToken` | string(可选) | 设备注册后服务端签发的写入令牌 | 环境变量(优先级高于本地配置): | 变量 | 作用 | | --- | --- | | `DO_NOT_TRACK=1` | 强制关闭遥测 | | `LDESIGN_TELEMETRY=0` | 强制关闭遥测 | | `LDESIGN_TELEMETRY=1` | 即使本地配置 `enabled: false` 也强制开启 | | `LDESIGN_TELEMETRY_ENDPOINT` | 覆盖上报端点 | 上报端点路径(由服务端 `@ldesign/cli-telemetry-server` 实现):`POST /v1/ingest/devices/register`、`POST /v1/ingest/runs/start`、`POST /v1/ingest/runs/:runId/logs`、`POST /v1/ingest/runs/:runId/finish`。 ## 目录结构 ``` packages/tool/telemetry/ ├── src/ │ ├── index.ts # 导出入口:聚合 sanitize / transport / config / session │ ├── config.ts # 开关与上报目标配置(resolveTelemetryConfig / saveTelemetryConfig) │ ├── sanitize.ts # 敏感信息脱敏(sanitizeLogText / sanitizeRepositoryUrl) │ ├── session.ts # 会话上下文(TelemetrySession / notifyFastPathInvocation) │ └── transport.ts # 尽力而为网络传输(BestEffortTransport) └── test/ ├── config.test.ts ├── sanitize.test.ts ├── session.test.ts ├── transport-options.test.ts └── transport.test.ts ``` ## 相关包 本包自身零运行时依赖(package.json 无 `dependencies` / `peerDependencies`)。工作区内的真实上下游: | 包名 | 关系 | 说明 | | --- | --- | --- | | `@ldesign/cli` | 下游消费方 | 以 `workspace:*` 依赖本包;命令执行经 `TelemetrySession` 上报,`telemetry:status` / `telemetry:endpoint` / `telemetry:enable` / `telemetry:disable` 命令基于 `resolveTelemetryConfig` / `saveTelemetryConfig` 实现 | | `@ldesign/cli-telemetry-server` | 配套服务端 | NestJS 服务,实现 `/v1/ingest/*` 接口接收本包上报 | ## 本地开发 在 `packages/tool/telemetry` 目录内执行(均为 package.json `scripts` 中真实存在的命令): | 命令 | 实际执行 | 说明 | | --- | --- | --- | | `pnpm build` | `tsc -p tsconfig.json` | 编译输出到 `dist/` | | `pnpm typecheck` | `tsc --noEmit -p tsconfig.json` | 仅类型检查 | | `pnpm test` | `vitest run` | 运行 `test/` 下的测试 | ## 许可证 暂无 —— 本包 package.json 未声明 `license` 字段,包目录内也没有 LICENSE 文件。