# @arms/rum-electron 中文文档

规范地址：https://npmcn.com/package/%40arms/rum-electron/

版本：0\.0\.10-beta\.1
npm 元数据更新时间：2026-09-23T12:51:44.885Z
中文译文更新时间：2026-11-06T19:55:58.280Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40arms/rum-electron
原文对照：https://npmcn.com/package/%40arms/rum-electron/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：4.3 MB，15 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=18\.0\.0
- 运行依赖：1 个
- peer 依赖：electron \>=28\.0\.0，@trpc/server \*
- 首次发布：2026-05-07T09:55:28.139Z
- 最新版本发布：2026-09-23T12:51:44.694Z
- 近 30 天下载量：21146（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：14（近 12 个月 14 个）

## 中文简介

Electron 的 ARMS RUM SDK – 主要和渲染器进程的真正用户监测

## 安装

```sh
npm install @arms/rum-electron
```

也可以使用：`pnpm add @arms/rum-electron`、`yarn add @arms/rum-electron`、`bun add @arms/rum-electron`

## README

# @arms/rum-electron

阿里云 ARMS 用户体验监控 Electron SDK。一次主进程 `init()` 即覆盖主进程与渲染进程：自动采集异常、原生崩溃、HTTP/tRPC、应用启动指标、页面 PV、性能、Web Vitals 等数据，由主进程统一上报。

## 核心特性

-   **零配置自动注入**：主进程 `init()` 后，所有 `BrowserWindow` 自动注入 Browser SDK 与 IPC Bridge，渲染进程零改造
-   **统一上报通道**：渲染进程事件经 `arms:rum-bridge` IPC 通道回流至主进程，由主进程统一组织与上报
-   **主进程监控全覆盖**：
    -   未捕获异常、未处理 Promise 拒绝、`console.error` 拦截
    -   原生崩溃（集成 WASM `minidump-processor`，解析 `.dmp` 获取完整堆栈与模块）
    -   应用启动指标（`app ready` 耗时、进程数、主进程 CPU/内存）
    -   HTTP 请求自动采集：`globalThis.fetch` 与 `http`/`https` 模块双层 patch（覆盖 **axios 默认 adapter**、got、node-fetch 等），自动产出 `type='api'` 资源事件，附带 DNS/TCP/TLS/TTFB/下载等细分耗时
    -   tRPC server 端 procedure 调用（`type='rpc'`），通过 `armsRum.instrumentTRPC()` 一行接入
-   **内存与 OOM 监控**：运行时内存水位 + OOM 专项（`RendererOOM` / `MainProcessOOM` 回溯补报 / 双链路去重）+ memory-eviction（`MemoryEviction`，不计崩溃率）+ V8 堆高水位预警（`V8HeapNearOOM`）
-   **渲染进程自动注入**：PV、性能、Web Vitals、白屏、API、长任务等
-   **CPU Profiling（默认关闭）**：主进程自身（后台 worker + `node:inspector`，`collectors.profiling`）与渲染窗口侧（`browserCollectors.profiling`）双侧采集，支持自动轮转与手动开始/取消；采集模式、预算与离线兜底见[《Profiling 采集使用手册》](https://npmcn.com/package/%40arms/rum-electron/docs/Profiling%20%E9%87%87%E9%9B%86%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.md)
-   **分布式链路追踪**：内置 `tracing` 配置，支持 W3C tracecontext / B3 / B3 multi / Jaeger / SW8；主进程 fetch、http/https 模块与 tRPC procedure 共享同一份决策
-   **远程配置**：支持 ARMS 控制台下发配置，动态调整采样率、采集器开关等

## 安装

```bash
npm install @arms/rum-electron
```

| 依赖 | 版本要求 | 说明 |
| --- | --- | --- |
| `electron` | `>= 28.0.0` | `peerDependency`（必装），由项目自行安装 |
| `@trpc/server` | `*` | 仅在使用 `instrumentTRPC()` 时由业务侧安装（optional peer） |

> 运行环境要求 **Node >= 18**、Electron >= 28。需要 Electron 28+ 是因为 SDK 使用 `session.registerPreloadScript()`（v28 新增），低版本会自动回退到 `session.setPreloads()`。

## 快速接入

### 1\. 主进程顶层 `import` 并 `init()`

**SDK 必须在 `app.ready` 之前被 `import`**——`src/index.ts` 顶层会调用 `protocol.registerSchemesAsPrivileged()` 注册 `rum-event` 协议（占位用，预留给后续降级通道，不影响功能）。

```typescript
// main/index.ts —— 文件顶部
import armsRum from '@arms/rum-electron';
import { app } from 'electron';

armsRum.init({
  endpoint: '<your-endpoint>',  // 控制台「用户体验监控 > 应用列表」创建应用后获取
  env: 'prod',                  // 'prod' | 'gray' | 'pre' | 'daily' | 'local'
  version: '1.0.0',
});

app.whenReady().then(() => {
  // 创建 BrowserWindow 等
});
```

### 2\. 渲染进程零改造

默认 `autoInject: true`：SDK 监听 `web-contents-created`，在每个 `BrowserWindow` 的 `dom-ready` 时机注入 Browser SDK 脚本与 IPC Bridge。渲染进程**既不需要** `import` SDK，**也不需要**修改 preload。

### 3.（可选）验证数据

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  beforeReport(bundle) {
    console.log('[RUM]', bundle);
    return bundle;     // 返回 falsy（如 undefined）会丢弃整个 bundle 不上报；需保留数据必须 return bundle
  },
});
```

### 4.（可选）自定义 partition

`BrowserWindow` 使用了自定义 `partition`（如 `'persist:main'`）时，必须显式声明，否则该 partition 下的窗口不会注入 IPC Bridge：

```typescript
// 方式一：init 时声明（单 partition 推荐）
await armsRum.init({
  endpoint: '<your-endpoint>',
  partition: 'persist:main',
});

// 方式二：init 之后动态注册（多 partition 场景）
await armsRum.init({ endpoint: '<your-endpoint>' });
await armsRum.registerSession('persist:other');
```

### 5.（可选）启用 tRPC 监控

主进程使用 tRPC 定义 server router 时（如 `electron-trpc`），用 `armsRum.instrumentTRPC()` 包一层 `t`，所有 procedure 自动带监控 middleware：

```typescript
import { initTRPC } from '@trpc/server';
import armsRum from '@arms/rum-electron';

const t = armsRum.instrumentTRPC(initTRPC.create());

export const appRouter = t.router({
  greeting: t.procedure.input(...).query(...),
});
```

详见 [`docs/接入Electron应用.md`](https://npmcn.com/package/%40arms/rum-electron/docs/%E6%8E%A5%E5%85%A5Electron%E5%BA%94%E7%94%A8.md) 中的 tRPC 监控章节。

> 主进程作为 tRPC client 调用云端 HTTP 服务时**无需额外接入**：底层 fetch 或 http/https 请求会被 `ApiCollector` 自动采集为 `type='api'` 事件。

## 配置一览

`init(config)` 接收 `IElectronConfig`，继承自 `@arms/rum-core` 的 `IConfiguration`。下表为常用字段，完整版见 [`docs/Electron SDK配置参考.md`](https://npmcn.com/package/%40arms/rum-electron/docs/Electron%20SDK%E9%85%8D%E7%BD%AE%E5%8F%82%E8%80%83.md)。

### 基础

| 字段 | 类型 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| `endpoint` | `string` | 是 | — | ARMS 数据上报地址 |
| `enable` | `boolean` | 否 | `true` | 关闭后所有采集器与上报均不工作 |
| `env` | `'prod' | 'gray' | 'pre' | 'daily' | 'local'` | 否 | — | 应用环境标识 |
| `version` | `string` | 否 | — | 应用版本号 |
| `app` | `object` | 否 | — | 应用扩展信息（`name` / `channel` / `framework` 等） |
| `user` | `object` | 否 | — | 用户信息（`id` / `name` / `tags`） |

### Electron 专属

| 字段 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `autoInject` | `boolean` | `true` | 是否自动向 `BrowserWindow` 注入 Browser SDK |
| `partition` | `string` | — | 自定义 session partition；与 `BrowserWindow.webPreferences.partition` 对应 |
| `spaMode` | `false | true | 'auto' | 'hash' | 'history'` | `false` | SPA 路由追踪模式 |
| `tracing` | `boolean | ITracingOption` | — | 分布式链路追踪（主进程 fetch + tRPC procedure 共用） |
| `evaluateApi` | `(request, response, error?) => Promise<IApiBaseAttr>` | — | 自定义 API/RPC payload 解析，返回值经 `reviseApiAttr` 裁剪后合并 |
| `parseViewName` | `(url: string) => string` | — | 自定义页面 name 解析（兜底用 SpaMode 解析 URL） |
| `parseResourceName` | `(url: string) => string` | — | 自定义资源 name 解析；默认取 URL pathname |
| `beforeReport` | `(bundle) => any` | — | 上报前回调，可改写 bundle |
| `browserCollectors` | `Record<string, boolean | ICollectorConfig>` | 普通采集器启用 | 渲染进程采集器开关（仅 `autoInject` 模式生效）；渲染窗口侧 Profiling 在 `browserCollectors.profiling` 配置（不支持 `url`） |
| `documentPolicy` | `'auto' | 'manual'` | `'auto'` | ANR/Profiling 共用策略头管理；宿主已有响应头监听时选 `manual` 并显式合并，初始化后固定 |
| `properties` | `Record<string, number | string>` | — | 全局自定义属性，附加到所有上报事件 |

### 主进程管理的采集器（collectors）

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  collectors: {
    crash: false,            // 关闭崩溃采集
    consoleError: false,     // 关闭 console.error 拦截
    api: {
      enable: true,
      filters: [/\.internal\.example\.com/],   // 命中即不上报
    },
    rpc: {
      enable: true,
      filters: [/^internal\./],                // 按 procedure path 跳过
    },
    memory: {
      enable: true,                            // 默认关闭，需显式开启；OOM / eviction / 堆预警均随此总开关
      interval: 1_800_000,                     // 窗口聚合上报间隔 ms，默认 30min（最小值同样为 30min）
      onLaunch: true,                          // app ready 时发出启动基线事件
      onInterval: true,                        // 启用窗口聚合周期采集
      onCrash: true,                           // render/child-process-gone 时立即 flush
      onQuit: true,                            // before-quit 时立即 flush
      onOom: true,                             // OOM 事件分发 + 主进程 OOM 回溯补报（默认 true；eviction 不受其控制）
      crashReasons: [                          // crash flush 触发 reason 白名单（默认 6 项）
        'crashed', 'oom', 'memory-eviction',
        'abnormal-exit', 'launch-failed', 'integrity-failure',
      ],
      heapWarning: {                           // 渲染进程 V8 堆高水位预警（near_oom），默认全开
        enable: true,                          // 默认 true
        threshold: 0.85,                       // 堆使用率阈值 (0,1)，默认 0.85
        consecutiveCount: 3,                   // 连续超阈采样次数，默认 3
        sampleInterval: 10_000,                // 采样间隔 ms（下限 1s），默认 10s
      },
    },
    anr: {
      enable: true,                            // 默认关闭，需显式开启
      anrThreshold: 5000,                      // ANR 阈值 ms（3000–30000）
      captureStackTrace: true,                 // 渲染进程调用栈采集（Electron >= 34 需 Feature Flag；低版本自动走 CDP 采集）
      main: true,
      renderer: true,
    },
  },
});
```

| 采集器 | 默认 | 说明 |
| --- | --- | --- |
| `jsError` | `true` | 主进程未捕获异常 + 未处理 Promise 拒绝 |
| `consoleError` | `true` | `console.error` 拦截上报 |
| `crash` | `true` | 原生崩溃采集（依赖 `crashReporter`） |
| `application` | `true` | 应用启动指标 |
| `memory` | `false` | 内存监控总开关：运行时内存水位（10s 后台采样 / 30min 窗口聚合 + crash/quit 触发；事件附 `context` 公用环境快照）+ OOM 专项 + memory-eviction + V8 堆高水位预警，详见下文「内存与 OOM 监控」 |
| `api` | `true` | 主进程 HTTP 请求采集：`globalThis.fetch` + `http`/`https` 模块 patch，覆盖 axios 默认 adapter 等（`type='api'`，附细分耗时字段） |
| `rpc` | `true` | tRPC server middleware（配合 `instrumentTRPC`，`type='rpc'`） |
| `anr` | `false` | 应用未响应监控（主进程 worker + V8 Inspector 采集调用栈，降级为 setTimeout 探针；渲染进程心跳超时，Electron >= 34 经官方 API、低版本经 CDP 采集渲染进程调用栈） |
| `profiling` | `false` | 主进程自身 Node/V8 CPU 采样：`enable` 控制自动轮转，配置即接入手动；栈采样间隔固定 10ms；渲染窗口侧在 `browserCollectors.profiling` 配置（不支持 `url`） |

### CPU Profiling

主进程自身在 `collectors.profiling` 配置，渲染窗口侧在 `browserCollectors.profiling` 配置（不支持 `url`）；对象上传基址只接受 main 配置：

```typescript
await armsRum.init({
  endpoint: 'https://your-ingest.example/log?workspace=your-workspace&service_id=your-service',
  // 渲染域：渲染窗口侧自动轮转
  browserCollectors: { profiling: { enable: true, sampling: 100 } },
  // 主进程域：主进程自身（不开自动，手动仍可用）
  collectors: { profiling: { enable: false } },
});
```

**开启前须确认**（任一不满足都会导致无数据）：

-   须先 `init` 再创建窗口并首次导航，晚初始化不能追溯授权；endpoint 须包含 `workspace` 与 `service_id`。
-   两侧 `enable` 仅控制本域自动轮转（默认 `false`）；配置 profiling 对象即接入手动，`enable: false` 时只待命、不构造原生 Profiler 常驻，手动不受二级采样限制、但仍受全局开关与 session 一级采样约束。
-   配置不热更新：运行中 `setConfig`、晚到远端配置只在下个新文档或真实 session 生效。
-   宿主已有 `onHeadersReceived` 监听时必须 `documentPolicy: 'manual'`，并在宿主原监听中调用 `mergeSessionDocumentPolicy`，见[接入指南](https://npmcn.com/package/%40arms/rum-electron/docs/%E6%8E%A5%E5%85%A5Electron%E5%BA%94%E7%94%A8.md#document-policy-%E4%B8%8E%E5%AE%BF%E4%B8%BB%E7%9B%91%E5%90%AC%E7%BB%84%E5%90%88)。

手动采集 `armsRum.startProfiling({ target, duration, onComplete, onError })` 返回 cancel；`duration` 默认 60s、有限值限制 5000–60000；`onComplete` 表示采集完成、不表示上传成功；取消不撤回已采集片段。参数契约、错误码与排障见[《Profiling 采集使用手册》](https://npmcn.com/package/%40arms/rum-electron/docs/Profiling%20%E9%87%87%E9%9B%86%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.md)。

完整接入、`autoInject: false` 与纯合并示例见[接入指南](https://npmcn.com/package/%40arms/rum-electron/docs/%E6%8E%A5%E5%85%A5Electron%E5%BA%94%E7%94%A8.md#%E5%90%AF%E7%94%A8%E7%AA%97%E5%8F%A3%E4%B8%8E%E4%B8%BB%E8%BF%9B%E7%A8%8B-profiling)；字段与约束见[配置参考](https://npmcn.com/package/%40arms/rum-electron/docs/Electron%20SDK%E9%85%8D%E7%BD%AE%E5%8F%82%E8%80%83.md#profiling-%E9%87%87%E9%9B%86%E5%99%A8)。本期不接入 Session Replay。

### ANR 监控

`AnrCollector` 检测主进程与渲染进程的事件循环长时间阻塞（Application Not Responding），作为 `EXCEPTION` 事件上报：`exception.type='anr'`，`exception.source='main_anr'`（主进程）或 `'renderer_anr'`（渲染进程）。

-   **主进程**：独立 `worker_threads` watchdog 通过 IPC 心跳检测主线程阻塞，阻塞时经 V8 Inspector（`connectToMainThread` + `Debugger.pause`）采集主线程调用栈（`snapshots.timing='on-block'`，`snapshots.stack_source='inspector_worker'`）；worker 不可用或 Inspector 超时时自动降级为 `setTimeout` 探针漂移检测，此路径无调用栈、仅 post-block 进程快照（`snapshots.timing='post-block'`）。
-   **渲染进程**：主进程作为外部观察者，监测渲染进程经 preload 定时器发送的 IPC 心跳超时；超时后采集调用栈（`snapshots.timing='on-detect'`）——Electron >= 34 经 `webContents.mainFrame.collectJavaScriptCallStack()`（`snapshots.stack_source='collectJavaScriptCallStack'`）；Electron < 34 自动降级为 CDP 采集：SDK 预先 `webContents.debugger.attach` + `Debugger.enable`，ANR 时发送 `Debugger.pause` 打断阻塞主线程获取栈帧（`snapshots.stack_source='cdp_debugger'`）。

> ℹ️ **渲染进程心跳机制**：心跳由 SDK preload 脚本内的 `setInterval` 自主驱动，与渲染进程主线程共用同一事件循环——主线程被同步阻塞时心跳随之停发，从而被主进程 watchdog 判定为 ANR。无需主进程 `executeJavaScript` 注入。

-   **防抖与限流**：同源同窗口 120s 内最多 1 条；全局 30min 内最多 5 条；ANR 触发后 5s 恢复静默窗；被抑制次数记入 `snapshots.suppressed_count`。
-   **`caused_by`**（仅主进程，启发式推断）：系统可用内存 < 15% → `memory_pressure`；主进程 CPU > 80% → `cpu_saturation`；否则 `event_loop_blocked`。

> ⚠️ **渲染进程调用栈采集（Electron >= 34）需用户设置 Feature Flag**：在 `app.ready` 之前、`import` SDK 之前调用 `app.commandLine.appendSwitch('enable-features', 'DocumentPolicyIncludeJSCallStacksInCrashReports')`。 SDK 自动注入 `Document-Policy: include-js-call-stacks-in-crash-reports` 响应头；未设置 flag 时渲染进程 ANR 仍会上报，但 `stack` 为空。
> 
> **Electron < 34（低至 28）自动降级为 CDP 采集**，无需 Feature Flag 与 Document-Policy；若该窗口的调试会话已被 DevTools 扩展/业务代码经 `webContents.debugger` 占用，则降级为无栈事件（仅 warn 一次）。
> 
> ANR 与 Profiling 共用一个 session 策略监听。Electron 每个 session 每 event 仅允许一个 `onHeadersReceived` listener；宿主已有监听时设顶层 `documentPolicy: 'manual'` 并显式组合响应头。`autoInjectDocumentPolicy: false` 只关闭 ANR 的策略申请，不关闭 Profiling 的策略管理。SDK 不会自动识别或恢复未知宿主监听。

### 内存与 OOM 监控

`MemoryCollector`（`collectors.memory`，默认关闭，需显式开启）除运行时内存水位（启动基线 / 30min 窗口聚合 / crash / quit 多触发时机，后台采样固定 10s）外，还提供四类异常事件，均以 EXCEPTION 上报：

| 事件 | type / subtype / name | 语义 |
| --- | --- | --- |
| 渲染进程 OOM | `crash` / `oom` / `RendererOOM` | 判定三判据（满足其一）：`render-process-gone` 的 `reason='oom'`；`killed` 且 `exitCode=134`；`killed` 且系统可用内存 ≤ 10%。immediate 分发，附带崩溃时刻全进程内存现场与 `crashed_url` |
| 主进程 OOM 回溯 | `crash` / `oom` / `MainProcessOOM` | 主进程死亡无法实时上报，下次启动回溯补报；仅当上次启动异常退出且有高水位佐证（工作集 ≥ 70% 或系统可用内存 ≤ 10%）才补报，断电 / 强杀等无佐证场景自动降噪不发 |
| memory-eviction | `memory` / `eviction` / `MemoryEviction` | 渲染进程被系统因整机内存压力回收：应用整体存活，**不计入崩溃率**，可进异常列表告警；仅随 memory 总开关，与 `onOom` / `onCrash` 互不影响；同时 APPLICATION 内存指标照发（双链路） |
| V8 堆高水位预警 | `memory` / `near_oom` / `V8HeapNearOOM` | `heapUsed / heap_size_limit` 超过阈值（默认 0.85）连续 3 个采样周期（默认每 10s）触发，5min 冷却，immediate 单发；与 OOM 构成「预警 → 真死」漏斗，不计入崩溃率 |

-   **`onOom`**（默认 `true`）：控制 OOM 事件分发与主进程 OOM 回溯补报；eviction 不受其控制。
-   **`heapWarning`** 配置入口为 `collectors.memory.heapWarning`（`enable` 默认 `true`、`threshold` 默认 `0.85`、`consecutiveCount` 默认 `3`、`sampleInterval` 默认 `10s`，下限 `1s`）；`autoInject: false` 手动注入模式下需在渲染侧 browser 初始化配置 `collectors.heapWarning` 启用。
-   **独立限流**：OOM 桶 30min 内最多 5 条、eviction 桶 30min 内最多 2 条，独立分桶计数，防多窗口连续异常风暴。
-   **`system_memory` 条件附带**：仅 OOM 与 eviction 事件在应用占用系统内存 ≥ 30% 或系统可用内存 ≤ 15% 时于 `snapshots` 附带 `system_memory` 键，其余场景省略；near\_oom 不附带。
-   **Electron 42+ 双链路去重**：同一渲染进程 V8 堆 OOM，运行时链路与 crashReporter / minidump 链路经跨会话登记表去重（60s 容差）；minidump 链路未命中登记表（运行时漏报）时补发 OOM 归因的 crash 事件（`subtype='oom'`、`name='RendererOOM'`，吸收 crashpad 注解中的 JS 调用栈），避免漏采。
-   **崩溃率口径**：`type='crash'` 且 `name != 'NonFatalCrash'` 计入崩溃率；`type='memory'` 不计入；子进程（GPU / utility）崩溃不计入崩溃率，仅内存留痕。

### 渲染进程采集器（browserCollectors）

`autoInject: true` 时控制注入到渲染进程的 Browser SDK 采集器：

| 采集器 | 说明 |
| --- | --- |
| `perf` | 页面加载性能 |
| `webvitals` | Web Vitals（LCP / FID / CLS） |
| `exception` | 未捕获异常 + Promise 拒绝 |
| `whiteScreen` | 白屏检测 |
| `api` | XHR / Fetch HTTP 请求 |
| `staticResource` | 静态资源加载 |
| `click` / `action` | 用户交互 |
| `longTask` | 长任务（>50ms） |
| `profiling` | 渲染窗口侧 CPU 采样（`enable` 控制自动轮转；不支持 `url`） |

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  browserCollectors: {
    longTask: false,
    whiteScreen: false,
    api: { enable: true },
  },
});
```

### 链路追踪（tracing）

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  tracing: {
    enable: true,
    sample: 10,                                    // 10% 采样（取值 0–100）
    propagatorTypes: ['tracecontext', 'b3'],
    allowedUrls: [/^https:\/\/api\.example\.com/], // 仅向白名单注入追踪头
  },
});
```

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `enable` | `boolean` | 是否启用链路追踪 |
| `sample` | `number` | 采样率，取值 **0–100**（默认 100） |
| `propagatorTypes` | `Array<'tracecontext' | 'b3' | 'b3multi' | 'jaeger' | 'sw8'>` | 传播协议 |
| `allowedUrls` | `Array<MatchOption | TraceOption>` | 命中规则的 URL/path 才会注入追踪头；未配置时默认全量命中 |
| `tracestate` / `baggage` | `boolean` | 是否携带 W3C tracestate / baggage |

主进程 fetch 与 http/https 模块请求（`ApiCollector`）、tRPC procedure（`RpcCollector`）共用同一份 `tracing` 决策，自动在 outbound 请求注入 `traceparent` 等头。

### evaluateApi：把 payload 写入 snapshots

`evaluateApi` 用于把请求/响应内容写入事件。**SDK 不会自动采集 payload**——业务侧按需提取并经返回值 `snapshots` 上报，SDK 自动经 `reviseApiAttr` 裁剪至 5KB：

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  async evaluateApi(request, response, error) {
    const snapshot: Record<string, unknown> = {};
    if (request && typeof request === 'object' && 'input' in request) {
      snapshot.input = (request as { input?: unknown }).input;
    }
    if (response && typeof response === 'object' && 'data' in response) {
      snapshot.output = (response as { data?: unknown }).data;
    }
    return {
      success: error ? 0 : 1,
      snapshots: JSON.stringify(snapshot),
    };
  },
});
```

> 字段约定：`snapshots` 留给 SDK / `evaluateApi` 写采集元数据，`properties` 保留给用户业务标签。回调有 50ms 超时硬限，超时后回退到原始事件。

### 离线队列（offlineQueue）

普通事件上报失败（网络异常 / 超时 / HTTP 非 2xx）时，自动持久化到磁盘（`{userData}/rum-electron-store/offline-queue/`），应用重启或网络恢复后自动重发。**Profiling 对象与 metadata 除外**：不受本节配置控制，使用有界内存重试 + 独立存储落盘重放（见[《Profiling 采集使用手册》](https://npmcn.com/package/%40arms/rum-electron/docs/Profiling%20%E9%87%87%E9%9B%86%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.md)第三节）：

```typescript
armsRum.init({
  endpoint: '<your-endpoint>',
  offlineQueue: {
    enable: true,        // 默认 true
    maxAgeDays: 30,      // 最大保留天数，默认 30
    maxQueueSize: 200,   // 最大条数，默认 200，超限淘汰最旧
  },
});
```

## 运行时 API

```typescript
// 修改单个字段
armsRum.setConfig('enable', false);

// 批量修改
armsRum.setConfig({ env: 'staging', version: '1.1.0' });

// 读取当前完整配置
const config = armsRum.getConfig();

// 为额外的 partition 注册 preload（init 之后调用）
await armsRum.registerSession('persist:other');

// 一行接入 tRPC server 监控（需 @trpc/server）
const t = armsRum.instrumentTRPC(initTRPC.create());
```

### 渲染进程门面 `window.ArmsRum`

preload 脚本会在渲染进程暴露 `window.ArmsRum` 门面（不依赖 `autoInject`，preload 已加载即可用），提供 `sendCustom` / `sendView` / `sendException` / `sendResource` 四个方法，payload 经 IPC 转发至主进程，复用主进程校验与组装逻辑：

```typescript
// renderer（任意页面脚本）
window.ArmsRum?.sendCustom({ type: 'biz', name: 'checkout_click', value: 1 });
window.ArmsRum?.sendException(new Error('checkout failed'));
```

-   不依赖 Browser SDK 注入时机，页面早期即可调用；`autoInject: false` 手动注入模式下同样可用
-   兼容 `contextIsolation` 开启 / 关闭两种场景（双注入兼容）
-   普通上报在 SDK `init()` 之前会被静默丢弃；`startProfiling` 需 browser 初始化和握手完成，否则通过 `onError` 返回不可用原因，不排队至未来页面
-   SDK 增量合并门面，不覆盖已有 `sendXxx`。宿主同时冻结对象并禁止替换全局属性时无法增加方法；请预留可扩展门面或使用 browser 模块 API
-   `sendView` 的视图 URL 由 SDK 自动采集当前页面地址，payload 中的 `url` 字段会被忽略

## 注意事项

1.  **`init()` 必须在 `app.ready` 之前调用**，且 SDK 模块本身必须更早被 `import`——`src/index.ts` 顶层调用 `protocol.registerSchemesAsPrivileged()`，错过 `ready` 之前的窗口会导致协议注册失败并触发 Electron 警告。
2.  **Electron 版本 `>= 28`**：SDK 优先使用 `session.registerPreloadScript()`（v28 新增），低版本自动降级到 `session.setPreloads()`。
3.  **不要覆盖 SDK 注册的 preload**：若应用层调用 `session.setPreloads()` 覆盖全部 preload，渲染进程事件将无法回流。建议使用追加方式。
4.  **`autoInject: true` 模式下禁止在渲染进程手动 `import '@arms/rum-electron/browser'`**：会导致重复初始化与事件双采。
5.  **自定义 partition 必须显式声明**：未声明的 partition 下的窗口里 `window.ArmsEventBridge` 为 `undefined`，RUM 数据无法上报。
6.  **`evaluateApi` 内禁止同步阻塞**：回调有 50ms 超时硬限，超时后回退到原始事件不抛错。
7.  **tRPC 监控仅采 server 端**：主进程作为 tRPC client 调用云端 HTTP 时由 `ApiCollector` 在 fetch / http 模块层自动采集为 `type='api'`，不需要再包 link。
8.  **主进程原生 ESM 可用**：无打包器直接 `import` SDK 产物（如 `dist/index.mjs`）时 `@arms/rum-core` 模块解析正常（0.0.9 修复了此场景下的解析崩溃）。

## 常见问题

### @arms/rum-electron 是什么？

Electron 的 ARMS RUM SDK – 主要和渲染器进程的真正用户监测

### 如何安装 @arms/rum-electron？

在项目目录运行 npm install @arms/rum-electron，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：electron（\>=28\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @arms/rum-electron 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @arms/rum-electron 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @arms/rum-electron 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @arms/rum-electron 可以商用吗？

@arms/rum-electron 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @arms/rum-electron 的下载量有多少？

根据 npm 官方下载统计，@arms/rum-electron 在 2026/10/07 – 2026/11/05 这 30 天内被下载 21,146 次，日均约 705 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @arms/rum-electron 还在维护吗？

最新版本 0\.0\.10-beta\.1 发布于 2026/09/23（1 个月前）；至今共发布 14 个版本，其中过去 12 个月发布了 14 个；首次发布于 2026/05/07。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

