@blueking/open-telemetry 0.0.20 → 0.0.22-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +11 -25
  2. package/dist/bk-rum.global.js +2 -12
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/config.d.ts +8 -44
  5. package/dist/core/hash.d.ts +2 -0
  6. package/dist/core/plugin.d.ts +2 -7
  7. package/dist/core/processor.d.ts +0 -20
  8. package/dist/core/sdk.d.ts +1 -7
  9. package/dist/core/telemetry-attributes.d.ts +1 -2
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +1045 -1463
  12. package/dist/index.js.map +1 -1
  13. package/dist/plugins/common.d.ts +1 -1
  14. package/dist/plugins/csp-violation.d.ts +0 -8
  15. package/dist/plugins/error.d.ts +1 -5
  16. package/dist/plugins/long-task.d.ts +1 -3
  17. package/dist/plugins/web-vitals.d.ts +1 -4
  18. package/dist/schema/attributes.d.ts +8 -10
  19. package/dist/schema/span.d.ts +2 -0
  20. package/package.json +2 -6
  21. package/skills/bk-rum-otele/SKILL.md +9 -5
  22. package/skills/bk-rum-otele/evals/evals.json +2 -2
  23. package/skills/bk-rum-otele/references/api.md +10 -22
  24. package/skills/bk-rum-otele/references/architecture.md +38 -118
  25. package/skills/bk-rum-otele/references/capabilities.md +26 -28
  26. package/skills/bk-rum-otele/references/concepts.md +14 -106
  27. package/skills/bk-rum-otele/references/configuration.md +25 -66
  28. package/skills/bk-rum-otele/references/custom-plugin.md +10 -13
  29. package/skills/bk-rum-otele/references/data-model.md +23 -95
  30. package/skills/bk-rum-otele/references/getting-started.md +1 -1
  31. package/skills/bk-rum-otele/references/plugins-basic.md +135 -0
  32. package/skills/bk-rum-otele/references/plugins-error-security.md +86 -0
  33. package/skills/bk-rum-otele/references/plugins-experience.md +124 -0
  34. package/skills/bk-rum-otele/references/plugins-network.md +32 -0
  35. package/skills/bk-rum-otele/references/plugins.md +3 -486
  36. package/skills/bk-rum-otele/references/privacy.md +4 -25
  37. package/skills/bk-rum-otele/references/telemetry-reference.md +49 -243
  38. package/skills/bk-rum-otele/references/transport-sampling.md +15 -50
  39. package/skills/bk-rum-otele/references/troubleshooting.md +7 -34
  40. package/dist/core/metric.d.ts +0 -2
  41. package/dist/core/signal.d.ts +0 -3
  42. package/dist/core/throttle.d.ts +0 -20
  43. package/dist/plugins/request-body.d.ts +0 -15
@@ -8,5 +8,5 @@ interface RequestDetails {
8
8
  url?: string;
9
9
  }
10
10
  export { REQUEST_DISCARD_ATTRIBUTE };
11
- export declare const decorateRequestSpan: (context: BkOTRuntimeContext, span: Span, subtype: "fetch" | "xhr", domainContext: BkOTRequestContext, details?: RequestDetails, fetchRequest?: Request | RequestInit) => void;
11
+ export declare const decorateRequestSpan: (context: BkOTRuntimeContext, span: Span, subtype: "fetch" | "xhr", domainContext: BkOTRequestContext, details?: RequestDetails) => void;
12
12
  export declare const createCommonInstrumentationsPlugin: (option: BkOTRequestConfig | boolean | undefined) => BkOTPlugin;
@@ -3,14 +3,6 @@ import type { BkOTPlugin } from '../core/plugin';
3
3
  * CSP 违规事件采集插件,通过监听 `securitypolicyviolation` 事件捕获被 CSP 策略拦截的脚本/资源,
4
4
  * 以 error span 上报,进入统一错误分析口径。
5
5
  *
6
- * 节流策略:
7
- * - 同 fingerprint(`violatedDirective + blockedURI + sourceFile + lineNumber`)
8
- * 在 60s 窗口内最多上报 5 条,避免风暴打爆 collector(如某段被拦截的 inline 脚本被反复渲染)。
9
- * - `browser.csp_violation.count` counter 在节流前累计所有违规,span 只保留窗口触发序号。
10
- *
11
- * 体积优化:
12
- * - `csp.original_policy`(完整 CSP 策略,可能数 KB)仅在窗口首条上报,后续同 fingerprint 不再重复携带。
13
- *
14
6
  * URL 处理:
15
7
  * - `blockedURI` / `sourceFile` 中的 URL 类值会经 `redactUrl` 脱敏。
16
8
  * - `blockedURI` 是 'inline' / 'eval' 等 CSP 关键字时直接保留,不调用 redactUrl。
@@ -1,6 +1,2 @@
1
1
  import type { BkOTPlugin } from '../core/plugin';
2
- export interface BkOTErrorPluginOptions {
3
- maxPerWindow?: number;
4
- windowMs?: number;
5
- }
6
- export declare const createErrorPlugin: (options?: BkOTErrorPluginOptions) => BkOTPlugin;
2
+ export declare const createErrorPlugin: () => BkOTPlugin;
@@ -1,12 +1,10 @@
1
1
  import type { BkOTPlugin } from '../core/plugin';
2
2
  /**
3
3
  * 主线程阻塞优先使用 Long Animation Frame API 获取脚本归因,不支持时回退到 Long Tasks API;
4
- * span 保留单次诊断详情,metric 只保留低基数维度用于聚合分布。
4
+ * span 保留单次诊断详情,分布与计数由服务端从原始事件计算。
5
5
  */
6
6
  export interface BkOTLongTaskPluginOptions {
7
7
  /** 采集阈值,默认 50ms。Performance API 本身通常只产生大于 50ms 的条目。 */
8
8
  threshold?: number;
9
- /** 标记 warning 的阈值,默认 100ms。 */
10
- warningThreshold?: number;
11
9
  }
12
10
  export declare const createLongTaskPlugin: (options?: BkOTLongTaskPluginOptions) => BkOTPlugin;
@@ -4,10 +4,7 @@
4
4
  * 基于 google/web-vitals 库(attribution 版本)采集 Core Web Vitals:
5
5
  * CLS / FCP / INP / LCP / TTFB
6
6
  *
7
- * 维度分层(关键设计):
8
- * - metric (histogram):仅带低基数维度(`view.url_path_group` / navigation.type / vital.name / vital.rating),
9
- * 适合做 P50 / P75 / P99 聚合统计,避免维度爆炸
10
- * - span (browser.web_vital):带 vital.id(唯一)、vital.value 与 attribution 详情
7
+ * browser.web_vital span 带 vital.id(唯一)、vital.value 与 attribution 详情
11
8
  * (LCP 元素 url / CLS shift target / INP interaction target 等高基数字段),
12
9
  * 方便按个例排查"哪个元素拖累了 LCP"
13
10
  *
@@ -4,14 +4,10 @@
4
4
  * 插件里不要散落硬编码字符串,后续字段命名调整只改这里,避免采集端与字段文档逐步漂移。
5
5
  */
6
6
  export declare const RUM_ATTRIBUTES: {
7
- readonly actionErrorCount: "action.error.count";
8
- readonly actionFrustrationCount: "action.frustration.count";
9
7
  readonly actionFrustrationType: "action.frustration.type";
10
8
  readonly actionId: "action.id";
11
9
  readonly actionLoadingTime: "action.loading_time";
12
- readonly actionLongTaskCount: "action.long_task.count";
13
10
  readonly actionName: "action.name";
14
- readonly actionResourceCount: "action.resource.count";
15
11
  readonly actionTargetName: "action.target.name";
16
12
  readonly actionTargetTag: "action.target.tag";
17
13
  readonly actionType: "action.type";
@@ -22,17 +18,15 @@ export declare const RUM_ATTRIBUTES: {
22
18
  readonly deviceLogicalProcessorCount: "device.logical_processor_count";
23
19
  readonly deviceMemoryGib: "device.memory_gib";
24
20
  readonly deviceType: "device.type";
21
+ readonly eventId: "event.id";
22
+ readonly eventPhase: "event.phase";
23
+ readonly eventTimestamp: "event.timestamp";
24
+ readonly eventType: "event.type";
25
25
  readonly errorType: "error_type";
26
- readonly exceptionFingerprint: "exception.fingerprint";
27
- readonly exceptionMessageShort: "exception.message_short";
28
- readonly exceptionStackTopFrame: "exception.stack_top_frame";
29
26
  readonly longTaskBlockingDuration: "long_task.blocking_duration";
30
- readonly longTaskCulprit: "long_task.culprit";
31
27
  readonly longTaskDuration: "long_task.duration";
32
28
  readonly longTaskEntryType: "long_task.entry_type";
33
29
  readonly longTaskId: "long_task.id";
34
- readonly longTaskIsFrozenFrame: "long_task.is_frozen_frame";
35
- readonly longTaskScriptCount: "long_task.script.count";
36
30
  readonly longTaskStartTime: "long_task.start_time";
37
31
  readonly networkEffectiveType: "network.effective_type";
38
32
  readonly nextHopProtocol: "resource.protocol";
@@ -43,7 +37,9 @@ export declare const RUM_ATTRIBUTES: {
43
37
  readonly osName: "os.name";
44
38
  readonly sessionHasReplay: "session.has_replay";
45
39
  readonly sessionId: "session.id";
40
+ readonly sessionSampleRate: "session.sample_rate";
46
41
  readonly sessionStartTime: "session.start_time";
42
+ readonly sessionType: "session.type";
47
43
  readonly spanSubtype: "span_subtype";
48
44
  readonly spanType: "span_type";
49
45
  readonly userId: "user.id";
@@ -59,7 +55,9 @@ export declare const RUM_ATTRIBUTES: {
59
55
  readonly viewLoadingTime: "view.loading_time";
60
56
  readonly viewLoadingType: "view.loading_type";
61
57
  readonly viewName: "view.name";
58
+ readonly viewStartedAt: "view.started_at";
62
59
  readonly viewUrl: "view.url";
63
60
  readonly viewUrlPathGroup: "view.url_path_group";
61
+ readonly viewVersion: "view.version";
64
62
  };
65
63
  export type RumAttributeKey = (typeof RUM_ATTRIBUTES)[keyof typeof RUM_ATTRIBUTES];
@@ -14,7 +14,9 @@ export declare const RUM_SPAN_TYPE: {
14
14
  readonly longtask: "longtask";
15
15
  readonly resource: "resource";
16
16
  readonly route: "route";
17
+ readonly session: "session";
17
18
  readonly vital: "vital";
19
+ readonly websocket: "websocket";
18
20
  };
19
21
  export interface RumResourceSpanInput {
20
22
  initiatorType?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueking/open-telemetry",
3
- "version": "0.0.20",
3
+ "version": "0.0.22-beta.1",
4
4
  "description": "OpenTelemetry browser SDK for BK RUM",
5
5
  "author": "TencentCloud Real User Monitoring",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,7 @@
14
14
  "scripts": {
15
15
  "prepublishOnly": "pnpm build && pnpm dts && pnpm skill:refs",
16
16
  "skill:refs": "node scripts/gen-skill-references.mjs",
17
+ "test:skill-refs": "node --test tests/gen-skill-references.test.mjs",
17
18
  "build": "vite build && vite build --mode cdn && pnpm dts",
18
19
  "build:cdn": "vite build --mode cdn",
19
20
  "build:esm": "vite build",
@@ -26,16 +27,11 @@
26
27
  },
27
28
  "dependencies": {
28
29
  "@opentelemetry/api": "^1.9.1",
29
- "@opentelemetry/api-logs": "^0.217.0",
30
30
  "@opentelemetry/context-zone": "2.7.1",
31
31
  "@opentelemetry/core": "^2.7.1",
32
- "@opentelemetry/exporter-logs-otlp-http": "^0.217.0",
33
- "@opentelemetry/exporter-metrics-otlp-http": "^0.217.0",
34
32
  "@opentelemetry/exporter-trace-otlp-http": "^0.217.0",
35
33
  "@opentelemetry/instrumentation": "^0.217.0",
36
34
  "@opentelemetry/resources": "^2.7.1",
37
- "@opentelemetry/sdk-logs": "^0.217.0",
38
- "@opentelemetry/sdk-metrics": "^2.7.1",
39
35
  "@opentelemetry/sdk-trace-base": "^2.7.1",
40
36
  "@opentelemetry/sdk-trace-web": "^2.7.1",
41
37
  "@opentelemetry/semantic-conventions": "^1.38.0",
@@ -27,7 +27,11 @@ description: 帮助业务方在前端应用里接入、使用和配置蓝鲸 RUM
27
27
  | 搞懂三类信号、Instrumentation vs Plugin、采样、数据归一、运行时上下文 | `references/concepts.md` |
28
28
  | 查配置项、默认值、Endpoint、插件参数和 Hook | `references/configuration.md` |
29
29
  | 查 Transport、单信号开关、批量上报、Session 采样和 traceparent 透传 | `references/transport-sampling.md` |
30
- | 开关某个采集能力、看请求配置和各插件参数(request/error/blankScreen/longTask/websocket 等) | `references/plugins.md` |
30
+ | 了解插件默认组合、启用规则和能力分类 | `references/plugins.md` |
31
+ | 配置 Session、Device、View、Action | `references/plugins-basic.md` |
32
+ | 配置 Resource、Web Vitals、Blank Screen、Long Task、View Loading Time | `references/plugins-experience.md` |
33
+ | 配置 Error、CSP Violation 和错误上报 | `references/plugins-error-security.md` |
34
+ | 配置 Fetch/XHR Request、HTTP Body、Trace Header、WebSocket | `references/plugins-network.md` |
31
35
  | 写自定义插件、接入第三方 OpenTelemetry instrumentation | `references/custom-plugin.md` |
32
36
  | 查公开 API(start/flush/shutdown/setUser/setView/reportAction/reportCustomEvent 等) | `references/api.md` |
33
37
  | Vue / React / Vue Router / 微前端 集成 | `references/framework-integration.md` |
@@ -91,7 +95,7 @@ CDN:
91
95
  </script>
92
96
  ```
93
97
 
94
- `transport.endpoint` 可提供上报根地址(不含路径前缀),SDK 自动拼 `/v1/rum`、`/v1/metrics`、`/v1/logs`;若通过 `transport.signals.{traces|metrics|logs}.endpoint` 自定义某一类地址,则该信号使用完整 URL,不再拼接。当所有已开启信号都有独立地址时,根 endpoint 可省略。三类信号可分别设为 `false` 关闭,但不能全部关闭。`token` 作为 `Authorization: Bearer <token>` 默认头。构造后默认 `autoStart: true` 自动启动,无需手动 `start()`。
98
+ `transport.endpoint` 是必填上报根地址(不含路径前缀),SDK 自动拼 `/v1/rum`。SDK 不创建 Metric/Log Provider,所有原始 RUM 事件统一走 Trace Span。`token` 作为 `Authorization: Bearer <token>` 默认头。构造后默认 `autoStart: true` 自动启动,无需手动 `start()`。
95
99
 
96
100
  ## 默认采集能力清单
97
101
 
@@ -99,16 +103,16 @@ CDN:
99
103
 
100
104
  - 基础能力:Session、View;内置采集:`request`、`action`、`resource`、`error`、`webVitals`、`blankScreen`、`device`
101
105
 
102
- View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`cspViolation`、`websocket`。关闭默认能力时显式设为 `false`。各插件参数见 `references/plugins.md`。
106
+ View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`cspViolation`、`websocket`。关闭默认能力时显式设为 `false`。各插件参数按「任务路由」读取对应 `plugins-*.md`。
103
107
 
104
108
  ## 关键易错点
105
109
 
106
110
  - **单实例**:`fetch`/`xhr`/`action`/`websocket` 会 patch 或监听全局 API,同页面只应初始化一个 SDK 实例,微前端只在主应用初始化一次。
107
111
  - **`use()` / `useInstrumentation()` 必须在 `start()` 之前**:要注册自定义插件或 instrumentation,请设 `autoStart: false` 再手动 `start()`。
108
112
  - **采样影响手动上报**:未命中采样时 `reportAction()` / `reportCustomEvent()` 静默丢弃,排查时先确认采样。
109
- - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;HTTP body 默认关闭,显式配置 `request.body` 时必须提供 `redact`,默认只采集错误请求;`user.id` 需 hash 的话要在传入前处理。
113
+ - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;SDK 不采集 HTTP Body;`user.id` 需 hash 的话要在传入前处理。
110
114
  - **Consent**:未授权初始化时配置 `privacy.trackingConsent: 'not-granted'`,用户授权后调用 `setTrackingConsent('granted')`;撤销授权会停止采集并解除 patch。
111
- - **信号开关**:`transport.signals.traces/metrics/logs` 设为 `false` 可关闭对应导出链路;关闭 Trace 后不会注入 `traceparent`。只开 Metric 时没有精确 View 下钻。
115
+ - **单一信号**:只有 `/v1/rum` Trace 通道;计数、直方图、分位数、错误指纹和跨事件聚合由服务端完成。
112
116
  - **低基数路由**:用 `tracking.view.getPathGroup` 把 `/user/123` 归类成 `/user/:id`,避免高基数 URL 污染指标维度。
113
117
  - **手动 View 的时机**:使用 `autoStart: false`,先 `await start()` 建立 Session,再调用 `startView()`;启动前调用会因没有有效采样 Session 而被忽略。
114
118
  - **Action 命名隐私**:默认 `nameCollection: 'explicit'` 只读取 `data-bk-action-name`,否则退回标签名;只有显式设为 `text` 才读取可访问名称和 DOM 文本。
@@ -13,7 +13,7 @@
13
13
  "id": 1,
14
14
  "name": "local-no-data-troubleshoot",
15
15
  "prompt": "我按文档接了 bk-rum,本地起了 collector 在 4318,但 Network 里没看到 /rum 请求,reportCustomEvent 也没上报,debug 我也开了。可能是什么问题?怎么排查?",
16
- "expected_output": "排障应覆盖:session.sampleRate 是会话级确定性采样,未命中时手动事件静默丢弃(建议调试设 sampleRate:1);enabled/Consent/有效 View 是否正常;建议 transport.signals.traces.processor:'simple';检查 collector、endpoint 与 Network 中 /v1/rum、/v1/metrics、/v1/logs。",
16
+ "expected_output": "排障应覆盖:session.sampleRate 是会话级确定性采样,未命中时手动事件静默丢弃(建议调试设 sampleRate:1);enabled/Consent/有效 View 是否正常;建议 transport.processor:'simple';检查 collector、endpoint 与 Network 中 /v1/rum。",
17
17
  "files": [],
18
18
  "assertions": []
19
19
  },
@@ -21,7 +21,7 @@
21
21
  "id": 2,
22
22
  "name": "instrumentation-vs-plugin-httpbody",
23
23
  "prompt": "配置里有 instrumentations 和 plugins 两块,fetch、error 这些好像两边都能配?它们到底有什么区别?另外我想采集接口报错时的请求/响应 body 来排查问题,该怎么配、要注意什么?",
24
- "expected_output": "正确区分内置 tracking、RUM Plugin 与额外 OTel Instrumentation;指出当前 request 是 SDK 自有 Fetch/XHR patch,生成 browser.resource CLIENT Span,不使用官方 Fetch/XHR instrumentation;说明 excludedUrls、allowedTracingUrls、request.beforeSend;HTTP body 默认关闭,显式配置 tracking.request.body 后默认只采集错误请求,必须配置 redact,并限制 Content-Type 和大小。",
24
+ "expected_output": "正确区分内置 tracking、RUM Plugin 与额外 OTel Instrumentation;指出当前 request 是 SDK 自有 Fetch/XHR patch,生成 browser.resource CLIENT Span,不使用官方 Fetch/XHR instrumentation;说明 excludedUrls、allowedTracingUrls、request.beforeSend;SDK 不读取或上报 HTTP Body。",
25
25
  "files": [],
26
26
  "assertions": []
27
27
  }
@@ -42,7 +42,7 @@ await bkOT.start();
42
42
  await bkOT.flush();
43
43
  ```
44
44
 
45
- 先并行调用已启动插件的 `flush()`,再 force flush Trace、Metric、Log Provider。SDK 已在 `pagehide` 和页面变为 hidden 时触发 flush;业务只需在关键流程完成后按需主动调用。
45
+ 先并行调用已启动插件的 `flush()`,再 force flush Trace Provider。SDK 已在 `pagehide` 和页面变为 hidden 时触发 flush;业务只需在关键流程完成后按需主动调用。
46
46
 
47
47
  ### shutdown()
48
48
 
@@ -180,21 +180,9 @@ span.end();
180
180
 
181
181
  只有已采样且同时带有效 `session.id`、`view.id` 的 Span 会导出。
182
182
 
183
- ### emitLog(record)
183
+ ### tracer
184
184
 
185
- ```ts
186
- bkOT.emitLog({
187
- severityText: 'INFO',
188
- body: 'biz.cache_ready',
189
- attributes: { 'biz.cache': 'homepage' },
190
- });
191
- ```
192
-
193
- 自动合并运行时上下文与脱敏。自定义插件应使用 `emitLog()`,不要直接调用 `logger.emit()`。
194
-
195
- ### tracer / meter / logger
196
-
197
- 实例公开 SDK 私有 Provider 对应的原生 OpenTelemetry `Tracer`、`Meter`、`Logger`。优先使用 `startSpan()` 与 `emitLog()`。当前没有公开稳定的自定义 Metric 采样 helper,直接通过 `meter` 创建的数据点默认无法通过过滤器,不应作为接入方稳定能力;详见[架构与数据流](./architecture.md#扩展边界)。
185
+ 实例公开 SDK 私有 Provider 对应的 OpenTelemetry `Tracer`。SDK 不创建或公开 `Meter`、`Logger`,自定义 RUM 事件使用 `startSpan()`。
198
186
 
199
187
  ## 扩展注册
200
188
 
@@ -219,7 +207,7 @@ bkOT.useInstrumentation(new SomeWebInstrumentation());
219
207
 
220
208
  两者都必须在 `start()` 前调用;使用默认自动启动时没有可靠的动态注册窗口,推荐配置 `autoStart: false`。完整插件契约见[自定义插件](./custom-plugin.md)。
221
209
 
222
- 额外 instrumentation 的稳定扩展边界是 Trace。第三方 Metric 不会自动获得 SDK 内部采样标记,默认无法通过 Metric 过滤器。
210
+ 额外 instrumentation 的稳定扩展边界是 Trace;SDK 不注册 Metric Provider。
223
211
 
224
212
  ## 运行时与诊断成员
225
213
 
@@ -294,7 +282,7 @@ const config = resolveConfig({
294
282
  transport: { endpoint: 'https://rum-collector.example.com' },
295
283
  });
296
284
 
297
- console.log(config.transport.traces && config.transport.traces.endpoint);
285
+ console.log(config.transport.endpoint);
298
286
  ```
299
287
 
300
288
  用于预览核心解析结果和测试配置。插件自己的参数默认值在插件工厂执行时解析,不会全部展开到 `ResolvedBkOTConfig`。
@@ -309,7 +297,7 @@ console.log(config.transport.traces && config.transport.traces.endpoint);
309
297
  | `createDevicePlugin` | `BkOTDevicePluginOptions` |
310
298
  | `createCommonInstrumentationsPlugin` | `BkOTRequestConfig \| boolean` |
311
299
  | `createResourcePlugin` | 直接传 `boolean`,控制是否为静态资源创建 Span;默认 `true` |
312
- | `createErrorPlugin` | `BkOTErrorPluginOptions` |
300
+ | `createErrorPlugin` | 无 |
313
301
  | `createWebVitalsPlugin` | 无 |
314
302
  | `createBlankScreenPlugin` | `BkOTBlankScreenPluginOptions` |
315
303
  | `createActionPlugin` | `BkOTActionPluginOptions` |
@@ -325,7 +313,7 @@ console.log(config.transport.traces && config.transport.traces.endpoint);
325
313
 
326
314
  - `RumRuntimeContext` 及 Session/View/User 相关类型。
327
315
  - `PluginManager`。
328
- - `FilteringSpanProcessor`、`FilteringMetricExporter`、`FilteringLogRecordProcessor`。
316
+ - `FilteringSpanProcessor`。
329
317
  - `EXCLUDED_ACTIVITY_MUTATIONS_ATTRIBUTE`,用于标记不应延长 View Loading/Action 的 DOM 子树。
330
318
  - 配置输入、解析结果、Transport、Hook、请求上下文等 TypeScript 类型。
331
319
 
@@ -340,11 +328,11 @@ console.log(config.transport.traces && config.transport.traces.endpoint);
340
328
  | 分类 | 类型 |
341
329
  | --- | --- |
342
330
  | 顶层配置 | `BkOTOptions`、`BkOTApplicationConfig`、`BkOTTransportConfig`、`BkOTTrackingConfig`、`BkOTTrackingConsent`、`BkOTContextConfig`、`BkOTPrivacyConfig`、`BkOTExtensionsConfig` |
343
- | Transport | `BkOTBatchConfig`、`SignalExporterConfig`、`SignalExporterInputConfig`、`SignalExportersInputConfig`、`TraceExporterInputConfig`、`MetricExporterInputConfig` |
331
+ | Transport | `BkOTBatchConfig`、`SignalExporterConfig` |
344
332
  | View/Session/User | `BkOTViewConfig`、`BkOTSessionConfig`、`BkOTStartViewOptions`、`BkOTViewContext`、`BkOTSessionLifecycleEvent`、`BkOTUserContext` |
345
- | Request | `BkOTRequestConfig`、`BkOTRequestEvent`、`BkOTRequestContext`、`BkOTRequestBodyConfig`、`BkOTRequestBodyRedactPayload`、`BkOTUrlMatcher` |
333
+ | Request | `BkOTRequestConfig`、`BkOTRequestEvent`、`BkOTRequestContext`、`BkOTUrlMatcher` |
346
334
  | 事件与 Hook | `BkOTActionEventPayload`、`BkOTCustomEventPayload`、`BkOTBeforeSendEvent`、`BkOTAttributesConfig`、`BkOTAttributeValue` |
347
- | 插件 | `BkOTPlugin`、`BkOTRuntimeContext`、`BkOTActionPluginOptions`、`BkOTBlankScreenPluginOptions`、`BkOTDevicePluginOptions`、`BkOTErrorPluginOptions`、`BkOTLongTaskPluginOptions` |
335
+ | 插件 | `BkOTPlugin`、`BkOTRuntimeContext`、`BkOTActionPluginOptions`、`BkOTBlankScreenPluginOptions`、`BkOTDevicePluginOptions`、`BkOTLongTaskPluginOptions` |
348
336
  | 实例与解析结果 | `BkOTInstance`、`PluginManager`、`ResolvedBkOTConfig`、`ResolvedApplicationConfig`、`ResolvedTransportConfig`、`ResolvedViewConfig`、`ResolvedConfigHooks` |
349
337
  | Schema | `RumAttributeKey`、`RumSpanClassification`、`RumSpanType`、`RumSpanResult` |
350
338
 
@@ -2,140 +2,60 @@
2
2
 
3
3
  # 架构与数据流
4
4
 
5
- 本页描述当前 `src/` 的实现边界,适合 SDK 维护者、扩展插件作者和需要解释“为什么数据没有被导出”的接入方。
5
+ SDK 只负责采集浏览器事实和必须在浏览器本地完成的体验语义计算,所有数据统一编码为 RUM Span,通过 `<transport.endpoint>/v1/rum` 上报。
6
6
 
7
- ## 源码模块
7
+ ## 模块边界
8
8
 
9
- | 目录/文件 | 职责 | 稳定入口 |
10
- | --- | --- | --- |
11
- | `src/index.ts` | ESM 公共导出边界 | npm import 只能依赖这里导出的符号 |
12
- | `src/browser.ts` | CDN/IIFE 入口 | 暴露 `window.BkOpenTelemetry` |
13
- | `src/core/config.ts` | 输入类型、校验、默认值、Endpoint 与 Hook 解析 | `BkOTOptions`、`resolveConfig()` |
14
- | `src/core/sdk.ts` | Provider、Exporter、生命周期、内置插件组合、公开实例 API | `BkOpenTelemetry` |
15
- | `src/core/runtime-context.ts` | User/Session/View/Action 属性快照与历史归属 | `RumRuntimeContext` |
16
- | `src/core/processor.ts` | Span/Metric/Log 的采样、上下文、自上报和 beforeSend 过滤 | 三个 Filtering 类 |
17
- | `src/core/plugin.ts` | 插件契约、启动、并行 flush、反向 shutdown、错误隔离 | `createPlugin()` |
18
- | `src/plugins/` | 浏览器采集与 RUM 语义 | 各 `create*Plugin()` |
19
- | `src/schema/` | 归一字段、Span 类型、结果和耗时分桶 | `RUM_ATTRIBUTES`、`buildRumSpanAttributes()` |
9
+ | 模块 | 职责 |
10
+ | --- | --- |
11
+ | `core/config.ts` | 配置校验、Endpoint、Hook、Resource 属性 |
12
+ | `core/sdk.ts` | TracerProvider、Exporter、生命周期和公开 API |
13
+ | `core/runtime-context.ts` | User/Session/View/Action 当前快照与历史归属 |
14
+ | `core/processor.ts` | 采样、上下文、自上报和 beforeSend 过滤 |
15
+ | `plugins/` | 浏览器原始事件采集与本地体验语义 |
16
+ | `schema/` | RUM 字段和 Span 分类 |
20
17
 
21
- 文档描述与源码冲突时,以 `src/index.ts` 的公开导出和对应实现为准。`dist/` 是构建产物,不作为文档事实源。
18
+ SDK 不创建 `MeterProvider`、`LoggerProvider`、Metric Reader 或 Log Processor。
22
19
 
23
- ## 构造、启动与关闭
20
+ ## 生命周期
24
21
 
25
- ### 构造阶段
22
+ 构造时只创建 Resource、TracerProvider、OTLP Trace Exporter 和运行时上下文。获得 Consent 后,插件依次建立 Session、View、请求、资源、错误、Vitals、Action 等采集。`flush()` 刷新插件和 Trace Provider;`shutdown()` 反向关闭插件并关闭 Trace Provider。
26
23
 
27
- `new BkOpenTelemetry(options)` 同步完成:
24
+ ## 原始事件模型
28
25
 
29
- 1. `resolveConfig()` 校验 `application.name`、Transport 和已启用信号的 Endpoint。
30
- 2. 创建 Resource、TracerProvider、MeterProvider、LoggerProvider。
31
- 3. 根据三类信号开关决定是否创建 exporter、processor 或 metric reader。
32
- 4. 创建运行时上下文;初始状态尚无 Session/View,也未命中采样。
33
- 5. `autoStart !== false` 时异步调用 `start()`。
26
+ 公共流程:
34
27
 
35
- 因此,需要在启动前注册扩展或立即创建手动 View 时,应显式设置 `autoStart: false`。
28
+ 1. 插件读取浏览器事件的真实时间。
29
+ 2. 按事件时间关联 `session.id`、`view.id`、`action.id`。
30
+ 3. 写入唯一 `event.id`、`event.type`、`event.timestamp`。
31
+ 4. 创建 RUM Span,应用 URL/属性脱敏。
32
+ 5. FilteringSpanProcessor 校验采样和有效上下文,执行 `tracking.beforeSend`。
33
+ 6. 通过 `/v1/rum` 批量上报。
36
34
 
37
- ### 启动阶段
35
+ Session 和 View 使用显式生命周期事件:
38
36
 
39
- `start()` 幂等。获得 Consent 且 `enabled=true` 时,插件按以下顺序初始化:
37
+ - `browser.session`:`event.phase=start|rotate|end`。
38
+ - `browser.view`:`event.phase=start|update|end`,并携带单调递增的 `view.version`。
39
+ - `browser.websocket`:`event.phase=connect|open|error|close`,通过 `websocket.connection.id` 关联。
40
40
 
41
- 1. 上下文:Session → Device → Activity → View → Resource Observer。
42
- 2. 请求:统一 Fetch/XHR patch。
43
- 3. RUM:Error → Web Vitals → Blank Screen → Action → 按需 WebSocket / Long Task / CSP。
44
- 4. 接入方 `extensions.plugins`。
45
- 5. 接入方 OpenTelemetry instrumentations。
41
+ Session 生命周期允许只有 `session.id`;其他普通事件必须同时归属有效 Session 和 View。
46
42
 
47
- 单个插件 `init()` 抛错不会阻断其他插件;仅在 `debug: true` 时输出 warning。Consent 撤销后再授权会重新执行插件 `init()`,插件必须在 `shutdown()` 中完整释放监听和 patch。
43
+ ## SDK 与服务端分工
48
44
 
49
- ### flush 与 shutdown
45
+ SDK 保留浏览器端才可靠的计算:CLS、INP、Action Loading Time、View Loading Time、挫败信号和白屏判断。
50
46
 
51
- - `flush()`:并行刷新插件,再 force flush Trace、Metric、Log provider。
52
- - `shutdown()`:反向关闭插件,结束/刷新最终数据,移除页面生命周期监听,关闭三个 provider。
53
- - `shutdown()` 后同一实例不能重新启动;需要重新创建实例。
54
- - SDK 在 `pagehide` 和页面变为 hidden 时主动调用 `flush()`。
47
+ 服务端负责:
55
48
 
56
- ## 从浏览器事件到 OTLP
49
+ - View/Session 时长、事件计数、错误率、吞吐量;
50
+ - Counter、Histogram、P50/P75/P95/P99;
51
+ - 错误指纹、分组和风暴控制;
52
+ - 采样率修正、乱序/迟到事件合并;
53
+ - 基于 `event.id` 去重,基于 `view.id + view.version` 幂等更新。
57
54
 
58
- 一次事件的公共路径是:
55
+ ## 请求采集
59
56
 
60
- 1. 插件或公开 API 观察浏览器事件。
61
- 2. 从 `RumRuntimeContext` 读取事件发生时对应的 User、Session、View、Action 属性。
62
- 3. 构造原生 OpenTelemetry Span、Metric datapoint 或 LogRecord。
63
- 4. 应用 URL/属性脱敏和事件级 Hook。
64
- 5. Filtering processor/exporter 校验采样与上下文。
65
- 6. 通过对应 OTLP HTTP exporter 上报。
57
+ Fetch/XHR 由 SDK 单层 patch:创建 `browser.resource` CLIENT Span、可选注入 `traceparent`、关联 Resource Timing,并通过活动总线参与 View/Action Loading Time。`excludedUrls` 完全排除请求,`request.beforeSend` 可修改或丢弃请求 Span。SDK 不读取请求或响应 Body。
66
58
 
67
- 不同信号的最终过滤规则不同:
59
+ ## 隐私与扩展
68
60
 
69
- | 信号 | 接受条件 | 最终 Hook |
70
- | --- | --- | --- |
71
- | Span | 已采样,且同时有有效 `session.id`、`view.id`;排除 SDK 上报请求和请求级丢弃标记 | `tracking.beforeSend` |
72
- | Log | 同 Span;`session.start/rotate` 允许只有有效 Session | `tracking.beforeSend` |
73
- | Metric | datapoint 带内部已采样标记;导出前移除该标记 | 无全局 beforeSend |
74
-
75
- 这意味着手动模式首次 `startView()` 之前,普通 Span/Log 不会导出;只创建原生 meter 数据但没有使用 SDK 采样属性的自定义 Metric 也不会导出。
76
-
77
- ## 运行时上下文与历史归属
78
-
79
- 运行时上下文维护当前属性,也保留有限的变更时间线。PerformanceObserver 经常在事件结束后才回调,因此 `startSpan(..., { startTime, contextTime })` 可以按事件真实发生时间解析其所属 Session/View/Action,避免把旧页面资源归到新 View。
80
-
81
- ### Span 与 Log
82
-
83
- Span/Log 可携带唯一关联字段:
84
-
85
- - `user.id`
86
- - `session.id`
87
- - `view.id`、`view.name`、`view.url`、`view.url_path_group`
88
- - 活动期间的 `action.id`
89
-
90
- ### Metric
91
-
92
- Metric 只保留 `view.url_path_group` 等低基数属性,不携带 `session.id`、`view.id`、`action.id`。需要从聚合指标下钻到具体访问时,查询同名语义 Span 或 View Snapshot Log,或由后端使用 exemplar/派生数据建立关联。
93
-
94
- ## Session、采样与 Consent
95
-
96
- 三者是不同控制层:
97
-
98
- | 控制层 | 决定什么 | 运行期变化 |
99
- | --- | --- | --- |
100
- | `enabled` | 实例是否启动采集 | 构造后不提供 Setter |
101
- | Consent | 是否安装采集副作用、创建 Session/View | `setTrackingConsent()` 可授权/撤销 |
102
- | `session.sampleRate` | 有效 Session 的数据是否进入导出链路 | Session 轮换后用新 ID 重新计算 |
103
- | Signal 开关 | 是否存在对应 exporter/processor/reader | 构造时固定 |
104
-
105
- Session 采样由 `application.name + session.id` 稳定 hash 决定,同一 Session 的三类信号保持一致。插件仍可维护页面生命周期,但未采样数据会在创建或导出路径被丢弃。
106
-
107
- ## 请求采集设计
108
-
109
- Fetch/XHR 由 `createCommonInstrumentationsPlugin()` 的单一生命周期直接 patch,不叠加官方 Fetch/XHR instrumentation:
110
-
111
- - `excludedUrls` 在最前面完全排除请求。
112
- - 开始请求时创建 `browser.resource` CLIENT Span,并登记 View/Action 活动。
113
- - 只有 `allowedTracingUrls` 命中且 Trace 开启时才调用全局 propagator 注入。SDK 成功注册默认 W3C propagator 时注入 `traceparent`/已有 `tracestate`;宿主已有全局 propagator 时,实际 Header 由宿主决定。
114
- - Resource Observer 把同一 URL/时间窗的 PerformanceResourceTiming 匹配回请求 Span。
115
- - `request.beforeSend` 可修改请求事件属性或标记丢弃该 Span。
116
- - 配置 Body 且 Log 开启时,异步生成关联 `trace.id` / `span.id` 的 `browser.request.body` Log。
117
- - SDK 自身所有已启用 OTLP Endpoint 始终排除,防止递归上报。
118
-
119
- 静态资源复用同一个 Resource Observer,但 Fetch/XHR entry 只用于 timing 匹配,不再创建第二条资源 Span。
120
-
121
- ## 脱敏与 Hook 顺序
122
-
123
- | 入口 | 作用范围 | 适合用途 |
124
- | --- | --- | --- |
125
- | `privacy.redactUrl` | SDK 写入的 URL 类属性 | 删除 query/hash、模板化路径 |
126
- | `privacy.redactAttributes` | Resource、通过 SDK `startSpan()`、`emitLog()` 和内置插件显式应用的属性 | 删除敏感业务字段 |
127
- | `tracking.request.beforeSend` | 单个 Fetch/XHR,带原始 Request/Response/XHR 上下文 | 请求专属补充或丢弃 |
128
- | Request Body `redact` | 单个请求/响应 Body,必填 | 内容级脱敏;返回 `undefined` 跳过该 Body |
129
- | `tracking.beforeSend` | Span/Log 进入底层 processor 前 | 最终兜底修改或丢弃;不作用于 Metric |
130
-
131
- 第三方 instrumentation 自己生成的属性不经过 SDK 的 `redactAttributes` 构造路径。若要统一约束第三方 Span,应在 `tracking.beforeSend` 中做最终清理。
132
-
133
- ## 扩展边界
134
-
135
- - RUM 语义、Session/View 关联、Log 或活动总线:使用 `createPlugin()`。
136
- - 已有标准 OpenTelemetry instrumentation:通过 `extensions.instrumentations` 或 `useInstrumentation()` 注册。
137
- - 自定义 Log 使用 `context.emitLog()`,不要直接 `context.logger.emit()`,否则不会自动合并运行时上下文。
138
- - 自定义 Span 优先使用 `context.startSpan()`,它会应用运行时属性与脱敏。
139
- - 当前包没有导出稳定的自定义 Metric 采样属性/helper。直接使用 `context.meter` 创建的数据点默认无法通过 `FilteringMetricExporter`;不要依赖内部 `bk.rum.sampled` 字段,也不要把 `getRuntimeAttributes()` 中的唯一 Session/View/Action ID 整体复制到 labels。需要稳定扩展时优先使用 Span/Log,或先在 SDK 内补充公共 Metric API。
140
-
141
- 完整契约与示例见[自定义插件](./custom-plugin.md)。
61
+ `privacy.redactUrl` 处理 URL,`privacy.redactAttributes` 处理 Resource 和 SDK Span,`tracking.beforeSend` 是导出前最终兜底。自定义 RUM 插件使用 `context.startSpan()`;SDK 不提供 `meter`、`logger` 或 `emitLog()`。
@@ -6,43 +6,43 @@
6
6
 
7
7
  ## 总览
8
8
 
9
- | 能力 | 配置入口 | 默认 | 浏览器入口 | Trace | Metric | Log |
10
- | --- | --- | --- | --- | --- | --- | --- |
11
- | Session | `session` | 必选基础能力 | `localStorage`、用户活动、页面可见性 | — | — | `session.start` / `session.rotate` |
12
- | View | `tracking.view` | 自动模式 | Navigation Timing、History、hash、BFCache、DOM Mutation | `browser.view` | `browser.view.loading_time` | `browser.view` Snapshot |
13
- | Fetch/XHR | `tracking.request` | 开 | `fetch`、`XMLHttpRequest`、Resource Timing | `browser.resource` | — | 可选 `browser.request.body` |
14
- | 静态资源 | `tracking.resource` | 开 | Resource PerformanceObserver | `browser.resource` | — | — |
15
- | JS / Promise / 资源错误 | `tracking.error` | 开 | `error`、`unhandledrejection` | 三类 `browser.*error` | — | — |
16
- | Web Vitals | `tracking.webVitals` | 开 | `web-vitals`、Layout Shift、Event Timing | `browser.web_vital` | 两个 Histogram | — |
17
- | Action | `tracking.action` | 开 | click、DOM、请求与活动总线 | `action.click` | — | — |
18
- | 手动 Action | `reportAction()` | 可调用 | 业务调用 | `action.custom` | — | — |
19
- | 自定义事件 | `reportCustomEvent()` | 可调用 | 业务调用 | `custom.<name>` | — | — |
20
- | 白屏 | `tracking.blankScreen` | 开 | DOM 命中测试、View 活动 | `browser.blank_screen` | `browser.blank_screen.count` | — |
21
- | 设备 | `tracking.device` | 开 | UA、UA-CH、Screen、Network Information | Resource 与运行时公共属性 | — | Resource 与运行时公共属性 |
22
- | Long Task | `tracking.longTask` | 关 | Long Animation Frames / Long Tasks | `browser.long_task` | 三个聚合指标 | — |
23
- | WebSocket | `tracking.websocket` | 关 | `WebSocket` Proxy | `websocket.connect` | 四个聚合指标 | error / close |
24
- | CSP | `tracking.cspViolation` | 关 | `securitypolicyviolation` | `csp.violation` | — | — |
25
- | 自定义插件 | `extensions.plugins` / `use()` | 无 | 由插件决定 | 支持 | 无稳定公共辅助 API | 推荐 `emitLog()` |
26
- | OTel instrumentation | `extensions.instrumentations` / `useInstrumentation()` | 无 | 由 instrumentation 决定 | 支持 | 无稳定支持 | 取决于实现 |
27
-
28
- “默认开”表示获得 Consent 且 SDK 已启动后启用。是否真正导出还受 `enabled`、Session 采样、Session/View 有效性和单信号开关控制。
9
+ | 能力 | 配置入口 | 默认 | 浏览器入口 | 原始 RUM Span |
10
+ | --- | --- | --- | --- | --- |
11
+ | Session | `session` | 必选基础能力 | `localStorage`、用户活动、页面可见性 | `browser.session` start/rotate/end |
12
+ | View | `tracking.view` | 自动模式 | Navigation Timing、History、hash、BFCache、DOM Mutation | `browser.view` start/update/end |
13
+ | Fetch/XHR | `tracking.request` | 开 | `fetch`、`XMLHttpRequest`、Resource Timing | `browser.resource` |
14
+ | 静态资源 | `tracking.resource` | 开 | Resource PerformanceObserver | `browser.resource` |
15
+ | JS / Promise / 资源错误 | `tracking.error` | 开 | `error`、`unhandledrejection` | 三类 `browser.*error` |
16
+ | Web Vitals | `tracking.webVitals` | 开 | `web-vitals`、Layout Shift、Event Timing | `browser.web_vital` |
17
+ | Action | `tracking.action` | 开 | click、DOM、请求与活动总线 | `action.click` |
18
+ | 手动 Action | `reportAction()` | 可调用 | 业务调用 | `action.custom` |
19
+ | 自定义事件 | `reportCustomEvent()` | 可调用 | 业务调用 | `custom.<name>` |
20
+ | 白屏 | `tracking.blankScreen` | 开 | DOM 命中测试、View 活动 | `browser.blank_screen` |
21
+ | 设备 | `tracking.device` | 开 | UA、UA-CH、Screen、Network Information | Resource 与运行时公共属性 |
22
+ | Long Task | `tracking.longTask` | 关 | Long Animation Frames / Long Tasks | `browser.long_task` |
23
+ | WebSocket | `tracking.websocket` | 关 | `WebSocket` Proxy | `browser.websocket` connect/open/error/close |
24
+ | CSP | `tracking.cspViolation` | 关 | `securitypolicyviolation` | `csp.violation` |
25
+ | 自定义插件 | `extensions.plugins` / `use()` | 无 | 由插件决定 | `context.startSpan()` |
26
+ | OTel instrumentation | `extensions.instrumentations` / `useInstrumentation()` | 无 | 由 instrumentation 决定 | 支持 |
27
+
28
+ “默认开”表示获得 Consent 且 SDK 已启动后启用。是否真正导出还受 `enabled`、Session 采样和 Session/View 有效性控制。
29
29
 
30
30
  ## 能力边界
31
31
 
32
32
  ### SDK 直接负责
33
33
 
34
34
  - 创建和轮换 Session,划分初始加载、SPA、BFCache、手动和 Session 续期 View。
35
- - 统一 patch Fetch/XHR;请求 span、活动计数、Trace Header、Resource Timing 和 Body 采集共用同一生命周期。
35
+ - 统一 patch Fetch/XHR;请求 span、活动追踪、Trace Header 和 Resource Timing 共用同一生命周期。
36
36
  - 把浏览器事件归一为 `span_type`、`span_subtype`、`result`、`error_type` 等字段。
37
- - 自动为 Span/Log 关联 `session.id`、`view.id`,为 Metric 保留低基数 `view.url_path_group`。
37
+ - 自动为 Span 关联 `session.id`、`view.id` 和 `action.id`。
38
38
  - 在 exporter 前执行采样、有效上下文、自上报请求和 `tracking.beforeSend` 过滤。
39
39
 
40
40
  ### SDK 不负责
41
41
 
42
42
  - 不聚合 `session.duration`、影响用户数、地理信息、Trace 关键路径等后端指标。
43
43
  - 不自动判断业务字段是否敏感,也不 hash `user.id`。
44
- - 不默认采集 HTTP 请求/响应 Body。
45
- - 不把唯一的 `session.id`、`view.id`、`action.id` 放入 Metric labels。
44
+ - 不采集 HTTP 请求/响应 Body。
45
+ - 不在浏览器生成 Counter、Histogram、分位数、错误指纹或跨事件计数。
46
46
  - 不保证浏览器未暴露的数据,例如缺少 `Timing-Allow-Origin` 的跨域资源网络阶段。
47
47
 
48
48
  ## 默认开启与关闭
@@ -84,13 +84,11 @@ Session 与 View 是导出有效性边界,不提供关闭开关。`tracking.vi
84
84
 
85
85
  | 能力 | 主要成本/风险 | 建议 |
86
86
  | --- | --- | --- |
87
- | `session.sampleRate` | 决定三类信号总体数据量 | 按应用容量设置;排障临时设为 `1` |
88
- | Metric 自定义维度 | 高基数会放大时序数量 | 只放应用、租户类别、路由模板等低基数字段 |
89
- | Request Body | 可能包含凭证、个人数据,且增加网络体积 | 默认关闭;开启时限制类型/大小并强制脱敏 |
87
+ | `session.sampleRate` | 决定 RUM Span 总体数据量 | 按应用容量设置;排障临时设为 `1` |
90
88
  | Action 文本命名 | DOM 文本可能包含用户输入 | 保持 `nameCollection: 'explicit'`,关键元素使用 `data-bk-action-name` |
91
89
  | Device 持久 ID | 支持跨 Session 关联 | 默认不持久化;需取得合规依据后再开启 |
92
90
  | Long Task | 产生 Span 与脚本归因信息 | 仅性能分析场景开启,结合采样控制 |
93
- | WebSocket | Proxy 全局构造器并统计消息字节 | 同页面单实例;不采集消息内容 |
91
+ | WebSocket | Proxy 全局构造器并监听连接生命周期 | 不包裹 `send()`,不采集消息内容、数量或字节数 |
94
92
 
95
93
  ## 下一步
96
94