@blueking/open-telemetry 0.0.22-beta.1 → 0.0.23
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.
- package/README.md +258 -70
- package/dist/bk-rum.global.js +2 -2
- package/dist/bk-rum.global.js.map +1 -1
- package/dist/core/config.d.ts +10 -10
- package/dist/core/runtime-context.d.ts +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +608 -662
- package/dist/index.js.map +1 -1
- package/dist/plugins/blank-screen.d.ts +1 -1
- package/dist/plugins/common.d.ts +2 -2
- package/dist/plugins/device.d.ts +2 -2
- package/dist/plugins/resource.d.ts +1 -0
- package/dist/plugins/web-vitals.d.ts +1 -3
- package/dist/schema/attributes.d.ts +6 -7
- package/dist/schema/span.d.ts +24 -15
- package/package.json +1 -1
- package/skills/bk-rum-otele/SKILL.md +31 -30
- package/skills/bk-rum-otele/references/actions.md +166 -0
- package/skills/bk-rum-otele/references/api.md +248 -215
- package/skills/bk-rum-otele/references/architecture.md +139 -37
- package/skills/bk-rum-otele/references/blank-screen.md +190 -0
- package/skills/bk-rum-otele/references/capabilities.md +175 -83
- package/skills/bk-rum-otele/references/configuration.md +226 -151
- package/skills/bk-rum-otele/references/data-model.md +157 -24
- package/skills/bk-rum-otele/references/errors-security.md +168 -0
- package/skills/bk-rum-otele/references/extensions.md +237 -0
- package/skills/bk-rum-otele/references/framework-integration.md +318 -75
- package/skills/bk-rum-otele/references/getting-started.md +186 -70
- package/skills/bk-rum-otele/references/network.md +258 -0
- package/skills/bk-rum-otele/references/performance.md +198 -0
- package/skills/bk-rum-otele/references/privacy.md +236 -67
- package/skills/bk-rum-otele/references/production.md +266 -0
- package/skills/bk-rum-otele/references/session-context.md +185 -0
- package/skills/bk-rum-otele/references/telemetry-reference.md +500 -51
- package/skills/bk-rum-otele/references/transport-sampling.md +321 -32
- package/skills/bk-rum-otele/references/troubleshooting.md +341 -151
- package/skills/bk-rum-otele/references/views-routing.md +211 -0
- package/skills/bk-rum-otele/references/concepts.md +0 -60
- package/skills/bk-rum-otele/references/custom-plugin.md +0 -170
- package/skills/bk-rum-otele/references/plugins-basic.md +0 -135
- package/skills/bk-rum-otele/references/plugins-error-security.md +0 -86
- package/skills/bk-rum-otele/references/plugins-experience.md +0 -124
- package/skills/bk-rum-otele/references/plugins-network.md +0 -32
- package/skills/bk-rum-otele/references/plugins.md +0 -62
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
|
|
2
|
+
|
|
3
|
+
# 生产接入指南
|
|
4
|
+
|
|
5
|
+
生产接入的目标不只是“有数据”,而是数据边界正确、基数可控、容量可估算、跨域链路稳定,并且出现故障时不影响业务页面。
|
|
6
|
+
|
|
7
|
+
## 推荐基线
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { BkOpenTelemetry } from '@blueking/open-telemetry';
|
|
11
|
+
|
|
12
|
+
export const rum = new BkOpenTelemetry({
|
|
13
|
+
application: {
|
|
14
|
+
name: 'order-center',
|
|
15
|
+
environment: 'production',
|
|
16
|
+
version: window.__APP_VERSION__,
|
|
17
|
+
},
|
|
18
|
+
transport: {
|
|
19
|
+
endpoint: 'https://rum-collector.example.com',
|
|
20
|
+
token: window.__RUM_WRITE_TOKEN__,
|
|
21
|
+
processor: 'batch',
|
|
22
|
+
timeoutMillis: 10_000,
|
|
23
|
+
},
|
|
24
|
+
session: {
|
|
25
|
+
sampleRate: 0.2,
|
|
26
|
+
},
|
|
27
|
+
tracking: {
|
|
28
|
+
view: {
|
|
29
|
+
getPathGroup(rawUrl) {
|
|
30
|
+
return new URL(rawUrl, location.href).pathname
|
|
31
|
+
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
32
|
+
.replace(/\/users\/[^/]+/g, '/users/:id');
|
|
33
|
+
},
|
|
34
|
+
excludedActivityUrls: [/\/events\/stream(?:\?|$)/, /\/analytics(?:\?|$)/],
|
|
35
|
+
},
|
|
36
|
+
request: {
|
|
37
|
+
excludedUrls: [/\/health(?:\?|$)/],
|
|
38
|
+
allowedTracingUrls: [
|
|
39
|
+
rawUrl => new URL(rawUrl, location.href).origin === 'https://api.example.com',
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
blankScreen: {
|
|
43
|
+
rootSelector: '#app',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
privacy: {
|
|
47
|
+
redactUrl(rawUrl) {
|
|
48
|
+
const url = new URL(rawUrl, location.href);
|
|
49
|
+
url.username = '';
|
|
50
|
+
url.password = '';
|
|
51
|
+
url.search = '';
|
|
52
|
+
url.hash = '';
|
|
53
|
+
url.pathname = url.pathname
|
|
54
|
+
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
55
|
+
.replace(/\/users\/[^/]+/g, '/users/:id');
|
|
56
|
+
return url.href;
|
|
57
|
+
},
|
|
58
|
+
redactAttributes(attributes) {
|
|
59
|
+
const next = { ...attributes };
|
|
60
|
+
delete next['biz.secret'];
|
|
61
|
+
return next;
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
这只是结构基线,不能直接替代本应用的 URL、身份、隐私和容量评审。
|
|
68
|
+
|
|
69
|
+
## 1. 确定应用身份
|
|
70
|
+
|
|
71
|
+
建议:
|
|
72
|
+
|
|
73
|
+
- `application.name`:一个部署单元或前端产品的稳定名;
|
|
74
|
+
- `environment`:`production`、`staging` 等有限枚举;
|
|
75
|
+
- `version`:能映射到静态资源和 source map 的构建版本。
|
|
76
|
+
|
|
77
|
+
不要把租户、用户、主机、运行时间拼到这些 Resource 字段中。需要租户维度时使用经过评审的低基数自定义属性,并由服务端做权限隔离。
|
|
78
|
+
|
|
79
|
+
## 2. 估算采样与数据量
|
|
80
|
+
|
|
81
|
+
Session 采样率控制整体数据量。粗略估算:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
日 Span 量 ≈ 日 Session 数 × sampleRate × 采样 Session 的平均 Span 数
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
平均 Span 数受页面数、请求/资源数、错误、Vital、Action,以及 Long Task/CSP/WebSocket 开关影响。建议先在灰度环境或少量流量以 `sampleRate: 1` 测量,再回推生产比例。
|
|
88
|
+
|
|
89
|
+
采样策略注意:
|
|
90
|
+
|
|
91
|
+
- 同一 Session 采样决定稳定,适合还原完整用户旅程;
|
|
92
|
+
- 不支持按单一错误事件强制保留;
|
|
93
|
+
- sampleRate 变化只影响新建/轮换 Session 的决定;
|
|
94
|
+
- 服务端不能用已采样原始条数直接当全量用户数,必须结合采样率建模。
|
|
95
|
+
|
|
96
|
+
## 3. 控制路由和事件基数
|
|
97
|
+
|
|
98
|
+
必须排查:
|
|
99
|
+
|
|
100
|
+
- `view.url_path_group` 是否含订单 ID、用户 ID、UUID;
|
|
101
|
+
- custom/action name 是否拼业务 ID;
|
|
102
|
+
- 自定义属性是否包含时间戳、随机值、整条 URL;
|
|
103
|
+
- error message 是否因为动态值导致无限分组。
|
|
104
|
+
|
|
105
|
+
SDK 不在浏览器做错误指纹。服务端应基于 stack/message 归一规则生成 error group,同时保留原始事件供诊断。
|
|
106
|
+
|
|
107
|
+
## 4. 配置隐私边界
|
|
108
|
+
|
|
109
|
+
至少审查:
|
|
110
|
+
|
|
111
|
+
- URL path/query/fragment;
|
|
112
|
+
- 默认 `rum.page.path`(它不经过 `redactUrl` / `getPathGroup`);
|
|
113
|
+
- `user.id`;
|
|
114
|
+
- Error message 和 stack;
|
|
115
|
+
- Action 显式名称或 DOM 文本;
|
|
116
|
+
- CSP `original_policy`;
|
|
117
|
+
- Long Task source URL/function;
|
|
118
|
+
- View/Custom/Request Hook 添加的业务字段;
|
|
119
|
+
- 持久 Device ID 和 localStorage。
|
|
120
|
+
|
|
121
|
+
默认 URL 会删除 query/hash,但 path 不会模板化。完整边界见[隐私、Consent 与字段治理](./privacy.md)。
|
|
122
|
+
|
|
123
|
+
`tracking.beforeSend` 只暴露顶层 attributes,不能修改 exception Span Event 中的 message/stacktrace;异常内容必须在业务产生前避免携带密钥和个人信息,并在 Collector 端做二次清洗。
|
|
124
|
+
|
|
125
|
+
初始 `trackingConsent: 'not-granted'` 不等于“构造时完全不读取浏览器信息”。只要 `tracking.device !== false`,构造实例仍会读取 Device Resource 快照,但不会发送;要求授权前零读取时,应延迟到授权后再 `new BkOpenTelemetry()`。
|
|
126
|
+
|
|
127
|
+
## 5. 配置 Collector 与 CORS
|
|
128
|
+
|
|
129
|
+
验证真实浏览器请求,而不是只用 curl:
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
POST <endpoint>/v1/rum
|
|
133
|
+
Content-Type: application/json
|
|
134
|
+
Authorization: Bearer ...
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Collector 要求:
|
|
138
|
+
|
|
139
|
+
- OPTIONS 和 POST CORS 正确;
|
|
140
|
+
- body limit 能容纳 batch;
|
|
141
|
+
- 只接受受限 RUM 写入 token;
|
|
142
|
+
- 2xx 表示整批成功;
|
|
143
|
+
- 限流用 429/503 和合理 `Retry-After`;
|
|
144
|
+
- 能处理 OTLP JSON 的 `resourceSpans/scopeSpans/spans`;
|
|
145
|
+
- 对 tenant、service.name、environment 做校验;
|
|
146
|
+
- 具备服务端二次脱敏。
|
|
147
|
+
|
|
148
|
+
## 6. 谨慎开启 traceparent
|
|
149
|
+
|
|
150
|
+
默认不向任何业务请求注入,包括同源。只允许自有、已完成 CORS 和追踪评审的 API:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
allowedTracingUrls: [
|
|
154
|
+
rawUrl => {
|
|
155
|
+
const url = new URL(rawUrl, location.href);
|
|
156
|
+
return url.origin === 'https://api.example.com' && url.pathname.startsWith('/v2/');
|
|
157
|
+
},
|
|
158
|
+
]
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
不要使用宽泛 `/./` 或所有 URL,避免向第三方发送 Trace ID,也避免触发额外预检。API 端必须允许 `traceparent` header,并正确接续 W3C Trace Context。
|
|
162
|
+
|
|
163
|
+
## 7. 排除长活动与噪声
|
|
164
|
+
|
|
165
|
+
两类配置语义不同:
|
|
166
|
+
|
|
167
|
+
- `request.excludedUrls`:不采集、不注入、不计入活动;
|
|
168
|
+
- `view.excludedActivityUrls`:仍采集请求,但不让它延长 View loading time。
|
|
169
|
+
|
|
170
|
+
长轮询、流式 Fetch、埋点上报通常使用第二类;健康检查、明确无诊断价值的高频请求可使用第一类。
|
|
171
|
+
|
|
172
|
+
## 8. 校准白屏和 Action
|
|
173
|
+
|
|
174
|
+
白屏:
|
|
175
|
+
|
|
176
|
+
- SPA 设置真实 root;
|
|
177
|
+
- 骨架/loading selector 是否合理;
|
|
178
|
+
- Canvas/iframe 页面是否适合九点 DOM 采样;
|
|
179
|
+
- 在弱网和首屏延迟场景验证误报。
|
|
180
|
+
|
|
181
|
+
Action:
|
|
182
|
+
|
|
183
|
+
- 保留默认 `explicit`;
|
|
184
|
+
- 关键按钮添加稳定 `data-bk-action-name`;
|
|
185
|
+
- 不在显式名称中放用户或订单信息;
|
|
186
|
+
- 将 rage/dead/error click 当启发式信号,不当业务失败真值。
|
|
187
|
+
|
|
188
|
+
## 9. 控制可选高成本能力
|
|
189
|
+
|
|
190
|
+
默认关闭项应按问题启用:
|
|
191
|
+
|
|
192
|
+
| 能力 | 适合场景 | 主要风险 |
|
|
193
|
+
| --- | --- | --- |
|
|
194
|
+
| Long Task | 主线程卡顿和脚本归因 | 事件量、脚本 URL/函数信息 |
|
|
195
|
+
| CSP | 安全策略诊断 | `original_policy`、高频 violation |
|
|
196
|
+
| WebSocket | 连接失败/断开分析 | 全局 Proxy、长连接生命周期 |
|
|
197
|
+
|
|
198
|
+
先小流量评估平均每 Session 增量,再扩大采样。
|
|
199
|
+
|
|
200
|
+
## 10. 单实例与加载顺序
|
|
201
|
+
|
|
202
|
+
同一 window 只初始化一个实例,因为 SDK 会监听或 patch 全局能力。微前端应由主应用持有并向子应用暴露受控 API。
|
|
203
|
+
|
|
204
|
+
初始化越早,越能捕获首屏 navigation、资源和错误;但必须确保:
|
|
205
|
+
|
|
206
|
+
- endpoint/token 已可用;
|
|
207
|
+
- Consent 状态正确;
|
|
208
|
+
- `blankScreen.rootSelector` 已存在或会在检查前出现;
|
|
209
|
+
- 扩展已在 start 前注册。
|
|
210
|
+
|
|
211
|
+
需要等待 Consent 或运行配置时使用 `autoStart: false`。
|
|
212
|
+
|
|
213
|
+
## 11. 业务故障隔离
|
|
214
|
+
|
|
215
|
+
SDK 设计为:
|
|
216
|
+
|
|
217
|
+
- 单个插件 init 失败不阻断其他插件;
|
|
218
|
+
- 非 debug 模式尽量不污染业务 Console;
|
|
219
|
+
- exporter 失败不会让业务 Fetch/XHR 失败;
|
|
220
|
+
- unsupported Performance API 时跳过对应能力。
|
|
221
|
+
|
|
222
|
+
但自定义 Hook/插件仍是业务代码:必须快速、同步、无副作用,不应发网络请求或抛异常。上线前对 `redactUrl`、`redactAttributes`、`getPathGroup`、两个 `beforeSend` 做异常与性能测试。
|
|
223
|
+
|
|
224
|
+
## 12. 灰度验收
|
|
225
|
+
|
|
226
|
+
建议按以下顺序:
|
|
227
|
+
|
|
228
|
+
1. 测试环境 sampleRate 1,验证所有默认 Span;
|
|
229
|
+
2. 检查实际 OTLP JSON 的敏感字段;
|
|
230
|
+
3. 验证跨域 Collector、鉴权、429/503;
|
|
231
|
+
4. 验证 SPA route、BFCache、手动/自动 View 无重复;
|
|
232
|
+
5. 弱网、后台、关闭页面时验证尽力 flush;
|
|
233
|
+
6. 观察平均 Span/Session、batch body、错误率和队列丢弃;
|
|
234
|
+
7. 1% 或内部用户灰度;
|
|
235
|
+
8. 调整 sampleRate/排除项;
|
|
236
|
+
9. 扩大流量并配置服务端监控告警。
|
|
237
|
+
|
|
238
|
+
## 13. 服务端建模验收
|
|
239
|
+
|
|
240
|
+
服务端需要理解:
|
|
241
|
+
|
|
242
|
+
- Session/View 生命周期通过多条 Span 表达,`session.phase`、`view.phase` 与 `view.version` 用于重建状态;
|
|
243
|
+
- `action.id` 负责关联窗口,不提供客户端 count;
|
|
244
|
+
- `vital.value` 是原始指标;分位数服务端计算;
|
|
245
|
+
- 资源网络阶段只在浏览器可见时出现;
|
|
246
|
+
- IP/geo、错误指纹、聚合数不是 SDK 字段;
|
|
247
|
+
- 事件时间直接使用 OTLP envelope 的 `startTimeUnixNano/endTimeUnixNano` 纳秒字符串;
|
|
248
|
+
- Schema version 当前是 Resource `rum.schema.version=3`。
|
|
249
|
+
|
|
250
|
+
字段级规则见[遥测字段字典](./telemetry-reference.md)。
|
|
251
|
+
|
|
252
|
+
## 上线清单
|
|
253
|
+
|
|
254
|
+
- [ ] 单实例、初始化位置明确
|
|
255
|
+
- [ ] application name/environment/version 稳定
|
|
256
|
+
- [ ] endpoint 最终为 `/v1/rum` 且 CORS 通过
|
|
257
|
+
- [ ] token 最小权限,可轮换
|
|
258
|
+
- [ ] sampleRate 有容量依据
|
|
259
|
+
- [ ] 动态路由已分组、URL 已脱敏
|
|
260
|
+
- [ ] user/action/error/custom 字段完成隐私评审
|
|
261
|
+
- [ ] traceparent 只对明确 API 白名单开启
|
|
262
|
+
- [ ] 流式/长轮询不延长 View loading
|
|
263
|
+
- [ ] 白屏 root 和阈值经过真实页面验证
|
|
264
|
+
- [ ] 可选高成本插件按需启用
|
|
265
|
+
- [ ] Collector 有二次校验、服务端聚合和告警
|
|
266
|
+
- [ ] 有版本回滚和关闭 `enabled`/采样的应急开关
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
|
|
2
|
+
|
|
3
|
+
# Session 与公共上下文
|
|
4
|
+
|
|
5
|
+
Session 是采样和访问会话边界;User、Device 以及 Session 字段共同组成后续 Span 自动继承的公共上下文。Session 在获得 Consent 后始终启用,不能通过 `tracking` 关闭。
|
|
6
|
+
|
|
7
|
+
## Session 生命周期
|
|
8
|
+
|
|
9
|
+
SDK 使用以下固定规则:
|
|
10
|
+
|
|
11
|
+
| 规则 | 当前值 | 是否可配置 |
|
|
12
|
+
| --- | ---: | --- |
|
|
13
|
+
| 无活动超时 | 15 分钟 | 否 |
|
|
14
|
+
| 最长生命周期 | 4 小时 | 否 |
|
|
15
|
+
| 活动事件 | `click`、`keydown`、`scroll`、`touchstart` | 否 |
|
|
16
|
+
| 活动续期节流 | 1 秒 | 否 |
|
|
17
|
+
| 可见页面定期检查 | 60 秒 | 否 |
|
|
18
|
+
| 采样率 | `1` | 是,`session.sampleRate` |
|
|
19
|
+
|
|
20
|
+
初始化时,SDK 尝试从 localStorage 读取同一应用和 Collector 隔离的 Session Record:
|
|
21
|
+
|
|
22
|
+
- Record 有效:复用 ID,并延长无活动过期时间。
|
|
23
|
+
- Record 不存在:创建新 Session,发送 `browser.session` start。
|
|
24
|
+
- Record 已过期:创建新 ID,发送 rotate;旧 Session 的 end 由持有旧上下文的 Tab 发送。
|
|
25
|
+
- localStorage 不可访问:退回当前 JavaScript 进程内存,不影响页面采集,但不能跨页面或跨 Tab 共享。
|
|
26
|
+
|
|
27
|
+
## 续期与过期
|
|
28
|
+
|
|
29
|
+
用户活动会延长有效 Session。达到 15 分钟无活动或 4 小时最长生命周期时,SDK:
|
|
30
|
+
|
|
31
|
+
1. 通知 View、Action 等插件 Session 已过期。
|
|
32
|
+
2. 发送 `browser.session` end。
|
|
33
|
+
3. 清除运行时 `session.*`。
|
|
34
|
+
4. 结束当前 View。
|
|
35
|
+
5. 触发一次 flush。
|
|
36
|
+
6. 在下一次用户活动时创建新 Session 和 `session_renewal` View。
|
|
37
|
+
|
|
38
|
+
页面重新可见时只检查和延长仍有效的 Session,不会主动创建新 Session。这样后台放置很久的页面不会仅因切回前台就复活旧访问。
|
|
39
|
+
|
|
40
|
+
## 跨 Tab 行为
|
|
41
|
+
|
|
42
|
+
默认 storage key 根据 `application.name` 与解析后 Endpoint host 计算,多个同源 Tab 因而共享 Session Record。
|
|
43
|
+
|
|
44
|
+
- 其他 Tab 只延长当前相同 Session 时,本 Tab 会更新自己的过期 Timer。
|
|
45
|
+
- 其他 Tab 使 Session 过期或替换 ID 时,本 Tab 会停用自己的 Session。
|
|
46
|
+
- 已停用的 Tab 不会被其他 Tab 的新 Session 被动复活;本 Tab 发生用户活动后才读取并接管共享 Session。
|
|
47
|
+
|
|
48
|
+
需要完全隔离不同接入实例时,可设置显式 `session.storageKey`。
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
new BkOpenTelemetry({
|
|
52
|
+
application: { name: 'order-web' },
|
|
53
|
+
transport: { endpoint: 'https://rum.example.com' },
|
|
54
|
+
session: {
|
|
55
|
+
sampleRate: 0.2,
|
|
56
|
+
storageKey: 'bk-rum-order-session',
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Session 采样
|
|
62
|
+
|
|
63
|
+
采样决定由 `application.name + "\0" + session.id` 的稳定 hash 得出:
|
|
64
|
+
|
|
65
|
+
- `sampleRate <= 0`:全部不采样。
|
|
66
|
+
- `sampleRate >= 1`:全部采样。
|
|
67
|
+
- 中间值:同一应用、同一 Session 始终得到相同决定。
|
|
68
|
+
- Session 轮换后使用新 ID 重新计算。
|
|
69
|
+
|
|
70
|
+
输入有限数值会限制到 `0..1`;缺省、`NaN` 或无限值回退为 `1`。采样率写入 Resource 的 `session.sample_rate`,不是每条 Span 的业务属性。
|
|
71
|
+
|
|
72
|
+
完整过滤与上报行为见[上报协议、批处理与采样](./transport-sampling.md)。
|
|
73
|
+
|
|
74
|
+
## Session 遥测
|
|
75
|
+
|
|
76
|
+
Span 名固定为 `browser.session`:
|
|
77
|
+
|
|
78
|
+
| `session.phase` | 使用时机 | 常见 reason |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `start` | 首次创建 | `init` |
|
|
81
|
+
| `rotate` | 旧 Session 过期后新建 | `inactivity`、`maxLifetime` |
|
|
82
|
+
| `end` | 当前 Session 失效 | `inactivity`、`maxLifetime`、`external` |
|
|
83
|
+
|
|
84
|
+
关键字段:
|
|
85
|
+
|
|
86
|
+
- `session.id`
|
|
87
|
+
- `session.start_time`
|
|
88
|
+
- `session.type=user`
|
|
89
|
+
- `session.has_replay=false`
|
|
90
|
+
- `session.lifecycle.reason`
|
|
91
|
+
- `session.previous_id`,仅存在前一个 ID 时出现
|
|
92
|
+
- `session.phase`
|
|
93
|
+
|
|
94
|
+
生命周期 Span 是瞬时事件,持续时间由服务端根据时间戳推导。
|
|
95
|
+
|
|
96
|
+
## User 上下文
|
|
97
|
+
|
|
98
|
+
初始化时可传入用户:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const bkOT = new BkOpenTelemetry({
|
|
102
|
+
application: { name: 'order-web' },
|
|
103
|
+
transport: { endpoint: 'https://rum.example.com' },
|
|
104
|
+
context: {
|
|
105
|
+
user: { id: anonymizedUserId },
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
bkOT.setUser({ id: 'user-002' });
|
|
110
|
+
bkOT.setUser({ id: undefined });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
SDK 只维护 `user.id`,并原样透传:不 hash、不截断、不验证、不自动脱敏。调用 `setUser()` 只影响之后创建的 Span,不会改写已结束数据,也不会触发 Session 轮换。
|
|
114
|
+
|
|
115
|
+
## Device Resource 属性
|
|
116
|
+
|
|
117
|
+
`tracking.device` 默认开启。构造阶段读取相对稳定的设备信息并写入 Resource:
|
|
118
|
+
|
|
119
|
+
| 字段 | 来源 | 可能缺失 |
|
|
120
|
+
| --- | --- | --- |
|
|
121
|
+
| `browser.name` | UA 简单识别:Edge/Chrome/Firefox/Safari/Other | 否 |
|
|
122
|
+
| `browser.version` | UA 主版本 | 未识别版本时 |
|
|
123
|
+
| `os.name` | UA / UA-CH platform | 否,无法识别为 `Other` |
|
|
124
|
+
| `device.type` | UA-CH mobile 或移动 UA | 否 |
|
|
125
|
+
| `device.memory_gib` | `navigator.deviceMemory` | 浏览器未实现时 |
|
|
126
|
+
| `device.logical_processor_count` | `navigator.hardwareConcurrency` | 浏览器未实现时 |
|
|
127
|
+
|
|
128
|
+
关闭 `tracking.device` 时,这些 Device Resource 字段不写入。
|
|
129
|
+
|
|
130
|
+
## Device 运行时属性
|
|
131
|
+
|
|
132
|
+
Device 插件还维护:
|
|
133
|
+
|
|
134
|
+
| 字段 | 更新时机 |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `device.id` | 插件启动时 |
|
|
137
|
+
| `browser.viewport.width/height` | 启动、resize、orientationchange |
|
|
138
|
+
| `browser.screen.width/height` | 启动、resize、orientationchange |
|
|
139
|
+
| `network.effective_type` | 启动和 connection change |
|
|
140
|
+
| `network.connection_type` | 同上 |
|
|
141
|
+
| `network.downlink` | 同上 |
|
|
142
|
+
| `network.rtt` | 同上 |
|
|
143
|
+
| `network.save_data` | 同上 |
|
|
144
|
+
|
|
145
|
+
视口变化使用 250ms trailing debounce;网络字段只有浏览器实现 Network Information API 时才存在。这些变化不主动生成 Span,只影响后续 Span 的上下文。
|
|
146
|
+
|
|
147
|
+
## Device ID 持久化
|
|
148
|
+
|
|
149
|
+
默认 `persistentId=false`:每次 Device 插件初始化时创建新的匿名设备 ID,只在当前采集周期内稳定;撤销并重新授予 Consent 会重新初始化插件,因此 ID 也会变化。
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
tracking: {
|
|
153
|
+
device: {
|
|
154
|
+
persistentId: true,
|
|
155
|
+
storageKey: 'BK_RUM_DEVICE_ID_ORDER',
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
开启后 ID 写入 localStorage;未指定 key 时按 `application.name` hash 隔离。localStorage 失败时仍生成内存 ID。持久设备 ID 会增加跨访问关联能力,也增加隐私风险,必须在取得合规依据后启用。
|
|
161
|
+
|
|
162
|
+
## 公共页面属性
|
|
163
|
+
|
|
164
|
+
`context.attributes.page` 在多数内置事件创建时执行:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
context: {
|
|
168
|
+
attributes: {
|
|
169
|
+
page: () => ({
|
|
170
|
+
'biz.space_id': currentSpaceId,
|
|
171
|
+
'biz.module': currentModule,
|
|
172
|
+
}),
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
未配置时默认返回 `rum.page.host` 和 `rum.page.path`。自定义 Hook 会完全替换默认实现,不是叠加;如仍需要默认字段,需自行返回。
|
|
178
|
+
|
|
179
|
+
Hook 每次执行,应保持低成本且不要抛错。它可能包含高基数字段,但服务端聚合维度应只选择稳定、低基数属性。
|
|
180
|
+
|
|
181
|
+
## Consent 对上下文的影响
|
|
182
|
+
|
|
183
|
+
`trackingConsent=not-granted` 时不创建 Session、不启动 Device 插件、不建立 View,也不安装浏览器 Patch。需要注意,SDK 构造时仍会为 OpenTelemetry Resource 同步读取稳定 Device 快照(除非 `tracking.device=false`),只是未授权时没有 Span 将它发送。运行期撤销 Consent 会停止插件并清除运行时 `session.id`,但当前实现不会删除 localStorage 中的 Session Record;重新授权时如果该 Record 仍有效,Session 插件可以恢复并续期同一 ID,否则创建新 Session。
|
|
184
|
+
|
|
185
|
+
完整 Consent 行为见[隐私、Consent 与字段治理](./privacy.md)。
|