@blueking/open-telemetry 0.0.33 → 0.0.35-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 (54) hide show
  1. package/README.md +67 -57
  2. package/dist/bk-rum.global.js +2 -2
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/action-activity.d.ts +5 -1
  5. package/dist/core/action-target.d.ts +19 -0
  6. package/dist/core/config.d.ts +15 -5
  7. package/dist/core/event-time.d.ts +7 -0
  8. package/dist/core/performance-timing.d.ts +13 -0
  9. package/dist/core/plugin.d.ts +37 -2
  10. package/dist/core/processor.d.ts +24 -2
  11. package/dist/core/request-timing.d.ts +3 -2
  12. package/dist/core/runtime-context.d.ts +62 -2
  13. package/dist/core/sdk.d.ts +23 -1
  14. package/dist/core/session-transition.d.ts +19 -0
  15. package/dist/core/trace-context.d.ts +6 -7
  16. package/dist/core/view-location.d.ts +10 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +2955 -1483
  19. package/dist/index.js.map +1 -1
  20. package/dist/integrations/vue-router.d.ts +25 -0
  21. package/dist/plugins/action.d.ts +1 -1
  22. package/dist/plugins/blank-screen-detection.d.ts +11 -0
  23. package/dist/plugins/blank-screen.d.ts +10 -18
  24. package/dist/plugins/common.d.ts +4 -2
  25. package/dist/plugins/document-vitals.d.ts +25 -0
  26. package/dist/plugins/page-view.d.ts +1 -1
  27. package/dist/plugins/resource.d.ts +14 -1
  28. package/dist/plugins/session-state.d.ts +14 -2
  29. package/dist/plugins/session-store.d.ts +12 -0
  30. package/dist/plugins/session.d.ts +1 -0
  31. package/dist/plugins/web-vitals-metrics.d.ts +80 -0
  32. package/dist/plugins/web-vitals.d.ts +2 -59
  33. package/dist/schema/attributes.d.ts +63 -0
  34. package/dist/schema/span.d.ts +5 -2
  35. package/package.json +9 -4
  36. package/skills/bk-rum-otele/references/actions.md +54 -37
  37. package/skills/bk-rum-otele/references/api.md +72 -51
  38. package/skills/bk-rum-otele/references/architecture.md +16 -16
  39. package/skills/bk-rum-otele/references/blank-screen.md +72 -142
  40. package/skills/bk-rum-otele/references/capabilities.md +66 -60
  41. package/skills/bk-rum-otele/references/configuration.md +101 -98
  42. package/skills/bk-rum-otele/references/data-model.md +22 -17
  43. package/skills/bk-rum-otele/references/errors-security.md +13 -13
  44. package/skills/bk-rum-otele/references/extensions.md +5 -3
  45. package/skills/bk-rum-otele/references/framework-integration.md +7 -24
  46. package/skills/bk-rum-otele/references/network.md +62 -49
  47. package/skills/bk-rum-otele/references/performance.md +62 -30
  48. package/skills/bk-rum-otele/references/privacy.md +5 -5
  49. package/skills/bk-rum-otele/references/production.md +9 -13
  50. package/skills/bk-rum-otele/references/session-context.md +67 -38
  51. package/skills/bk-rum-otele/references/span-protocol.md +771 -315
  52. package/skills/bk-rum-otele/references/telemetry-reference.md +288 -213
  53. package/skills/bk-rum-otele/references/troubleshooting.md +2 -2
  54. package/skills/bk-rum-otele/references/views-routing.md +103 -27
@@ -29,18 +29,18 @@ new BkOpenTelemetry({
29
29
 
30
30
  ## 顶层配置
31
31
 
32
- | 配置 | 类型 | 默认 | 说明 |
33
- | --- | --- | --- | --- |
34
- | `application` | `BkOTApplicationConfig` | 必填 | 应用 Resource 信息 |
35
- | `transport` | `BkOTTransportConfig` | 必填 | 唯一 Trace 上报通道 |
36
- | `autoStart` | `boolean` | `true` | 构造后异步调用 `start()` |
37
- | `enabled` | `boolean` | `true` | `false` 时不启动采集;Provider 仍会构造,便于公开 API 形态稳定 |
38
- | `debug` | `boolean` | `false` | 打印待导出 Span,并显示部分插件初始化/丢弃警告 |
39
- | `session` | `BkOTSessionConfig` | `{ sampleRate: 1 }` | 会话采样和存储 key |
40
- | `context` | `BkOTContextConfig` | 无 | 初始用户及按事件读取的自定义属性 |
41
- | `privacy` | `BkOTPrivacyConfig` | 已授权、默认 URL 清洗 | Consent 与脱敏 Hook |
42
- | `tracking` | `BkOTTrackingConfig` | 见能力矩阵 | 内置采集开关和参数 |
43
- | `extensions` | `BkOTExtensionsConfig` | 空数组 | 自定义 RUM 插件和 OTel instrumentation |
32
+ | 配置 | 类型 | 默认 | 说明 |
33
+ | ------------- | ----------------------- | --------------------- | -------------------------------------------------------------- |
34
+ | `application` | `BkOTApplicationConfig` | 必填 | 应用 Resource 信息 |
35
+ | `transport` | `BkOTTransportConfig` | 必填 | 唯一 Trace 上报通道 |
36
+ | `autoStart` | `boolean` | `true` | 构造后异步调用 `start()` |
37
+ | `enabled` | `boolean` | `true` | `false` 时不启动采集;Provider 仍会构造,便于公开 API 形态稳定 |
38
+ | `debug` | `boolean` | `false` | 打印待导出 Span,并显示部分插件初始化/丢弃警告 |
39
+ | `session` | `BkOTSessionConfig` | `{ sampleRate: 1 }` | 会话采样和存储 key |
40
+ | `context` | `BkOTContextConfig` | 无 | 初始用户及按事件读取的自定义属性 |
41
+ | `privacy` | `BkOTPrivacyConfig` | 已授权、默认 URL 清洗 | Consent 与脱敏 Hook |
42
+ | `tracking` | `BkOTTrackingConfig` | 见能力矩阵 | 内置采集开关和参数 |
43
+ | `extensions` | `BkOTExtensionsConfig` | 空数组 | 自定义 RUM 插件和 OTel instrumentation |
44
44
 
45
45
  如果要调用 `use()` 或 `useInstrumentation()`,必须设置 `autoStart: false`,先注册再 `await start()`。
46
46
 
@@ -48,42 +48,42 @@ new BkOpenTelemetry({
48
48
 
49
49
  ## application
50
50
 
51
- | 配置 | 类型 | 默认 | 上报位置 |
52
- | --- | --- | --- | --- |
53
- | `name` | `string` | 必填、非空 | Resource `service.name`,也参与 Session 稳定采样 |
54
- | `environment` | `string` | `'production'` | Resource `deployment.environment.name` |
55
- | `version` | `string` | 不发送 | Resource `service.version` |
51
+ | 配置 | 类型 | 默认 | 上报位置 |
52
+ | ------------- | -------- | -------------- | ------------------------------------------------ |
53
+ | `name` | `string` | 必填、非空 | Resource `service.name`,也参与 Session 稳定采样 |
54
+ | `environment` | `string` | `'production'` | Resource `deployment.environment.name` |
55
+ | `version` | `string` | 不发送 | Resource `service.version` |
56
56
 
57
57
  `name` 应稳定且低基数,不要包含用户、构建时间或路由。`version` 推荐使用可以定位前端构建产物的版本号或 commit 标识。
58
58
 
59
59
  ## transport
60
60
 
61
- | 配置 | 类型 | 默认 | 说明 |
62
- | --- | --- | ---: | --- |
63
- | `endpoint` | `string` | 必填、非空 | 上报根地址;去除末尾 `/` 后追加 `/v1/rum` |
64
- | `token` | `string` | 无 | 生成默认 `Authorization: Bearer <token>` |
65
- | `headers` | `Record<string, string>` | 无 | 自定义头;同名时覆盖 token 生成的头 |
66
- | `processor` | `'batch' \| 'simple'` | `'batch'` | 批量或逐 Span 导出 |
67
- | `batch` | `BkOTBatchConfig` | OTel 默认值 | 仅 batch 模式生效 |
68
- | `timeoutMillis` | `number` | 未配置时沿用 OTel exporter | exporter 请求及重试的总期限,必须大于 0。当前锁定的 `@opentelemetry/exporter-trace-otlp-http` 默认约为 `10000` |
69
- | `concurrencyLimit` | `number` | 未配置时沿用 OTel exporter | exporter 并发 Promise 上限。当前锁定依赖默认约为 `30` |
61
+ | 配置 | 类型 | 默认 | 说明 |
62
+ | ------------------ | ------------------------ | -------------------------: | -------------------------------------------------------------------------------------------------------------- |
63
+ | `endpoint` | `string` | 必填、非空 | 上报根地址;去除末尾 `/` 后追加 `/v1/rum` |
64
+ | `token` | `string` | 无 | 生成默认 `Authorization: Bearer <token>` |
65
+ | `headers` | `Record<string, string>` | 无 | 自定义头;同名时覆盖 token 生成的头 |
66
+ | `processor` | `'batch' \| 'simple'` | `'batch'` | 批量或逐 Span 导出 |
67
+ | `batch` | `BkOTBatchConfig` | OTel 默认值 | 仅 batch 模式生效 |
68
+ | `timeoutMillis` | `number` | 未配置时沿用 OTel exporter | exporter 请求及重试的总期限,必须大于 0。当前锁定的 `@opentelemetry/exporter-trace-otlp-http` 默认约为 `10000` |
69
+ | `concurrencyLimit` | `number` | 未配置时沿用 OTel exporter | exporter 并发 Promise 上限。当前锁定依赖默认约为 `30` |
70
70
 
71
71
  `batch` 子项由 SDK 原样传给 `BatchSpanProcessor`,本包不硬编码。未配置时沿用锁定的 `@opentelemetry/sdk-trace-base` 默认值(当前常见为):
72
72
 
73
- | 配置 | 默认 | 说明 |
74
- | --- | ---: | --- |
75
- | `maxQueueSize` | `2048` | 队列满后丢弃新的已结束 Span |
76
- | `maxExportBatchSize` | `512` | 单批 Span 上限,不能有效超过 queue size |
77
- | `scheduledDelayMillis` | `5000` | 批量调度等待 |
78
- | `exportTimeoutMillis` | `30000` | processor 等待 export 的上限 |
73
+ | 配置 | 默认 | 说明 |
74
+ | ---------------------- | ------: | --------------------------------------- |
75
+ | `maxQueueSize` | `2048` | 队列满后丢弃新的已结束 Span |
76
+ | `maxExportBatchSize` | `512` | 单批 Span 上限,不能有效超过 queue size |
77
+ | `scheduledDelayMillis` | `5000` | 批量调度等待 |
78
+ | `exportTimeoutMillis` | `30000` | processor 等待 export 的上限 |
79
79
 
80
80
  完整协议与重试语义见[上报协议、批处理与采样](./transport-sampling.md)。
81
81
 
82
82
  ## session
83
83
 
84
- | 配置 | 类型 | 默认 | 说明 |
85
- | --- | --- | --- | --- |
86
- | `sampleRate` | `number` | `1` | 0–1 的 Session 级确定性采样率;越界会截断 |
84
+ | 配置 | 类型 | 默认 | 说明 |
85
+ | ------------ | -------- | --------------------------- | ------------------------------------------- |
86
+ | `sampleRate` | `number` | `1` | 0–1 的 Session 级确定性采样率;越界会截断 |
87
87
  | `storageKey` | `string` | 按应用和 endpoint host 生成 | 跨 Tab 共享 Session 状态的 localStorage key |
88
88
 
89
89
  15 分钟无活动和 4 小时最大生命周期是当前固定行为,不是公开配置项。localStorage 不可用时退化为页面进程内存,无法跨页面/Tab 共享。详见[Session、用户与设备上下文](./session-context.md)。
@@ -101,12 +101,12 @@ context: {
101
101
  }
102
102
  ```
103
103
 
104
- | 配置 | 调用时机 | 合并到 |
105
- | --- | --- | --- |
106
- | `user.id` | 构造时,之后可用 `setUser()` 更新 | 运行时 `user.id` |
107
- | `attributes.page()` | 插件创建相关 Span、过滤层补属性时 | 页面/请求/事件 Span,具体取决于调用插件 |
108
- | `attributes.error()` | 创建错误 Span 时 | Error Span |
109
- | `attributes.custom()` | `reportCustomEvent()` 时 | Custom Span |
104
+ | 配置 | 调用时机 | 合并到 |
105
+ | --------------------- | --------------------------------- | --------------------------------------- |
106
+ | `user.id` | 构造时,之后可用 `setUser()` 更新 | 运行时 `user.id` |
107
+ | `attributes.page()` | 插件创建相关 Span、过滤层补属性时 | 页面/请求/事件 Span,具体取决于调用插件 |
108
+ | `attributes.error()` | 创建错误 Span 时 | Error Span |
109
+ | `attributes.custom()` | `reportCustomEvent()` 时 | Custom Span |
110
110
 
111
111
  Hook 每次调用都应返回新的普通对象,且不能抛异常。SDK 不 hash、不改写 `user.id`。如果 ID 敏感,接入方必须在传入前完成不可逆处理。
112
112
 
@@ -116,30 +116,30 @@ Hook 每次调用都应返回新的普通对象,且不能抛异常。SDK 不 h
116
116
 
117
117
  ## privacy
118
118
 
119
- | 配置 | 类型 | 默认 | 说明 |
120
- | --- | --- | --- | --- |
121
- | `trackingConsent` | `'granted' \| 'not-granted'` | `'granted'` | 初始化时是否安装采集插件 |
122
- | `redactUrl` | `(url: string) => string` | 去除认证信息、query、fragment | 所有按规范写入的 URL 在入 Span 前清洗 |
123
- | `redactAttributes` | `(attributes) => attributes` | 原样返回 | 插件 emit 和 Resource 构造时的统一属性过滤 |
119
+ | 配置 | 类型 | 默认 | 说明 |
120
+ | ------------------ | ---------------------------- | ----------------------------- | ------------------------------------------ |
121
+ | `trackingConsent` | `'granted' \| 'not-granted'` | `'granted'` | 初始化时是否安装采集插件 |
122
+ | `redactUrl` | `(url: string) => string` | 去除认证信息、query、fragment | 所有按规范写入的 URL 在入 Span 前清洗 |
123
+ | `redactAttributes` | `(attributes) => attributes` | 原样返回 | 插件 emit 和 Resource 构造时的统一属性过滤 |
124
124
 
125
125
  `redactAttributes` 必须返回合法 OpenTelemetry `Attributes`。删除字段时返回新对象最安全。Consent 与各 Hook 的覆盖边界见[隐私、Consent 与字段治理](./privacy.md)。
126
126
 
127
127
  ## tracking 默认开关
128
128
 
129
- | 配置 | 默认 | 类型/参数 | 作用 |
130
- | --- | --- | --- | --- |
131
- | `request` | 开 | `boolean \| BkOTRequestConfig` | Fetch/XHR、可选 traceparent |
132
- | `resource` | 开 | `boolean` | 静态资源 PerformanceResourceTiming |
133
- | `error` | 开 | `boolean` | runtime、Promise、资源加载错误 |
134
- | `webVitals` | 开 | `boolean` | CLS/FCP/INP/LCP/TTFB |
135
- | `action` | 开 | `boolean \| BkOTActionPluginOptions` | 点击 Action 与挫败信号 |
136
- | `blankScreen` | 开 | `boolean \| BkOTBlankScreenPluginOptions` | 白屏检测 |
137
- | `device` | 开 | `boolean \| BkOTDevicePluginOptions` | Resource 与运行时设备属性 |
138
- | `longTask` | 关 | `boolean \| BkOTLongTaskPluginOptions` | LoAF/Long Task |
139
- | `websocket` | 关 | `boolean` | WebSocket 连接生命周期 |
140
- | `cspViolation` | 关 | `boolean` | CSP violation |
141
- | `view` | 自动、loading 开 | `BkOTViewConfig` | View 边界、命名和 loading time |
142
- | `beforeSend` | 无 | `(event) => boolean \| void` | 所有结束 Span 的最终业务过滤 |
129
+ | 配置 | 默认 | 类型/参数 | 作用 |
130
+ | -------------- | ---------------- | ----------------------------------------- | ---------------------------------- |
131
+ | `request` | 开 | `boolean \| BkOTRequestConfig` | Fetch/XHR、可选 traceparent |
132
+ | `resource` | 开 | `boolean` | 静态资源 PerformanceResourceTiming |
133
+ | `error` | 开 | `boolean` | runtime、Promise、资源加载错误 |
134
+ | `webVitals` | 开 | `boolean` | CLS/FCP/INP/LCP/TTFB |
135
+ | `action` | 开 | `boolean \| BkOTActionPluginOptions` | 点击 Action 与挫败信号 |
136
+ | `blankScreen` | 开 | `boolean \| BkOTBlankScreenPluginOptions` | 白屏检测 |
137
+ | `device` | 开 | `boolean \| BkOTDevicePluginOptions` | Resource 与运行时设备属性 |
138
+ | `longTask` | 关 | `boolean \| BkOTLongTaskPluginOptions` | LoAF/Long Task |
139
+ | `websocket` | 关 | `boolean` | WebSocket 连接生命周期 |
140
+ | `cspViolation` | 关 | `boolean` | CSP violation |
141
+ | `view` | 自动、loading 开 | `BkOTViewConfig` | View 边界、命名和 loading time |
142
+ | `beforeSend` | 无 | `(event) => boolean \| void` | 所有结束 Span 的最终业务过滤 |
143
143
 
144
144
  Session、Activity 和 Page View 上下文是关联模型的基础,不提供统一的 `tracking.session: false` 或 `tracking.activity: false` 开关。
145
145
 
@@ -158,12 +158,12 @@ tracking: {
158
158
  }
159
159
  ```
160
160
 
161
- | 配置 | 默认 | 说明 |
162
- | --- | --- | --- |
163
- | `excludedUrls` | 无 | 匹配后不建请求 Span、不注入 trace header,也不计入 View/Action 活动 |
164
- | `allowedTracingUrls` | 无 | 只有明确匹配的 URL 才注入 W3C `traceparent`,同源也不例外;注入的是独立 trace context,并通过 Span Link 关联回 RUM Span。业务已自行设置 trace Header 时不注入 |
165
- | `beforeSend` | 无 | 只作用于 Fetch/XHR 请求事件;`event.resource.outcome` 区分 response/abort/timeout/network_error,返回 `false` 丢弃请求 Span |
166
- | `getUrlTemplate` | 折叠动态段后的 pathname | 生成低基数 `url.template`,例如 `/api/orders/:id`。收到的是未脱敏 URL,返回空值或抛错时回退到默认规则 |
161
+ | 配置 | 默认 | 说明 |
162
+ | -------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
163
+ | `excludedUrls` | 无 | 匹配后不建请求 Span、不注入 trace header,也不计入 View/Action 活动 |
164
+ | `allowedTracingUrls` | 无 | 字符串按绝对 HTTP(S) origin + 路径段匹配;只有明确匹配的 URL 才注入 W3C `traceparent`,同源也不例外;注入的是独立 trace context,并通过 Span Link 关联回 RUM Span。业务已自行设置 trace Header 时不注入 |
165
+ | `beforeSend` | 无 | 只作用于 Fetch/XHR 请求事件;`event.resource.outcome` 区分 response/abort/timeout/network_error,返回 `false` 丢弃请求 Span |
166
+ | `getUrlTemplate` | 折叠动态段后的 pathname | 生成低基数 `url.template`,例如 `/api/orders/:id`。收到的是未脱敏 URL,返回空值或抛错时回退到默认规则 |
167
167
 
168
168
  URL matcher 支持 string、RegExp 或函数:
169
169
 
@@ -176,50 +176,52 @@ URL matcher 支持 string、RegExp 或函数:
176
176
 
177
177
  ## view
178
178
 
179
- | 配置 | 类型 | 默认 | 说明 |
180
- | --- | --- | --- | --- |
181
- | `tracking` | `'auto' \| 'manual'` | `'auto'` | 自动监听 History/hash,或只接受 `startView()` |
182
- | `loadingTime` | `boolean` | `true` | 自动计算初始加载和路由稳定耗时 |
183
- | `getUrlTemplate` | `(url) => string \| undefined` | 折叠动态段后的 pathname | 生成低基数 `view.url_template` |
184
- | `excludedActivityUrls` | URL matcher | 无 | 不让长轮询/流式/埋点请求延长 View loading time |
179
+ | 配置 | 类型 | 默认 | 说明 |
180
+ | ---------------------- | --------------------------------------------- | -------------------------- | --------------------------------------------------------------- |
181
+ | `tracking` | `'auto' \| 'manual'` | `'auto'` | 自动监听 History/hash,或只接受 `startView()` |
182
+ | `routeMode` | `'auto' \| 'hash' \| 'history' \| 'document'` | `'auto'` | 同文档导航身份与默认模板规则;MPA 可明确选择 document |
183
+ | `loadingTime` | `boolean` | `true` | 自动计算初始加载和路由稳定耗时 |
184
+ | `getUrlTemplate` | `(url) => string \| undefined` | 折叠动态段后的逻辑路由路径 | 生成低基数 `view.url_template`,显式 startView urlTemplate 优先 |
185
+ | `excludedActivityUrls` | URL matcher | 无 | 不让长轮询/流式/埋点请求延长 View loading time |
185
186
 
186
- `getUrlTemplate` 返回 `undefined` 或抛错时回退到默认规则:取 pathname 并把数字 ID、UUID、长十六进制段折叠为 `:id`。它与 `tracking.request.getUrlTemplate` 共用这套默认折叠,但两者是独立入口——页面路由与 API 路径的模板规则通常不同。自动路由不会因 query-only 变化创建新 View;hash 变化会创建,但纯锚点语义由业务自行决定是否改用 manual。详见[View、路由与页面加载](./views-routing.md)。
187
+ `getUrlTemplate` 返回 `undefined` 或抛错时回退到默认规则:Hash 路由取逻辑路径,History/document 取 pathname,再把数字 ID、UUID、长十六进制段折叠为 `:id`。View 与 request 模板是独立入口。query-only 只更新 URL;history 忽略 fragment,hash 按逻辑路径划界,document 不创建同文档导航 View。auto 识别标准 #/、#!/ 路由,对非标准 hash 保留锚点启发式;框架路由应优先用明确模式或手动接入。详见[View、路由与页面加载](./views-routing.md)。
187
188
 
188
189
  ## action
189
190
 
190
- | 配置 | 类型 | 默认 | 说明 |
191
- | --- | --- | --- | --- |
192
- | `actionNameAttribute` | `string` | `'data-bk-action-name'` | 从目标或祖先读取显式名称 |
193
- | `maxDuration` | `number` | `10000` | Action 最长持续时间,非法或非正数回退默认 |
194
- | `nameCollection` | `'explicit' \| 'text'` | `'explicit'` | 是否允许从可访问名称/DOM 文本推导名称 |
191
+ | 配置 | 类型 | 默认 | 说明 |
192
+ | --------------------- | ---------------------- | ----------------------- | ----------------------------------------- |
193
+ | `actionNameAttribute` | `string` | `'data-bk-action-name'` | 从目标或祖先读取显式名称 |
194
+ | `maxDuration` | `number` | `10000` | Action 最长持续时间,非法或非正数回退默认 |
195
+ | `nameCollection` | `'explicit' \| 'text'` | `'explicit'` | 是否允许从可访问名称/DOM 文本推导名称 |
195
196
 
196
197
  `text` 可能采集用户界面文本,开启前必须做隐私评审。详见[用户操作与挫败信号](./actions.md)。
197
198
 
198
199
  ## blankScreen
199
200
 
200
- | 配置 | 类型 | 默认 | 说明 |
201
- | --- | --- | --- | --- |
202
- | `rootSelector` | `string` | `'body'` | 应用根节点;不存在会成为白屏候选 |
203
- | `threshold` | `number` | `0.8` | 九点采样中的空白比例阈值,截断至 0–1 |
204
- | `checkDelay` | `number` | `1000` | 页面活动稳定后的首检延迟 |
205
- | `confirmationDelay` | `number` | `200` | 两次白屏结果的确认间隔 |
206
- | `ignoreSelectors` | `string[]` | 内置 loading/skeleton 列表 | 追加忽略元素,不替换内置列表 |
201
+ | 配置 | 类型 | 默认 | 说明 |
202
+ | ------------------- | ---------- | -------------------------- | ------------------------------------------------------------------- |
203
+ | `rootSelector` | `string` | `'body'` | 应用根节点;不存在会成为白屏候选 |
204
+ | `threshold` | `number` | `0.8` | 九点采样中的空白比例阈值,截断至 0–1 |
205
+ | `checkDelay` | `number` | `1000` | 页面活动稳定后的首检延迟 |
206
+ | `confirmationDelay` | `number` | `200` | 两次白屏结果的确认间隔 |
207
+ | `maxWait` | `number` | `10000` | 文档/活动最长等待与低频复检间隔(ms),最小 100;超时只报告观测状态 |
208
+ | `ignoreSelectors` | `string[]` | 内置 loading/skeleton 列表 | 追加忽略元素,不替换内置列表 |
207
209
 
208
210
  SPA 应将 `rootSelector` 指向真实挂载节点。详见[白屏检测](./blank-screen.md)。
209
211
 
210
212
  ## device
211
213
 
212
- | 配置 | 类型 | 默认 | 说明 |
213
- | --- | --- | --- | --- |
214
- | `persistentId` | `boolean` | `false` | 是否把匿名设备 ID 持久化到 localStorage |
215
- | `storageKey` | `string` | `BK_RUM_DEVICE_ID_<应用 hash>` | 持久设备 ID 的 key |
214
+ | 配置 | 类型 | 默认 | 说明 |
215
+ | -------------- | --------- | ------------------------------ | --------------------------------------- |
216
+ | `persistentId` | `boolean` | `false` | 是否把匿名设备 ID 持久化到 localStorage |
217
+ | `storageKey` | `string` | `BK_RUM_DEVICE_ID_<应用 hash>` | 持久设备 ID 的 key |
216
218
 
217
219
  `persistentId: false` 时,每次 Device 插件初始化都会创建新的设备 ID,只在当前采集周期内稳定;撤销再授予 Consent 会重新初始化插件并换 ID。`tracking.device: false` 还会阻止 `user_agent.*` 与 `device.type` 这四个 Resource 属性生成。详见[Session、用户与设备上下文](./session-context.md)。
218
220
 
219
221
  ## longTask
220
222
 
221
- | 配置 | 类型 | 默认 | 说明 |
222
- | --- | --- | --- | --- |
223
+ | 配置 | 类型 | 默认 | 说明 |
224
+ | ----------- | -------- | ---- | --------------------------------- |
223
225
  | `threshold` | `number` | `50` | 最低 duration,非法或负数回退默认 |
224
226
 
225
227
  优先使用 Long Animation Frame API,不支持时回退 Long Tasks API;两者的可用字段不同。详见[性能体验与长任务](./performance.md)。
@@ -244,22 +246,23 @@ interface BkOTBeforeSendEvent {
244
246
  signal: 'span';
245
247
  name: string;
246
248
  attributes: Record<string, unknown>;
249
+ events?: TimedEvent[];
250
+ links?: Link[];
247
251
  }
248
252
  ```
249
253
 
250
254
  该 Hook 在 Span 结束、导出过滤阶段执行:
251
255
 
252
256
  - 返回 `false` 丢弃;返回 `void` 保留;
253
- - 可原地修改 `event.attributes`;
254
- - 只暴露名字和属性,不暴露 Span event、时间、status、trace ID;
255
- - 在 Span 已完成常规脱敏之后执行;该 Hook 新增或改写的字段不会再自动经过 `redactAttributes`;
256
- - Hook 抛异常时 SDK 保留 Span 并继续发送,`debug: true` 时打印 warning;业务仍应在 Hook 内避免可能失败或高开销的逻辑。
257
+ - 可原地修改或删除 `attributes` 中的字段,以及 `events`、`links` 导出副本;
258
+ - Hook 前后均对 Span/Event/Link 属性脱敏,`redactAttributes` 应保持幂等;
259
+ - 全局 Hook 或最终脱敏抛错时丢弃该条 Span,`debug: true` 时打印 warning,不影响业务请求。
257
260
 
258
261
  ## extensions
259
262
 
260
- | 配置 | 类型 | 默认 | 说明 |
261
- | --- | --- | --- | --- |
262
- | `plugins` | `BkOTPlugin[]` | `[]` | 使用 SDK RUM runtime context 的插件 |
263
+ | 配置 | 类型 | 默认 | 说明 |
264
+ | ------------------ | ------------------- | ---- | ------------------------------------------------------- |
265
+ | `plugins` | `BkOTPlugin[]` | `[]` | 使用 SDK RUM runtime context 的插件 |
263
266
  | `instrumentations` | `Instrumentation[]` | `[]` | 绑定 SDK 私有 WebTracerProvider 的 OTel instrumentation |
264
267
 
265
268
  两类扩展都在 SDK 获得 Consent 后启动,并在撤销 Consent/shutdown 时关闭。使用方法见[插件与 OpenTelemetry 扩展](./extensions.md)。
@@ -25,13 +25,13 @@ resourceSpans[]
25
25
 
26
26
  ## 五层字段
27
27
 
28
- | 层级 | 示例 | 生命周期 | 负责方 |
29
- | ------------------ | ----------------------------------------------------------- | ------------- | -------------------------- |
28
+ | 层级 | 示例 | 生命周期 | 负责方 |
29
+ | ------------------ | -------------------------------------------------------------- | ------------- | -------------------------- |
30
30
  | Resource | `service.name`、`telemetry.sdk.version`、`session.sample_rate` | SDK 实例固定 | 配置解析和 Device Resource |
31
- | OpenTelemetry Span | `traceId`、`spanId`、`kind`、开始/结束时间、Status | 单个 Span | OpenTelemetry Provider |
32
- | RUM 运行时上下文 | `session.id`、`view.id`、`action.id`、`user.id` | 随运行时变化 | `RumRuntimeContext` |
33
- | RUM 分类与结果 | `span_type`、`outcome.type` | 单个原始 Span | 内置插件或手动 API |
34
- | 领域字段 | `resource.*`、`vital.*`、`error.*`、`blank_screen.*` | 单项能力决定 | 对应插件 |
31
+ | OpenTelemetry Span | `traceId`、`spanId`、`kind`、开始/结束时间、Status | 单个 Span | OpenTelemetry Provider |
32
+ | RUM 运行时上下文 | `session.id`、`view.id`、`action.ids`、`user.id` | 随运行时变化 | `RumRuntimeContext` |
33
+ | RUM 分类与结果 | `span_type`、`outcome.type` | 单个原始 Span | 内置插件或手动 API |
34
+ | 领域字段 | `resource.*`、`vital.*`、`error.*`、`blank_screen.*` | 单项能力决定 | 对应插件 |
35
35
 
36
36
  服务端派生字段不属于以上五层,不应伪装成浏览器原始字段。
37
37
 
@@ -45,7 +45,7 @@ Resource 在构造时创建,同一 SDK 实例的全部 Span 共用。基础字
45
45
  | `service.version` | `application.version`,未配置时不存在 |
46
46
  | `deployment.environment.name` | `application.environment`,默认 `production` |
47
47
  | `session.sample_rate` | 解析后的 `session.sampleRate` |
48
- | `telemetry.sdk.name` | 固定 `blueking` |
48
+ | `telemetry.sdk.name` | 固定 `blueking` |
49
49
  | `telemetry.sdk.language` | 固定 `webjs` |
50
50
  | `telemetry.sdk.version` | 当前 npm 包版本 |
51
51
 
@@ -69,9 +69,8 @@ User(业务提供,可变)
69
69
  - `user.id`:业务方传入,可在 Session 内变化。
70
70
  - `session.id`:Session 插件生成,是采样和访问会话边界。
71
71
  - `view.id`:每个 View 新生成,是普通 RUM Span 的必要关联字段。
72
- - `action.id`:始终是字符串。
73
- 自动 Action 活动窗口内写入当前活动 Action ID,多个点击窗口重叠时取最近一次。
74
- Action 自身 Span 和手动 Action 各自写入当前 Action ID。
72
+ - `action.id`:自动/手动 Action 自身的单个字符串身份。
73
+ - `action.ids`:Resource/Error/Long Task 的关联数组,按事件发生时间匹配全部 Action 区间及 Session/View;多个窗口可重叠,不双写单值字段。
75
74
 
76
75
  普通 Span 没有有效 Session 和 View 时不会导出。Session 生命周期 Span允许没有 View。
77
76
 
@@ -84,7 +83,9 @@ User(业务提供,可变)
84
83
 
85
84
  服务端使用 `traceId + spanId` 做原始 Span 幂等和调用链还原,不再维护额外的 `event.id`。瞬时事件的开始时间就是事件发生时间;Resource 等区间 Span 的 start/end 表示真实持续区间。
86
85
 
87
- PerformanceObserver 的回调时间可能晚于事件发生时间,因此 Resource、Vital 和 Long Task 会使用 Performance Entry 对应的时间创建 Span,并按该时间回查 Session/View/Action。
86
+ PerformanceObserver 的回调时间可能晚于事件发生时间。Resource/Long Task 使用条目时间创建 Span并回查上下文;Vital 快照的 Span 时间是观测/修订时刻,身份使用所属 document/activation/view 的起点,具体发生时间由对应 vital 归因属性表达。
87
+
88
+ Vital 的 View 区间使用与 PerformanceEntry 一致的相对时间,独立保存 epoch 时间用于身份和上报,避免墙钟调整或休眠漂移导致错归属。活跃 View 在快照生成时读取最新用户及业务属性;结束时冻结完整上下文,迟到指标不会带入新 View 的用户,也不会补回已删除的属性。
88
89
 
89
90
  ## 生命周期事件
90
91
 
@@ -98,14 +99,18 @@ Session、View 和 WebSocket 使用瞬时生命周期 Span:
98
99
 
99
100
  View 每次发出 start/update/end 都会递增 `view.version`。服务端应以 `view.id + view.version` 幂等处理,并允许较低版本晚于较高版本到达。
100
101
 
102
+ View 快照同时包含累计 `view.time_spent`、已观测 `view.foreground_time`、`view.is_active` 与页面状态明细,周期/隐藏检查点不会续 Session。服务端取最新版本,不能累计相加;缺 end 时仅知道最后观测下界。
103
+
104
+ Vital 使用稳定 `vital.id` 和递增 `vital.version`,同一指标允许结束 View 后修订;按最大版本覆盖而不是按 value 取最大(INP 的 p98 可能下降)。白屏 `detected` 是 Error,`recovered`/`observation` 是 Custom,不把恢复和未知状态累计为错误数。
105
+
101
106
  ## RUM 分类字段
102
107
 
103
108
  每个内置事件使用统一分类:
104
109
 
105
- | 字段 | 说明 |
106
- | ---------------- | --------------------------------------------------------------------------------------------------- |
107
- | `span_type` | 大类:`session`、`view`、`resource`、`vital`、`error`、`long_task`、`action`、`websocket`、`custom` |
108
- | `outcome.type` | `success`、`warning`、`error`、`timeout`、`abort` |
110
+ | 字段 | 说明 |
111
+ | -------------- | --------------------------------------------------------------------------------------------------- |
112
+ | `span_type` | 大类:`session`、`view`、`resource`、`vital`、`error`、`long_task`、`action`、`websocket`、`custom` |
113
+ | `outcome.type` | `success`、`warning`、`error`、`timeout`、`abort` |
109
114
 
110
115
  `span_type` 表示 Span 类别,`outcome.type` 表示结果,两者不要混用。例如带异常的 `custom.checkout` 仍是 `span_type=custom`,但 `outcome.type=error` 且 Span Status 为 ERROR。具体子类由 `resource.type`、`vital.metric`、`error.source`、`blank_screen.reason` 等领域字段表达。当前 SDK **不写** `outcome.reason`。
111
116
 
@@ -141,9 +146,9 @@ HTTP 结果只映射 `outcome.type`:
141
146
 
142
147
  默认 `redactUrl` 删除 username、password、query 和 fragment,保留 scheme、host、port 和 path。它用于 SDK 明确认定为 URL 的字段。
143
148
 
144
- `redactAttributes` 用于 Resource 和 SDK 创建的 Span 顶层属性;`tracking.beforeSend` 是 Span 结束后的顶层 attributes 兜底。第三方 Instrumentation 自己创建的字段不保证在创建时经过 `redactAttributes`,可在 `beforeSend` 中统一处理顶层字段。
149
+ `redactAttributes` 用于 Resource 属性,并在最终导出前处理所有 Span、Event、Link 属性,包括第三方 Instrumentation。`tracking.beforeSend` 可修改或删除 attributes/events/links 的导出副本;Hook 前后都会脱敏,应保持幂等。
145
150
 
146
- 两者都不能读取或改写已经记录的 Span Event。自动 Error、Fetch 网络异常和带 Error 的 Custom Event 产生的 `exception` Event,需要在错误产生前避免敏感内容,或由 Collector 做二次清洗。Long Task 插件会在写入自己的 script/attribution Event 前显式执行 `redactAttributes`。
151
+ 自动 Error、Fetch 网络异常和 Custom Event 的 `exception` message/stacktrace 同样经过最终脱敏。修改导出副本不会回写已结束的原 Span;过滤或脱敏抛错时丢弃该条遥测。
147
152
 
148
153
  详见[隐私、Consent 与字段治理](./privacy.md)。
149
154
 
@@ -6,10 +6,10 @@
6
6
 
7
7
  ## 默认状态
8
8
 
9
- | 能力 | 配置 | 默认 |
10
- | --- | --- | --- |
11
- | JS / Promise / Resource Error | `tracking.error` | 开启 |
12
- | CSP Violation | `tracking.cspViolation` | 关闭 |
9
+ | 能力 | 配置 | 默认 |
10
+ | ----------------------------- | ----------------------- | ---- |
11
+ | JS / Promise / Resource Error | `tracking.error` | 开启 |
12
+ | CSP Violation | `tracking.cspViolation` | 关闭 |
13
13
 
14
14
  关闭 `tracking.error` 不影响 Blank Screen 和 CSP,它们是独立插件。
15
15
 
@@ -55,22 +55,22 @@ Reason 是 Error 时保留其名称;其他对象尝试 JSON stringify,失败
55
55
 
56
56
  三类自动错误都会调用 `recordException()`,在 Span 内增加标准 `exception` Event:
57
57
 
58
- | Event 字段 | 说明 |
59
- | --- | --- |
60
- | `exception.type` | Error 的 `name`;非 Error 值时为 `window.error`、`UnhandledRejection` 或 `ResourceError` |
61
- | `exception.message` | 完整消息 |
62
- | `exception.stacktrace` | Error 存在 Stack 时 |
58
+ | Event 字段 | 说明 |
59
+ | ---------------------- | ---------------------------------------------------------------------------------------- |
60
+ | `exception.type` | Error 的 `name`;非 Error 值时为 `window.error`、`UnhandledRejection` 或 `ResourceError` |
61
+ | `exception.message` | 完整消息 |
62
+ | `exception.stacktrace` | Error 存在 Stack 时 |
63
63
 
64
64
  Span Status 同时设为 ERROR,message 为归一错误消息。顶层 `error.message` 便于直接检索,Exception Event 保留标准异常语义。
65
65
 
66
66
  ## 页面和 Action 关联
67
67
 
68
- 错误发生时先通知 Activity Bus,再创建 Span:
68
+ 错误创建 Span 后,经过采样与 beforeSend 过滤,再通知 Action:
69
69
 
70
70
  - 当前 View 自动写入 `view.id`。
71
- - 当前自动 Action 活动窗口内写入 `action.id`。
71
+ - 按错误发生时间及 Session/View 写入全部匹配窗口的 `action.ids`。
72
72
  - Action 插件据此标记 `error_click`。
73
- - Error 不延长 View Loading Time,但会更新当前 Action 的活动时间并标记 `error_click`。
73
+ - 被过滤的错误不触发 `error_click`;Error 不延长 View 或 Action 的 Loading Time。
74
74
 
75
75
  ## 错误公共属性
76
76
 
@@ -146,7 +146,7 @@ tracking: {
146
146
  - 建立错误组;
147
147
  - 对告警和存储做风暴控制;
148
148
  - 保留采样修正前后的口径;
149
- - 使用 `session.id`、`view.id`、`action.id` 关联影响范围。
149
+ - 使用 `session.id`、`view.id`、`action.ids` 关联影响范围。
150
150
 
151
151
  ## 隐私风险
152
152
 
@@ -23,6 +23,7 @@ interface BkOTPlugin {
23
23
  name: string;
24
24
  enabled?: boolean | ((config: ResolvedBkOTConfig) => boolean);
25
25
  init(context: BkOTRuntimeContext): void | Promise<void>;
26
+ drain?(): void;
26
27
  flush?(): void | Promise<void>;
27
28
  shutdown?(): void | Promise<void>;
28
29
  }
@@ -31,10 +32,10 @@ interface BkOTPlugin {
31
32
  - `name` 用于诊断,不要求全局唯一,但推荐唯一。
32
33
  - `enabled=false` 或函数返回 false 时不启动。
33
34
  - `init` 按插件数组顺序等待执行。
34
- - `flush` 对所有已启动插件并行执行。
35
- - `shutdown` 按启动顺序反向、逐个等待执行。
35
+ - `flush` 先同步调用所有 `drain` 读取待交付队列,再按启动顺序执行检查点。
36
+ - `shutdown` 先 drain/flush,再按启动顺序反向、逐个停止;单个插件异常不会阻止其余清理。
36
37
  - 单个 init 抛错会被隔离;`debug=true` 时输出 warning。
37
- - init 失败的插件不会执行 shutdown。
38
+ - init 失败时会调用 shutdown 清理已经安装的副作用。
38
39
 
39
40
  ## 注册时机
40
41
 
@@ -78,6 +79,7 @@ await bkOT.start();
78
79
  | `context.tracer` | 直接使用 OTel Tracer |
79
80
  | `getRuntimeAttributes()` | 当前上下文快照 |
80
81
  | `getRuntimeAttributesAt(timestamp)` | 按事件时间回查上下文 |
82
+ | `getRuntimeContextAtRelativeTime(relativeTime)` | 按 Performance 相对起点查 Session/View/Action,返回 attributes 和用于上报的 epoch time;历史外返回 undefined |
81
83
  | `setRuntimeAttributes()` | 更新高级公共属性 |
82
84
  | `isSampled()` | 当前 Session 采样决定 |
83
85
  | `isSessionActive()` / `isViewActive()` | 有效上下文判断 |
@@ -98,10 +98,6 @@ export const rum = new BkOpenTelemetry({
98
98
  tracking: {
99
99
  view: {
100
100
  tracking: 'manual',
101
- getUrlTemplate(rawUrl) {
102
- const path = new URL(rawUrl, location.href).pathname;
103
- return path.replace(/\/orders\/[^/]+/, '/orders/:id');
104
- },
105
101
  },
106
102
  blankScreen: { rootSelector: '#app' },
107
103
  },
@@ -110,6 +106,7 @@ export const rum = new BkOpenTelemetry({
110
106
 
111
107
  ```ts
112
108
  // main.ts
109
+ import { trackVueRouterViews } from '@blueking/open-telemetry';
113
110
  import { createApp } from 'vue';
114
111
  import App from './App.vue';
115
112
  import router from './router';
@@ -117,30 +114,19 @@ import { rum } from './rum';
117
114
 
118
115
  const app = createApp(App).use(router);
119
116
 
120
- const syncView = (route: typeof router.currentRoute.value) => {
121
- const record = route.matched.at(-1);
122
- rum.startView({
123
- name: String(record?.name ?? record?.path ?? route.path),
124
- url: location.href,
125
- attributes: {
126
- 'app.route.name': String(record?.name ?? ''),
127
- },
128
- });
129
- };
130
-
131
117
  async function bootstrap() {
132
118
  await router.isReady();
133
119
  await rum.start();
134
120
 
135
- syncView(router.currentRoute.value);
136
- router.afterEach(to => syncView(to));
121
+ const stopTrackingViews = trackVueRouterViews(rum, router);
122
+ // 应用永久卸载时调用 stopTrackingViews()。
137
123
  app.mount('#app');
138
124
  }
139
125
 
140
126
  void bootstrap().catch(error => console.error('application bootstrap failed', error));
141
127
  ```
142
128
 
143
- 这里先同步一次当前 route,再注册后续导航,避免依赖 Router 初始导航 hook 的时序。`route.fullPath` 可能包含 query,不应直接作为 View name。
129
+ 辅助函数同步当前已解析路由,之后只接收成功且 path 改变的导航,并处理 BFCache 恢复。Hash/History 均使用 matched 参数化路径作为 name/template,不把业务 ID 或 query 当作页面名称。需要按 query 划分页面时,自行实现手动集成;不要同时注册两套路由监听。
144
130
 
145
131
  如果 blank screen 首检发生在应用 mount 之前,确保 HTML 已有 `#app` 根元素;否则应在初始化顺序或 `checkDelay` 上校准。
146
132
 
@@ -179,9 +165,7 @@ import { router } from './router';
179
165
  async function bootstrap() {
180
166
  await rum.start();
181
167
 
182
- createRoot(document.getElementById('root')!).render(
183
- <RouterProvider router={router} />,
184
- );
168
+ createRoot(document.getElementById('root')!).render(<RouterProvider router={router} />);
185
169
  }
186
170
 
187
171
  void bootstrap().catch(error => console.error('application bootstrap failed', error));
@@ -196,8 +180,7 @@ export const rum = new BkOpenTelemetry({
196
180
  tracking: {
197
181
  view: {
198
182
  tracking: 'manual',
199
- getUrlTemplate: rawUrl =>
200
- new URL(rawUrl, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id'),
183
+ getUrlTemplate: rawUrl => new URL(rawUrl, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id'),
201
184
  },
202
185
  blankScreen: { rootSelector: '#root' },
203
186
  },
@@ -338,7 +321,7 @@ consentManager.onChange(async allowed => {
338
321
  });
339
322
  ```
340
323
 
341
- 如果使用 manual View,授权后需要确认新的 Session 已创建,再按当前 Router 状态调用 `startView()`。自动模式会由 View 插件建立当前 View。
324
+ manual View 的 `startView()` 会保留最新路由意图,授权并建立有效 Session 后消费,撤权再授权时重建新的 View,不回放之前的 Span。授权前路由变化仍应同步调用 `startView()`;`trackVueRouterViews()` 已处理这一点。自动模式由 View 插件建立当前 View。
342
325
 
343
326
  这个示例适用于“授权前可以构造、但不能采集和发送”的策略。若合规要求授权前连 UA / UA-CH 这类 Device Resource 快照都不能读取,应把 `new BkOpenTelemetry()` 本身也延迟到首次授权后;只设置 `trackingConsent: 'not-granted'` 不会推迟构造阶段的 Device Resource 读取。
344
327