@blueking/open-telemetry 0.0.21 → 0.0.22

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 (46) 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 +10 -48
  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/runtime-context.d.ts +1 -1
  9. package/dist/core/sdk.d.ts +2 -8
  10. package/dist/core/telemetry-attributes.d.ts +1 -2
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +1074 -1484
  13. package/dist/index.js.map +1 -1
  14. package/dist/plugins/common.d.ts +1 -1
  15. package/dist/plugins/csp-violation.d.ts +0 -8
  16. package/dist/plugins/device.d.ts +2 -2
  17. package/dist/plugins/error.d.ts +1 -5
  18. package/dist/plugins/long-task.d.ts +1 -3
  19. package/dist/plugins/resource.d.ts +1 -0
  20. package/dist/plugins/web-vitals.d.ts +2 -7
  21. package/dist/schema/attributes.d.ts +8 -10
  22. package/dist/schema/span.d.ts +2 -0
  23. package/package.json +1 -6
  24. package/skills/bk-rum-otele/SKILL.md +12 -14
  25. package/skills/bk-rum-otele/evals/evals.json +2 -2
  26. package/skills/bk-rum-otele/references/api.md +10 -22
  27. package/skills/bk-rum-otele/references/architecture.md +38 -118
  28. package/skills/bk-rum-otele/references/capabilities.md +26 -28
  29. package/skills/bk-rum-otele/references/concepts.md +14 -106
  30. package/skills/bk-rum-otele/references/configuration.md +28 -69
  31. package/skills/bk-rum-otele/references/custom-plugin.md +10 -13
  32. package/skills/bk-rum-otele/references/data-model.md +23 -95
  33. package/skills/bk-rum-otele/references/getting-started.md +1 -1
  34. package/skills/bk-rum-otele/references/plugins-basic.md +7 -7
  35. package/skills/bk-rum-otele/references/plugins-error-security.md +4 -7
  36. package/skills/bk-rum-otele/references/plugins-experience.md +8 -9
  37. package/skills/bk-rum-otele/references/plugins-network.md +19 -128
  38. package/skills/bk-rum-otele/references/plugins.md +3 -3
  39. package/skills/bk-rum-otele/references/privacy.md +4 -25
  40. package/skills/bk-rum-otele/references/telemetry-reference.md +49 -279
  41. package/skills/bk-rum-otele/references/transport-sampling.md +15 -50
  42. package/skills/bk-rum-otele/references/troubleshooting.md +7 -34
  43. package/dist/core/metric.d.ts +0 -2
  44. package/dist/core/signal.d.ts +0 -3
  45. package/dist/core/throttle.d.ts +0 -20
  46. 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。
@@ -20,8 +20,8 @@ export declare const getDeviceResourceAttributes: () => Attributes;
20
20
  * - viewport 监听 `resize` / `orientationchange`,并经 250ms debounce 合并,避免拖窗口时高频触发;
21
21
  * 静默期结束后用最终值刷新 runtimeAttributes。
22
22
  * - network 监听 `connection.change`(本身低频,不需要 throttle)。
23
- * - 二者只更新 in-memory 的 runtimeAttributes,不会主动产生新的 span/log,cardinality 安全;
24
- * 但更新后续生成的 log/span 会带最新值。
23
+ * - 二者只更新 in-memory 的 runtimeAttributes,不会主动产生新的 Span;
24
+ * 更新后续生成的 Span 会带最新值。
25
25
  *
26
26
  * 与 session 插件的关系:device 跨会话持久(终身),session 有过期与续期(连续访问语义)。
27
27
  */
@@ -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;
@@ -9,6 +9,7 @@ type ResourceTimingWithStatus = PerformanceResourceTiming & {
9
9
  responseStatus?: number;
10
10
  };
11
11
  export declare const getResourceTimingAttributes: (entry: ResourceTimingWithStatus) => Record<string, number>;
12
+ export declare const getResourceDuration: (entry: ResourceTimingWithStatus) => number;
12
13
  export declare const getResourcePerformanceAttributes: (entry: ResourceTimingWithStatus) => {
13
14
  'resource.encoded_body_size': number;
14
15
  'resource.decoded_body_size': number;
@@ -4,16 +4,11 @@
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
  *
14
- * Histogram 设计:
15
- * - browser.web_vital.cls:单位 '1'(无量纲),CLS 是累积分数,不能与 ms 混用
16
- * - browser.web_vital.duration:单位 'ms',FCP/INP/LCP/TTFB 共享,靠 vital.metric 维度区分
11
+ * 数值语义:CLS 是无量纲分数,FCP/INP/LCP/TTFB 的 vital.value 单位为 ms。
17
12
  *
18
13
  * Navigation Type:
19
14
  * 优先使用 metric.navigationType(web-vitals 内部计算,含 'back-forward-cache' 等准确值),
@@ -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.21",
3
+ "version": "0.0.22",
4
4
  "description": "OpenTelemetry browser SDK for BK RUM",
5
5
  "author": "TencentCloud Real User Monitoring",
6
6
  "main": "dist/index.js",
@@ -27,16 +27,11 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@opentelemetry/api": "^1.9.1",
30
- "@opentelemetry/api-logs": "^0.217.0",
31
30
  "@opentelemetry/context-zone": "2.7.1",
32
31
  "@opentelemetry/core": "^2.7.1",
33
- "@opentelemetry/exporter-logs-otlp-http": "^0.217.0",
34
- "@opentelemetry/exporter-metrics-otlp-http": "^0.217.0",
35
32
  "@opentelemetry/exporter-trace-otlp-http": "^0.217.0",
36
33
  "@opentelemetry/instrumentation": "^0.217.0",
37
34
  "@opentelemetry/resources": "^2.7.1",
38
- "@opentelemetry/sdk-logs": "^0.217.0",
39
- "@opentelemetry/sdk-metrics": "^2.7.1",
40
35
  "@opentelemetry/sdk-trace-base": "^2.7.1",
41
36
  "@opentelemetry/sdk-trace-web": "^2.7.1",
42
37
  "@opentelemetry/semantic-conventions": "^1.38.0",
@@ -5,7 +5,7 @@ description: 帮助业务方在前端应用里接入、使用和配置蓝鲸 RUM
5
5
 
6
6
  # 蓝鲸 RUM OpenTelemetry SDK 接入助手
7
7
 
8
- `@blueking/open-telemetry` 是蓝鲸 RUM 的浏览器上报 SDK,基于 OpenTelemetry Web SDK,把页面访问、接口请求、静态资源、JS 错误、Web Vitals、白屏、设备、会话、用户动作等浏览器事件统一转成 Trace / Metric / Log 三类信号,通过 OTLP HTTP 上报到 collector。
8
+ `@blueking/open-telemetry` 是蓝鲸 RUM 的浏览器上报 SDK,基于 OpenTelemetry Web SDK,把页面访问、接口请求、静态资源、JS 错误、Web Vitals、白屏、设备、会话、用户动作等浏览器事件统一转成 RUM Span,通过唯一的 OTLP HTTP Trace 通道上报到 collector。
9
9
 
10
10
  本 skill 面向**集成使用方**:帮助把 SDK 接入到自己的前端应用,包括安装、配置、按需开关采集能力、框架集成、隐私脱敏、排障和手动上报。不覆盖 SDK 源码本身的开发维护。
11
11
 
@@ -24,31 +24,29 @@ description: 帮助业务方在前端应用里接入、使用和配置蓝鲸 RUM
24
24
  | 第一次接入、安装、最小示例、CDN、生产推荐配置 | `references/getting-started.md` |
25
25
  | 评估 SDK 能力边界、默认开关、浏览器 API、信号产出和降级行为 | `references/capabilities.md` |
26
26
  | 理解源码模块、初始化顺序、运行时上下文、过滤链路和 Hook 时机 | `references/architecture.md` |
27
- | 搞懂三类信号、Instrumentation vs Plugin、采样、数据归一、运行时上下文 | `references/concepts.md` |
27
+ | 搞懂单一 Trace 信号、Instrumentation vs Plugin、采样、数据归一、运行时上下文 | `references/concepts.md` |
28
28
  | 查配置项、默认值、Endpoint、插件参数和 Hook | `references/configuration.md` |
29
- | 查 Transport、单信号开关、批量上报、Session 采样和 traceparent 透传 | `references/transport-sampling.md` |
29
+ | 查 Transport、批量上报、Session 采样和 traceparent 透传 | `references/transport-sampling.md` |
30
30
  | 了解插件默认组合、启用规则和能力分类 | `references/plugins.md` |
31
31
  | 配置 Session、Device、View、Action | `references/plugins-basic.md` |
32
32
  | 配置 Resource、Web Vitals、Blank Screen、Long Task、View Loading Time | `references/plugins-experience.md` |
33
33
  | 配置 Error、CSP Violation 和错误上报 | `references/plugins-error-security.md` |
34
- | 配置 Fetch/XHR Request、HTTP Body、Trace Header、WebSocket | `references/plugins-network.md` |
34
+ | 配置 Fetch/XHR Request、Trace Header、WebSocket | `references/plugins-network.md` |
35
35
  | 写自定义插件、接入第三方 OpenTelemetry instrumentation | `references/custom-plugin.md` |
36
36
  | 查公开 API(start/flush/shutdown/setUser/setView/reportAction/reportCustomEvent 等) | `references/api.md` |
37
37
  | Vue / React / Vue Router / 微前端 集成 | `references/framework-integration.md` |
38
38
  | URL 脱敏、属性脱敏、公共属性、低基数路由、user.id 处理 | `references/privacy.md` |
39
39
  | 了解上报字段、span_type/result、哪些字段是后端派生 | `references/data-model.md` |
40
- | 查具体的 span 名 / metric 名 / log 事件名、完整属性字典 | `references/telemetry-reference.md` |
40
+ | 查具体的 Span 名、事件字段和完整属性字典 | `references/telemetry-reference.md` |
41
41
  | 本地看不到数据、手动事件没上报、白屏误报、接口 span 太多等排障 | `references/troubleshooting.md` |
42
42
 
43
43
  > `references/` 由 `packages/open-telemetry/scripts/gen-skill-references.mjs` 从 SDK 的 `wikis/` 自动生成,请勿手改。如内容过期,让维护者重新执行 `pnpm --filter @blueking/open-telemetry skill:refs`。
44
44
 
45
45
  ## 核心心智模型
46
46
 
47
- ### 三类信号
47
+ ### 单一 Trace 信号
48
48
 
49
- - **Trace**:有起止时间的行为——页面访问、接口请求、资源加载、用户点击、长任务。
50
- - **Metric**:可聚合的数值——Web Vitals、长任务数、WebSocket 消息大小、白屏结果。
51
- - **Log**:离散事件——错误、CSP 违规、会话生命周期、HTTP body 错误路径。
49
+ SDK 只创建 Trace Provider。页面、请求、资源、错误、Vital、白屏和生命周期事件都编码为 RUM Span;计数、直方图、分位数、错误分组和跨事件聚合由服务端完成。
52
50
 
53
51
  ### 内置采集与扩展
54
52
 
@@ -59,11 +57,11 @@ SDK 把能力拆成两类:
59
57
 
60
58
  ### 会话级确定性采样
61
59
 
62
- `session.sampleRate`(0–1,默认 1)是**会话级确定性采样**,不是 trace 级。决定由 `application.name + session.id` 的稳定 hash 得出,同一 Session 的 span/log/metric 决定一致。插件仍维护必要的浏览器生命周期,但未命中时数据不会导出,`reportAction()`、`reportCustomEvent()` 会被静默丢弃。调试时临时设 `sampleRate: 1` 和 `debug: true`。
60
+ `session.sampleRate`(0–1,默认 1)是**会话级确定性采样**,不是单条 Span 级。决定由 `application.name + session.id` 的稳定 hash 得出,同一 Session 的所有 Span 决定一致。插件仍维护必要的浏览器生命周期,但未命中时数据不会导出,`reportAction()`、`reportCustomEvent()` 会被静默丢弃。调试时临时设 `sampleRate: 1` 和 `debug: true`。
63
61
 
64
62
  ### 运行时上下文
65
63
 
66
- SDK 维护公共上下文并自动挂到后续 span/log 上:`user.id`(业务方提供,SDK 原样透传、不 hash 不脱敏)、`session.id`(Session 生成/轮换)、`view.*`(View 管理器维护)。Metric 只保留 `view.url_path_group` 等低基数维度,不携带唯一 `session.id` / `view.id` / `action.id`;精确关联使用对应 span 或 View Snapshot Log。运行中可用 `setUser()` 更新用户;手动 View 使用 `startView()` 划界、`setViewName()` 改名。
64
+ SDK 维护公共上下文并自动挂到后续 Span 上:`user.id`(业务方提供,SDK 原样透传、不 hash 不脱敏)、`session.id`(Session 生成/轮换)、`view.*`(View 管理器维护)和活动窗口内的 `action.id`。运行中可用 `setUser()` 更新用户;手动 View 使用 `startView()` 划界、`setViewName()` 改名。
67
65
 
68
66
  ### 数据归一
69
67
 
@@ -95,7 +93,7 @@ CDN:
95
93
  </script>
96
94
  ```
97
95
 
98
- `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()`。
96
+ `transport.endpoint` 是必填上报根地址(不含路径前缀),SDK 自动拼 `/v1/rum`。SDK 不创建 Metric/Log Provider,所有原始 RUM 事件统一走 Trace Span。`token` 作为 `Authorization: Bearer <token>` 默认头。构造后默认 `autoStart: true` 自动启动,无需手动 `start()`。
99
97
 
100
98
  ## 默认采集能力清单
101
99
 
@@ -110,9 +108,9 @@ View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`csp
110
108
  - **单实例**:`fetch`/`xhr`/`action`/`websocket` 会 patch 或监听全局 API,同页面只应初始化一个 SDK 实例,微前端只在主应用初始化一次。
111
109
  - **`use()` / `useInstrumentation()` 必须在 `start()` 之前**:要注册自定义插件或 instrumentation,请设 `autoStart: false` 再手动 `start()`。
112
110
  - **采样影响手动上报**:未命中采样时 `reportAction()` / `reportCustomEvent()` 静默丢弃,排查时先确认采样。
113
- - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;HTTP body 默认关闭,显式配置 `request.body` 时必须提供 `redact`,默认只采集错误请求;`user.id` 需 hash 的话要在传入前处理。
111
+ - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;SDK 不采集 HTTP Body;`user.id` 需 hash 的话要在传入前处理。
114
112
  - **Consent**:未授权初始化时配置 `privacy.trackingConsent: 'not-granted'`,用户授权后调用 `setTrackingConsent('granted')`;撤销授权会停止采集并解除 patch。
115
- - **信号开关**:`transport.signals.traces/metrics/logs` 设为 `false` 可关闭对应导出链路;关闭 Trace 后不会注入 `traceparent`。只开 Metric 时没有精确 View 下钻。
113
+ - **单一信号**:只有 `/v1/rum` Trace 通道;计数、直方图、分位数、错误指纹和跨事件聚合由服务端完成。
116
114
  - **低基数路由**:用 `tracking.view.getPathGroup` 把 `/user/123` 归类成 `/user/:id`,避免高基数 URL 污染指标维度。
117
115
  - **手动 View 的时机**:使用 `autoStart: false`,先 `await start()` 建立 Session,再调用 `startView()`;启动前调用会因没有有效采样 Session 而被忽略。
118
116
  - **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`、`ResolvedTransportConfig` |
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()`。