@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
|
@@ -1,135 +1,251 @@
|
|
|
1
1
|
<!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
`@blueking/open-telemetry` 是面向浏览器真实用户监控(RUM)的 OpenTelemetry 封装 SDK。它将页面访问、资源加载、接口请求、JavaScript 错误、Web Vitals、空白屏、会话和用户动作等浏览器事件统一转成原始 RUM Span,通过单一 OTLP HTTP 通道上报。
|
|
3
|
+
# 快速上手
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
本页用最少步骤完成安装、上报验证和第一个生产前配置。开始前需要一个接受 OTLP/HTTP JSON Trace 的 Collector 根地址;SDK 会固定请求 `<endpoint>/v1/rum`。
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
- 使用 OpenTelemetry 标准协议接入已有 Collector 或蓝鲸 RUM 后端。
|
|
11
|
-
- 将浏览器事件与后端 trace 关联,定位一次访问中的慢请求、资源异常和前端错误。
|
|
12
|
-
- 通过插件逐步打开高级采集能力,控制数据量、隐私和性能成本。
|
|
7
|
+
## 1. 安装
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @blueking/open-telemetry
|
|
11
|
+
```
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
2. `plugins`:负责浏览器 RUM 事件采集,包括页面、资源、错误、性能、会话、动作等能力。
|
|
18
|
-
3. `schema`:负责 RUM 字段、span 类型、结果、耗时分桶等归一化模型。
|
|
19
|
-
4. `browser` / `index`:分别提供 CDN 全局入口(`https://unpkg.com/@blueking/open-telemetry/dist/bk-rum.global.js`)和 ESM 模块入口(`@blueking/open-telemetry`)。
|
|
13
|
+
也可以使用 npm 或 yarn。SDK 的 ESM 构建把 OpenTelemetry 依赖视为 package dependencies,由应用构建工具解析。
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
## 2. 最小初始化
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
在前端应用唯一入口创建一个实例:
|
|
24
18
|
|
|
25
19
|
```ts
|
|
20
|
+
// rum.ts
|
|
26
21
|
import { BkOpenTelemetry } from '@blueking/open-telemetry';
|
|
27
22
|
|
|
28
|
-
new BkOpenTelemetry({
|
|
23
|
+
export const rum = new BkOpenTelemetry({
|
|
29
24
|
application: {
|
|
30
|
-
name: '
|
|
31
|
-
environment: 'production',
|
|
32
|
-
version: '1.0.0',
|
|
25
|
+
name: 'order-center',
|
|
33
26
|
},
|
|
34
27
|
transport: {
|
|
35
28
|
endpoint: 'https://rum-collector.example.com',
|
|
36
|
-
token: 'report-token',
|
|
37
29
|
},
|
|
38
30
|
});
|
|
39
31
|
```
|
|
40
32
|
|
|
41
|
-
|
|
33
|
+
只有两个必填字段:
|
|
42
34
|
|
|
43
|
-
|
|
35
|
+
- `application.name`:稳定、低基数的应用名;
|
|
36
|
+
- `transport.endpoint`:上报根地址,不能为空。
|
|
44
37
|
|
|
45
|
-
|
|
38
|
+
构造后默认自动启动。最终请求:
|
|
46
39
|
|
|
47
|
-
```
|
|
48
|
-
|
|
40
|
+
```text
|
|
41
|
+
POST https://rum-collector.example.com/v1/rum
|
|
42
|
+
Content-Type: application/json
|
|
49
43
|
```
|
|
50
44
|
|
|
45
|
+
不要把 `/v1/rum` 写进 endpoint,否则会重复追加。
|
|
46
|
+
|
|
47
|
+
## 3. 验证接入
|
|
48
|
+
|
|
49
|
+
打开浏览器 DevTools:
|
|
50
|
+
|
|
51
|
+
1. Network 过滤 `v1/rum`;
|
|
52
|
+
2. 等待默认 batch 调度,或执行 `await rum.flush()`;
|
|
53
|
+
3. 确认 POST 返回 2xx;
|
|
54
|
+
4. 确认请求体顶层包含 `resourceSpans`;
|
|
55
|
+
5. 确认 Span attributes 有 `service.name`、`session.id` 和 `view.id`。
|
|
56
|
+
|
|
57
|
+
联调阶段可以显式启动并打开调试:
|
|
58
|
+
|
|
51
59
|
```ts
|
|
52
|
-
|
|
60
|
+
export const rum = new BkOpenTelemetry({
|
|
61
|
+
application: { name: 'order-center' },
|
|
62
|
+
transport: {
|
|
63
|
+
endpoint: 'https://rum-collector.example.com',
|
|
64
|
+
processor: 'simple',
|
|
65
|
+
},
|
|
66
|
+
session: { sampleRate: 1 },
|
|
67
|
+
debug: true,
|
|
68
|
+
autoStart: false,
|
|
69
|
+
});
|
|
53
70
|
|
|
54
|
-
|
|
71
|
+
await rum.start();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
控制台会在 exporter 前打印 `[bk-ot][rum]` Span。验证完成后生产环境应恢复 `processor: 'batch'`。
|
|
75
|
+
|
|
76
|
+
## 4. 添加应用版本和鉴权
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
export const rum = new BkOpenTelemetry({
|
|
55
80
|
application: {
|
|
56
|
-
name: '
|
|
81
|
+
name: 'order-center',
|
|
57
82
|
environment: 'production',
|
|
58
|
-
version: '
|
|
83
|
+
version: '2026.07.21',
|
|
59
84
|
},
|
|
60
85
|
transport: {
|
|
61
86
|
endpoint: 'https://rum-collector.example.com',
|
|
62
|
-
token: window.
|
|
63
|
-
},
|
|
64
|
-
session: {
|
|
65
|
-
sampleRate: 0.2,
|
|
87
|
+
token: window.__RUM_WRITE_TOKEN__,
|
|
66
88
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`token` 会生成:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
Authorization: Bearer <token>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
浏览器凭证对页面用户可见,必须是仅允许 RUM 写入的受限 token。自定义 header、重试、CORS 和 batch 规则见[上报协议、批处理与采样](./transport-sampling.md)。
|
|
99
|
+
|
|
100
|
+
## 5. 配置 Session 采样
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
session: {
|
|
104
|
+
sampleRate: 0.2,
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
这是 Session 级稳定采样:同一 Session 要么全部采集,要么全部不导出,而不是每个 Span 随机抽样。默认值为 `1`。
|
|
109
|
+
|
|
110
|
+
测试手动事件时先保持 `1`;生产采样率根据访问量、每会话事件数和 Collector 容量评估。
|
|
111
|
+
|
|
112
|
+
## 6. 治理动态路由
|
|
113
|
+
|
|
114
|
+
默认 `view.url_path_group` 是 pathname,因此 `/orders/1001` 与 `/orders/1002` 仍是两个分组。生产环境应模板化动态段:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
tracking: {
|
|
118
|
+
view: {
|
|
119
|
+
getPathGroup(rawUrl) {
|
|
120
|
+
const path = new URL(rawUrl, location.href).pathname;
|
|
121
|
+
return path
|
|
122
|
+
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
123
|
+
.replace(/\/users\/[^/]+/g, '/users/:id');
|
|
70
124
|
},
|
|
71
125
|
},
|
|
72
|
-
|
|
73
|
-
user: { id: window.__BK_USER__?.id },
|
|
74
|
-
},
|
|
75
|
-
});
|
|
126
|
+
}
|
|
76
127
|
```
|
|
77
128
|
|
|
78
|
-
`
|
|
129
|
+
这只治理聚合基数,不会清洗 `view.url`。URL 隐私需要另外配置 `privacy.redactUrl`。
|
|
79
130
|
|
|
80
|
-
##
|
|
131
|
+
## 7. 关联登录用户
|
|
81
132
|
|
|
82
133
|
```ts
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
});
|
|
134
|
+
rum.setUser({ id: 'internal-stable-id' });
|
|
135
|
+
|
|
136
|
+
// 登出
|
|
137
|
+
rum.setUser({ id: undefined });
|
|
138
|
+
```
|
|
89
139
|
|
|
90
|
-
|
|
140
|
+
也可以在构造时设置:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
context: {
|
|
144
|
+
user: { id: window.__USER__?.rumId },
|
|
145
|
+
}
|
|
91
146
|
```
|
|
92
147
|
|
|
93
|
-
|
|
148
|
+
SDK 原样透传 `user.id`,不会 hash。不要直接发送手机号、邮箱或可枚举的敏感账号标识。
|
|
94
149
|
|
|
95
|
-
|
|
150
|
+
## 8. 手动上报业务事件
|
|
151
|
+
|
|
152
|
+
手动 Action:
|
|
96
153
|
|
|
97
154
|
```ts
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
155
|
+
rum.reportAction({
|
|
156
|
+
name: 'submit-order',
|
|
157
|
+
attributes: {
|
|
158
|
+
'biz.order.channel': 'web',
|
|
159
|
+
},
|
|
103
160
|
});
|
|
161
|
+
```
|
|
104
162
|
|
|
105
|
-
|
|
106
|
-
|
|
163
|
+
自定义事件:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
rum.reportCustomEvent({
|
|
167
|
+
name: 'checkout_completed',
|
|
168
|
+
attributes: {
|
|
169
|
+
'biz.payment.method': 'card',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
107
172
|
```
|
|
108
173
|
|
|
109
|
-
|
|
174
|
+
带错误:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
rum.reportCustomEvent({
|
|
178
|
+
name: 'checkout_failed',
|
|
179
|
+
error: new Error('payment rejected'),
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
名称必须低基数,不要拼 ID 或用户输入。未命中 Session 采样时这些调用被静默丢弃。
|
|
184
|
+
|
|
185
|
+
手动事件不会在 SDK 启动期间排队。若首个事件的交付时序重要,请使用 `autoStart: false` 并在 `await rum.start()` 完成后调用;manual View 还必须先 `startView()`。默认异步 autoStart 更适合不依赖“构造后立即上报”的自动采集场景。
|
|
186
|
+
|
|
187
|
+
## 9. CDN 接入
|
|
110
188
|
|
|
111
189
|
```html
|
|
112
190
|
<script src="https://unpkg.com/@blueking/open-telemetry/dist/bk-rum.global.js"></script>
|
|
113
191
|
<script>
|
|
114
|
-
window.
|
|
115
|
-
application: {
|
|
116
|
-
|
|
192
|
+
window.rum = new window.BkOpenTelemetry({
|
|
193
|
+
application: {
|
|
194
|
+
name: 'legacy-portal',
|
|
195
|
+
environment: 'production',
|
|
196
|
+
},
|
|
197
|
+
transport: {
|
|
198
|
+
endpoint: 'https://rum-collector.example.com',
|
|
199
|
+
token: window.__RUM_WRITE_TOKEN__,
|
|
200
|
+
},
|
|
117
201
|
});
|
|
118
202
|
</script>
|
|
119
203
|
```
|
|
120
204
|
|
|
121
|
-
|
|
205
|
+
生产 CDN 地址应固定 npm package 版本并使用你们认可的 CDN/SRI 策略,不要长期跟随 latest。全局 bundle 包含所需依赖,公开类名是 `window.BkOpenTelemetry`。
|
|
206
|
+
|
|
207
|
+
## 默认会采集什么
|
|
208
|
+
|
|
209
|
+
最小配置默认开启:
|
|
210
|
+
|
|
211
|
+
- Session 与 View 生命周期;
|
|
212
|
+
- Fetch/XHR 和静态资源;
|
|
213
|
+
- JS、Promise、资源加载错误;
|
|
214
|
+
- CLS、FCP、INP、LCP、TTFB;
|
|
215
|
+
- 点击 Action 与挫败信号;
|
|
216
|
+
- 白屏检测;
|
|
217
|
+
- 设备、浏览器、屏幕和可用网络信息。
|
|
218
|
+
|
|
219
|
+
默认关闭 Long Task、WebSocket 和 CSP。所有数据都是原始 RUM Span,不会创建 Metric/Log Provider。精确默认值见[能力矩阵](./capabilities.md)。
|
|
220
|
+
|
|
221
|
+
## 自动 View 与手动 View
|
|
222
|
+
|
|
223
|
+
默认 auto 会监听 History API、pathname 和 hash。只有 Router 无法被正确识别,或业务需要完全控制边界时才用 manual:
|
|
122
224
|
|
|
123
225
|
```ts
|
|
124
|
-
|
|
125
|
-
name: '
|
|
126
|
-
|
|
226
|
+
const rum = new BkOpenTelemetry({
|
|
227
|
+
application: { name: 'manual-view-app' },
|
|
228
|
+
transport: { endpoint: 'https://rum-collector.example.com' },
|
|
229
|
+
autoStart: false,
|
|
230
|
+
tracking: {
|
|
231
|
+
view: { tracking: 'manual' },
|
|
232
|
+
},
|
|
127
233
|
});
|
|
128
234
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
235
|
+
await rum.start();
|
|
236
|
+
rum.startView({
|
|
237
|
+
name: 'order-detail',
|
|
238
|
+
url: location.href,
|
|
132
239
|
});
|
|
133
240
|
```
|
|
134
241
|
|
|
135
|
-
|
|
242
|
+
必须先建立采样 Session,再调用 `startView()`。不要同时保留 auto 路由追踪和 Router `afterEach` 手动创建,否则会重复 View。
|
|
243
|
+
|
|
244
|
+
## 接入后下一步
|
|
245
|
+
|
|
246
|
+
- 上线前逐项评审:[生产接入指南](./production.md)
|
|
247
|
+
- Vue、React、微前端:[框架与路由集成](./framework-integration.md)
|
|
248
|
+
- 查所有开关:[配置参考](./configuration.md)
|
|
249
|
+
- 理解服务端收到什么:[RUM 数据模型](./data-model.md)
|
|
250
|
+
- 查精确字段:[遥测字段字典](./telemetry-reference.md)
|
|
251
|
+
- 没有数据:[调试与排障](./troubleshooting.md)
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
<!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
|
|
2
|
+
|
|
3
|
+
# 请求、资源与 WebSocket
|
|
4
|
+
|
|
5
|
+
网络能力覆盖 Fetch、XMLHttpRequest、静态资源和 WebSocket。Fetch/XHR 由 SDK 自有单层 Patch 负责 Span、Trace Header、Resource Timing 和页面活动;静态资源由 PerformanceObserver 采集;WebSocket 只记录连接生命周期。
|
|
6
|
+
|
|
7
|
+
## 默认状态
|
|
8
|
+
|
|
9
|
+
| 能力 | 配置 | 默认 |
|
|
10
|
+
| --------- | -------------------- | ---- |
|
|
11
|
+
| Fetch/XHR | `tracking.request` | 开启 |
|
|
12
|
+
| 静态资源 | `tracking.resource` | 开启 |
|
|
13
|
+
| WebSocket | `tracking.websocket` | 关闭 |
|
|
14
|
+
|
|
15
|
+
SDK 不采集任何请求 Body、响应 Body、WebSocket 消息内容、消息数量或消息字节数。
|
|
16
|
+
|
|
17
|
+
## Fetch/XHR Patch
|
|
18
|
+
|
|
19
|
+
`tracking.request=false` 时完全不 Patch Fetch/XHR。开启时,同一层实现负责:
|
|
20
|
+
|
|
21
|
+
1. 把 URL 转成绝对 URL。
|
|
22
|
+
2. 排除 SDK 自身上报和 `excludedUrls`。
|
|
23
|
+
3. 创建 `browser.resource` CLIENT Span。
|
|
24
|
+
4. 按白名单决定是否注入 `traceparent`。
|
|
25
|
+
5. 把请求开始/结束通知给 View/Action 页面活动。
|
|
26
|
+
6. 根据 Response 或终止原因生成结构化 outcome,并补充结果、异常和 Resource Timing。
|
|
27
|
+
7. 执行请求级 `beforeSend`。
|
|
28
|
+
8. 结束 Span,并进入全局过滤链路。
|
|
29
|
+
|
|
30
|
+
Patch 在插件 shutdown 时仅在全局方法仍是 SDK 安装版本的情况下恢复,避免覆盖 SDK 之后由业务安装的其他 Patch。
|
|
31
|
+
|
|
32
|
+
## 请求 Span
|
|
33
|
+
|
|
34
|
+
Fetch 和 XHR 都生成 `browser.resource`:
|
|
35
|
+
|
|
36
|
+
| 字段 | Fetch | XHR |
|
|
37
|
+
| --------------------------- | ---------------------------------------------- | --------------------------- |
|
|
38
|
+
| `resource.type` | `fetch` | `xhr` |
|
|
39
|
+
| `http.request.method` | `init.method`、Request method 或 `GET`,转大写 | `open()` method,转大写 |
|
|
40
|
+
| `url.full` | 绝对 URL,经脱敏 | 同左 |
|
|
41
|
+
| `http.response.status_code` | 获得真实 Response status 时 | `load` 且 `xhr.status>0` 时 |
|
|
42
|
+
| Span Kind | CLIENT | CLIENT |
|
|
43
|
+
|
|
44
|
+
Span 开始时间使用请求开始时间,结束时间优先使用匹配到的 `PerformanceResourceTiming.responseEnd`;没有匹配时使用 Fetch resolve/reject 或 XHR `load/abort/timeout/error` 的完成时间。`http.response.status_code` 只表示真实 HTTP Response,不会上报 XHR 的本地占位值 `0`。
|
|
45
|
+
|
|
46
|
+
## Outcome 与 Status
|
|
47
|
+
|
|
48
|
+
| 条件 | `outcome.type` | `outcome.reason` | OTel Status |
|
|
49
|
+
| ---------------------------------- | -------------- | ----------------- | --------------------------- |
|
|
50
|
+
| `408` / `504` | `timeout` | `network_timeout` | ERROR |
|
|
51
|
+
| 其他 `4xx` | `error` | `http_4xx` | ERROR |
|
|
52
|
+
| `5xx` | `error` | `http_5xx` | ERROR |
|
|
53
|
+
| Fetch AbortError / XHR `abort` | `abort` | 不写 | UNSET,不记录 exception |
|
|
54
|
+
| Fetch TimeoutError / XHR `timeout` | `timeout` | `network_timeout` | ERROR,Fetch 记录 exception |
|
|
55
|
+
| Fetch 其他 reject / XHR `error` | `error` | `network` | ERROR,Fetch 记录 exception |
|
|
56
|
+
| XHR `load` 但无法取得有效状态 | `error` | `network` | ERROR |
|
|
57
|
+
| 其余 | `success` | 不写 | UNSET |
|
|
58
|
+
|
|
59
|
+
SDK 不根据业务响应 JSON 中的 code 判断成功或失败;需要业务口径时使用 `request.beforeSend` 增加属性,或上报自定义事件。
|
|
60
|
+
|
|
61
|
+
## URL 排除
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
tracking: {
|
|
65
|
+
request: {
|
|
66
|
+
excludedUrls: [
|
|
67
|
+
'/health',
|
|
68
|
+
/\/polling\/(?:[^?]+)(?:\?|$)/,
|
|
69
|
+
url => new URL(url).hostname === 'analytics.example.com',
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Matcher 规则:
|
|
76
|
+
|
|
77
|
+
- 字符串:`absoluteUrl.includes(matcher)`,不是精确路径匹配。
|
|
78
|
+
- 正则:匹配前重置 `lastIndex=0`,可安全复用带 `g` 的正则。
|
|
79
|
+
- 函数:收到绝对 URL,返回 boolean。
|
|
80
|
+
|
|
81
|
+
命中 `excludedUrls` 后不创建 Span、不注入 Header、也不参与 View/Action 活动。SDK 自身 `/v1/rum` 请求始终排除,比较时忽略 query、fragment 和末尾斜杠。
|
|
82
|
+
|
|
83
|
+
## W3C Trace Context
|
|
84
|
+
|
|
85
|
+
默认不向任何请求注入 Trace Header,包括同源请求。只有 `allowedTracingUrls` 显式命中时才使用 `W3CTraceContextPropagator` 注入 `traceparent`:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
tracking: {
|
|
89
|
+
request: {
|
|
90
|
+
allowedTracingUrls: [
|
|
91
|
+
url => new URL(url).origin === 'https://api.example.com',
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Fetch 会合并 `init.headers` 或输入 Request 的 Headers;XHR 使用 `setRequestHeader()`。白名单应使用 URL-aware 函数或有边界的正则,不要用过宽字符串。
|
|
98
|
+
|
|
99
|
+
当前请求 Span 命中 Session 采样后,注入值采用 W3C Trace Context v00:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
103
|
+
│ └──────────── trace-id:32 位小写十六进制 ────────────┘
|
|
104
|
+
└ version=00 parent-id:16 位 ─────┘ sampled=01
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
这里的 `parent-id` 是本次 Fetch/XHR CLIENT Span 的 `spanId`。请求 Patch 只在当前 Session 已采样时创建并注入记录型 Span,因此当前实现发出的 flags 为 `01`。如果活动父上下文带有 `traceState`,传播器还会写 `tracestate`;SDK 自身不创建 `tracestate`。
|
|
108
|
+
|
|
109
|
+
已有 Header 的处理取决于浏览器 API:
|
|
110
|
+
|
|
111
|
+
- Fetch 使用 `Headers.set()`,会覆盖 Headers 中已有的 `traceparent` / `tracestate`;
|
|
112
|
+
- XHR 在 `send()` 前调用 `setRequestHeader()`,浏览器可能把业务先设置的同名值追加合并,形成无效 Trace Context;不要由业务再手工设置同名 Header;
|
|
113
|
+
- SDK 不先解析入站 Header 再决定是否保留,`allowedTracingUrls` 命中即按当前活动 SpanContext 注入。
|
|
114
|
+
|
|
115
|
+
跨域注入会触发 CORS 预检,服务端至少需要允许:
|
|
116
|
+
|
|
117
|
+
```http
|
|
118
|
+
Access-Control-Allow-Origin: https://your-web.example.com
|
|
119
|
+
Access-Control-Allow-Headers: traceparent, tracestate
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
若你的链路从不携带 `tracestate`,可以只允许 `traceparent`;如业务还有自定义 Header,应一并加入允许列表。
|
|
123
|
+
|
|
124
|
+
## 请求级 beforeSend
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
tracking: {
|
|
128
|
+
request: {
|
|
129
|
+
beforeSend(event, context) {
|
|
130
|
+
event.attributes['biz.api_group'] = classifyApi(event.resource.url);
|
|
131
|
+
if (
|
|
132
|
+
event.resource.outcome.type === 'response' &&
|
|
133
|
+
event.resource.outcome.statusCode === 404 &&
|
|
134
|
+
event.resource.url?.includes('/optional/')
|
|
135
|
+
) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`event.type` 固定为 `resource`;`event.resource` 包含 `transport`、`url`、`method` 和结构化 `outcome`:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
type BkOTRequestOutcome =
|
|
147
|
+
| { type: 'response'; statusCode?: number }
|
|
148
|
+
| { type: 'abort' }
|
|
149
|
+
| { type: 'timeout'; error?: unknown }
|
|
150
|
+
| { type: 'network_error'; error?: unknown };
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
第二个参数保留原始浏览器上下文:
|
|
154
|
+
|
|
155
|
+
- Fetch:`request`、可选 `response`、可选 `error`。
|
|
156
|
+
- XHR:原始 `XMLHttpRequest` 实例。
|
|
157
|
+
|
|
158
|
+
Hook 可原地修改 `event.attributes`;返回 `false` 时给 Span 写入内部丢弃标记,Span 正常结束但不会进入 Exporter。Hook 抛错时默认继续发送,`debug=true` 输出 warning。
|
|
159
|
+
|
|
160
|
+
之后仍会执行 `privacy.redactAttributes` 和全局 `tracking.beforeSend`。
|
|
161
|
+
|
|
162
|
+
## Resource Timing 匹配
|
|
163
|
+
|
|
164
|
+
Fetch resolve/reject 和 XHR 终止事件往往早于 Resource Timing Observer 回调。SDK 在请求完成后最多等待 200ms:
|
|
165
|
+
|
|
166
|
+
- 以去掉 fragment 后的绝对 URL 匹配;
|
|
167
|
+
- 同 URL 并发请求选择开始时间最接近的 Entry;
|
|
168
|
+
- 允许 Performance Entry 比 JavaScript 请求开始早最多 50ms;
|
|
169
|
+
- 待匹配队列最多 100 条,超出时释放最旧请求。
|
|
170
|
+
|
|
171
|
+
匹配成功后,请求 Span 使用 Resource Timing 的结束时间,并增加 DNS、连接、TLS、TTFB、下载、Body Size 等字段。匹配失败不影响基础请求 Span。
|
|
172
|
+
|
|
173
|
+
## 静态资源
|
|
174
|
+
|
|
175
|
+
`tracking.resource=true` 时,Resource PerformanceObserver 为非 Fetch/XHR Entry 创建独立 `browser.resource` CLIENT Span。Fetch 和 `xmlhttprequest` Entry 只回填已有请求 Span,不重复上报。
|
|
176
|
+
|
|
177
|
+
常见资源类型来自 `initiatorType`,例如 `script`、`link`、`img`、`css`、`beacon`、`other`。
|
|
178
|
+
|
|
179
|
+
| 字段 | 说明 |
|
|
180
|
+
| --------------------------------- | ---------------------------------------------------------- |
|
|
181
|
+
| `resource.type` | initiator type |
|
|
182
|
+
| `resource.size` | `transferSize` |
|
|
183
|
+
| `resource.encoded_body_size` | 编码后 Body Size |
|
|
184
|
+
| `resource.decoded_body_size` | 解码后 Body Size |
|
|
185
|
+
| `resource.protocol` | `nextHopProtocol`,例如 `h2` |
|
|
186
|
+
| `resource.cache.hit` | deliveryType=cache,或 transferSize=0 且 decodedBodySize>0 |
|
|
187
|
+
| `resource.delivery_type` | 浏览器提供的 delivery type |
|
|
188
|
+
| `resource.render_blocking_status` | blocking / non-blocking,浏览器支持时 |
|
|
189
|
+
|
|
190
|
+
## 网络阶段字段
|
|
191
|
+
|
|
192
|
+
每个阶段同时写相对资源开始的 `start` 和阶段 `duration`,单位 ms:
|
|
193
|
+
|
|
194
|
+
- `resource.redirect.*`
|
|
195
|
+
- `resource.worker.*`
|
|
196
|
+
- `resource.dns.*`
|
|
197
|
+
- `resource.connect.*`
|
|
198
|
+
- `resource.ssl.*`
|
|
199
|
+
- `resource.first_byte.*`
|
|
200
|
+
- `resource.download.*`
|
|
201
|
+
|
|
202
|
+
SDK 先验证 `startTime → fetchStart → DNS → connect → request → response` 全部有限且非递减;任一异常时整组阶段字段不写入,避免负耗时污染。Safari 等返回 `duration=0` 但 `responseEnd` 有效时,总 Span duration 回退为 `responseEnd - startTime`。
|
|
203
|
+
|
|
204
|
+
跨域资源缺少 `Timing-Allow-Origin` 时,浏览器会清零或隐藏部分阶段。SDK 不伪造缺失值。需要完整瀑布时,资源服务端应返回:
|
|
205
|
+
|
|
206
|
+
```http
|
|
207
|
+
Timing-Allow-Origin: https://your-web.example.com
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 仅关闭静态资源 Span
|
|
211
|
+
|
|
212
|
+
`tracking.resource=false` 不会完全关闭 Resource Observer。Observer 仍用于:
|
|
213
|
+
|
|
214
|
+
- 把 Fetch/XHR Resource Timing 回填到请求 Span;
|
|
215
|
+
- 把静态资源完成通知给 View/Action 页面活动。
|
|
216
|
+
|
|
217
|
+
它只禁止为静态资源创建独立 Span。
|
|
218
|
+
|
|
219
|
+
## WebSocket 生命周期
|
|
220
|
+
|
|
221
|
+
`tracking.websocket=true` 时,SDK 使用 Proxy 包装全局 `WebSocket` 构造器,并保持静态常量、`instanceof` 和子类构造行为。每条连接生成 `websocket.connection.id`,随后发送四类瞬时 CLIENT Span:
|
|
222
|
+
|
|
223
|
+
| phase | 时机 | 额外字段 |
|
|
224
|
+
| --------- | --------------------- | ------------------------------ | -------- |
|
|
225
|
+
| `connect` | 构造 WebSocket 后立即 | 基础目标字段 |
|
|
226
|
+
| `open` | `open` Event | 无 |
|
|
227
|
+
| `error` | `error` Event | `websocket.error.phase=connect | runtime` |
|
|
228
|
+
| `close` | `close` Event | code、reason、was_clean |
|
|
229
|
+
|
|
230
|
+
Span 名统一为 `browser.websocket`,通过 `websocket.phase` 区分,不使用长连接 Span。基础字段包括:
|
|
231
|
+
|
|
232
|
+
- `network.protocol.name=websocket`
|
|
233
|
+
- `url.full`,经脱敏
|
|
234
|
+
- `url.scheme=ws|wss`
|
|
235
|
+
- `server.address`
|
|
236
|
+
- 存在显式端口时的 `server.port`
|
|
237
|
+
|
|
238
|
+
命中 SDK Endpoint 排除规则的 URL 不采集。WebSocket 没有独立 excludedUrls;如需更细过滤,应关闭内置能力并使用自定义插件。
|
|
239
|
+
|
|
240
|
+
## 常见问题
|
|
241
|
+
|
|
242
|
+
### 请求重复
|
|
243
|
+
|
|
244
|
+
优先检查:
|
|
245
|
+
|
|
246
|
+
- 同页是否初始化多个 SDK 实例;
|
|
247
|
+
- 是否额外启用了 Fetch/XHR OpenTelemetry Instrumentation;
|
|
248
|
+
- 是否同时由微前端主、子应用初始化。
|
|
249
|
+
|
|
250
|
+
### 有请求 Span 但没有网络阶段
|
|
251
|
+
|
|
252
|
+
可能原因:浏览器不支持 Resource Timing、200ms 内没有匹配到 Entry、同 URL 高并发匹配失败、跨域缺少 TAO,或浏览器返回乱序时间点。
|
|
253
|
+
|
|
254
|
+
### 后端没有收到 traceparent
|
|
255
|
+
|
|
256
|
+
检查 URL 是否真正命中 `allowedTracingUrls`、浏览器预检是否成功、服务端是否允许 `traceparent`,以及代理是否删除该 Header。
|
|
257
|
+
|
|
258
|
+
完整字段见[遥测字段字典](./telemetry-reference.md#请求与静态资源字段)。
|