@blueking/open-telemetry 0.0.26 → 0.0.28
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 +3 -3
- package/dist/bk-rum.global.js +2 -2
- package/dist/bk-rum.global.js.map +1 -1
- package/dist/core/config.d.ts +7 -4
- package/dist/core/plugin.d.ts +3 -1
- package/dist/core/runtime-context.d.ts +1 -1
- package/dist/core/trace-context.d.ts +36 -0
- package/dist/core/url.d.ts +5 -0
- package/dist/index.js +565 -381
- package/dist/index.js.map +1 -1
- package/dist/schema/attributes.d.ts +1 -1
- package/package.json +2 -2
- package/skills/bk-rum-otele/SKILL.md +1 -1
- package/skills/bk-rum-otele/evals/evals.json +1 -1
- package/skills/bk-rum-otele/references/architecture.md +1 -1
- package/skills/bk-rum-otele/references/capabilities.md +3 -3
- package/skills/bk-rum-otele/references/configuration.md +6 -5
- package/skills/bk-rum-otele/references/framework-integration.md +7 -7
- package/skills/bk-rum-otele/references/getting-started.md +2 -2
- package/skills/bk-rum-otele/references/network.md +64 -16
- package/skills/bk-rum-otele/references/privacy.md +8 -6
- package/skills/bk-rum-otele/references/production.md +5 -3
- package/skills/bk-rum-otele/references/session-context.md +1 -1
- package/skills/bk-rum-otele/references/telemetry-reference.md +22 -8
- package/skills/bk-rum-otele/references/transport-sampling.md +1 -1
- package/skills/bk-rum-otele/references/troubleshooting.md +11 -1
- package/skills/bk-rum-otele/references/views-routing.md +6 -6
- package/dist/core/telemetry-attributes.d.ts +0 -3
|
@@ -54,7 +54,7 @@ export declare const RUM_ATTRIBUTES: {
|
|
|
54
54
|
readonly viewPhase: "view.phase";
|
|
55
55
|
readonly viewStartedAt: "view.started_at";
|
|
56
56
|
readonly viewUrl: "view.url";
|
|
57
|
-
readonly
|
|
57
|
+
readonly viewUrlTemplate: "view.url_template";
|
|
58
58
|
readonly viewVersion: "view.version";
|
|
59
59
|
readonly websocketPhase: "websocket.phase";
|
|
60
60
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueking/open-telemetry",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "OpenTelemetry browser SDK for BK RUM",
|
|
5
5
|
"author": "TencentCloud Real User Monitoring",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"docs:preview": "vitepress preview wikis",
|
|
24
24
|
"dev": "vite dev",
|
|
25
25
|
"dts": "vue-tsc --project tsconfig.dts.json",
|
|
26
|
-
"test:rum-context": "node --experimental-default-type=module --experimental-strip-types --test tests/action-plugin.test.mjs tests/consent.test.mjs tests/experience-plugins.test.mjs tests/request-model.test.mjs tests/runtime-context.test.mjs tests/sampling.test.mjs tests/session-state.test.ts tests/session-plugin.test.mjs tests/session-page-view.test.mjs tests/session-processors.test.mjs tests/web-vitals.test.mjs"
|
|
26
|
+
"test:rum-context": "node --experimental-default-type=module --experimental-strip-types --test tests/action-plugin.test.mjs tests/consent.test.mjs tests/experience-plugins.test.mjs tests/request-model.test.mjs tests/runtime-context.test.mjs tests/sampling.test.mjs tests/session-state.test.ts tests/session-plugin.test.mjs tests/session-page-view.test.mjs tests/session-processors.test.mjs tests/trace-context.test.mjs tests/web-vitals.test.mjs"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@opentelemetry/api": "^1.9.1",
|
|
@@ -114,6 +114,6 @@ View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`csp
|
|
|
114
114
|
- **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;SDK 不采集 HTTP Body;`user.id` 需 hash 的话要在传入前处理。`tracking.beforeSend` 新写入的字段不会再次自动经过 `redactAttributes`。
|
|
115
115
|
- **Consent**:未授权初始化时配置 `privacy.trackingConsent: 'not-granted'`,用户授权后调用 `setTrackingConsent('granted')`;撤销授权会停止采集并解除 patch。该配置不会阻止构造阶段读取 Device Resource 快照;要求授权前零读取时必须延迟构造 SDK。
|
|
116
116
|
- **单一信号**:只有 `/v1/rum` Trace 通道;计数、直方图、分位数、错误指纹和跨事件聚合由服务端完成。
|
|
117
|
-
-
|
|
117
|
+
- **低基数路由**:`tracking.view.getUrlTemplate` 与 `tracking.request.getUrlTemplate` 分别把页面路由和请求路径归类成 `/user/:id`,避免高基数 URL 污染指标维度。默认已按形状折叠数字 ID、UUID 和长十六进制段。
|
|
118
118
|
- **手动 View 的时机**:使用 `autoStart: false`,先 `await start()` 建立 Session,再调用 `startView()`;启动前调用会因没有有效采样 Session 而被忽略。
|
|
119
119
|
- **Action 命名隐私**:默认 `nameCollection: 'explicit'` 只读取 `data-bk-action-name`,否则退回标签名;只有显式设为 `text` 才读取可访问名称和 DOM 文本。
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"id": 0,
|
|
6
6
|
"name": "vue3-integration",
|
|
7
7
|
"prompt": "我们是一个 Vue3 + vue-router 的后台管理系统,想接入蓝鲸 RUM 做前端监控。collector 地址是 https://rum.example.com,token 放在 window.__RUM_TOKEN__。帮我写接入代码:要能追踪 SPA 路由切换、检测白屏(挂载点 #app),生产环境按 20% 采样,并且把 URL 里的 token 参数脱敏。",
|
|
8
|
-
"expected_output": "给出使用 @blueking/open-telemetry 的 BkOpenTelemetry 接入代码:application/transport(endpoint+token)、session.sampleRate=0.2、tracking.blankScreen.rootSelector='#app'、privacy.redactUrl 脱敏 token、通过 tracking.view.
|
|
8
|
+
"expected_output": "给出使用 @blueking/open-telemetry 的 BkOpenTelemetry 接入代码:application/transport(endpoint+token)、session.sampleRate=0.2、tracking.blankScreen.rootSelector='#app'、privacy.redactUrl 脱敏 token、通过 tracking.view.getUrlTemplate 自动追踪或 manual + await start() + startView() 对接 vue-router。API/配置项名称需与 SDK 实际一致。",
|
|
9
9
|
"files": [],
|
|
10
10
|
"assertions": []
|
|
11
11
|
},
|
|
@@ -108,7 +108,7 @@ SDK 只创建 OpenTelemetry Trace Provider。Session、View、请求、资源、
|
|
|
108
108
|
|
|
109
109
|
- `user.id`
|
|
110
110
|
- `session.id`、`session.start_time`、`session.type`、`session.has_replay`
|
|
111
|
-
- `view.id`、`view.name`、`view.url`、`view.
|
|
111
|
+
- `view.id`、`view.name`、`view.url`、`view.url_template`、`view.loading_type`
|
|
112
112
|
- 活动窗口内的 `action.id`
|
|
113
113
|
- Device 插件产生的视口、屏幕、网络和设备 ID
|
|
114
114
|
- View 自定义属性
|
|
@@ -24,7 +24,7 @@ SDK 只产生原始 RUM Span:
|
|
|
24
24
|
| View / Router | `tracking.view` | auto | Navigation Timing、History、hash、BFCache | `browser.view` | [View 与路由](./views-routing.md) |
|
|
25
25
|
| View Loading Time | `tracking.view.loadingTime` | 开 | 请求/资源/DOM/`window.open` 活动 | `browser.view` update | [View 与路由](./views-routing.md) |
|
|
26
26
|
| Fetch/XHR | `tracking.request` | 开 | fetch、XMLHttpRequest、Resource Timing | `browser.resource` CLIENT | [网络](./network.md) |
|
|
27
|
-
| Trace Header | `allowedTracingUrls` | 无白名单 | W3C Trace Context | 被观测请求的 `traceparent` | [网络](./network.md) |
|
|
27
|
+
| Trace Header | `allowedTracingUrls` | 无白名单 | W3C Trace Context | 被观测请求的 `traceparent` + `browser.resource` Span Link | [网络](./network.md) |
|
|
28
28
|
| 静态资源 | `tracking.resource` | 开 | Resource PerformanceObserver | `browser.resource` CLIENT | [网络](./network.md) |
|
|
29
29
|
| JS Error | `tracking.error` | 开 | window error | `browser.error` | [错误与安全](./errors-security.md) |
|
|
30
30
|
| Promise rejection | `tracking.error` | 开 | unhandledrejection | `browser.unhandledrejection` | [错误与安全](./errors-security.md) |
|
|
@@ -93,7 +93,7 @@ View 类型:
|
|
|
93
93
|
|
|
94
94
|
每个 View 产生 start/update/end 生命周期 Span,`view.version` 递增。Loading Time 等待页面活动安静后更新;隐藏页面会取消当前自动计算,业务可用 `setViewLoadingTime()` 手动确认。
|
|
95
95
|
|
|
96
|
-
自动 mode 不因 query-only 改变创建 View。默认
|
|
96
|
+
自动 mode 不因 query-only 改变创建 View。默认 `view.url_template` 会把数字 ID、UUID 和长十六进制段折叠为 `:id`,但只按形状猜,非数字动态段需要用 `getUrlTemplate` 显式提供。
|
|
97
97
|
|
|
98
98
|
## 网络与资源
|
|
99
99
|
|
|
@@ -101,7 +101,7 @@ Fetch/XHR 插件统一负责:
|
|
|
101
101
|
|
|
102
102
|
- 建 `browser.resource` CLIENT Span;
|
|
103
103
|
- 请求结果和 HTTP status;
|
|
104
|
-
- 可选 W3C `traceparent
|
|
104
|
+
- 可选 W3C `traceparent`:为每个白名单请求生成独立 trace context,并用 Span Link 关联,Link Attributes 记录命中格式与原始 Header;业务已有 trace Header 时不注入;
|
|
105
105
|
- 与 Resource Timing 在最多 200ms 内匹配;
|
|
106
106
|
- 向 View/Action activity 通知开始与结束。
|
|
107
107
|
|
|
@@ -110,7 +110,7 @@ context: {
|
|
|
110
110
|
|
|
111
111
|
Hook 每次调用都应返回新的普通对象,且不能抛异常。SDK 不 hash、不改写 `user.id`。如果 ID 敏感,接入方必须在传入前完成不可逆处理。
|
|
112
112
|
|
|
113
|
-
未配置 `attributes.page` 时默认返回空对象。页面地址由 `view.url` 表达,低基数路由由 `view.
|
|
113
|
+
未配置 `attributes.page` 时默认返回空对象。页面地址由 `view.url` 表达,低基数路由由 `view.url_template` 表达;该 Hook 只用于补充业务自定义的页面维度。
|
|
114
114
|
|
|
115
115
|
属性合并优先级不是全局统一的:各插件会先组合公共字段、Hook 字段和事件字段,`startSpan()` 再用运行时上下文作为底层。精确字段请以对应能力页和[RUM 数据模型](./data-model.md)为准。
|
|
116
116
|
|
|
@@ -161,8 +161,9 @@ tracking: {
|
|
|
161
161
|
| 配置 | 默认 | 说明 |
|
|
162
162
|
| --- | --- | --- |
|
|
163
163
|
| `excludedUrls` | 无 | 匹配后不建请求 Span、不注入 trace header,也不计入 View/Action 活动 |
|
|
164
|
-
| `allowedTracingUrls` | 无 | 只有明确匹配的 URL 才注入 W3C `traceparent
|
|
164
|
+
| `allowedTracingUrls` | 无 | 只有明确匹配的 URL 才注入 W3C `traceparent`,同源也不例外;注入的是独立 trace context,并通过 Span Link 关联回 RUM Span。业务已自行设置 trace Header 时不注入 |
|
|
165
165
|
| `beforeSend` | 无 | 只作用于 Fetch/XHR 请求事件;`event.resource.outcome` 区分 response/abort/timeout/network_error,返回 `false` 丢弃请求 Span |
|
|
166
|
+
| `getUrlTemplate` | 折叠动态段后的 pathname | 生成低基数 `url.template`,例如 `/api/orders/:id`。收到的是未脱敏 URL,返回空值或抛错时回退到默认规则 |
|
|
166
167
|
|
|
167
168
|
URL matcher 支持 string、RegExp 或函数:
|
|
168
169
|
|
|
@@ -179,10 +180,10 @@ URL matcher 支持 string、RegExp 或函数:
|
|
|
179
180
|
| --- | --- | --- | --- |
|
|
180
181
|
| `tracking` | `'auto' \| 'manual'` | `'auto'` | 自动监听 History/hash,或只接受 `startView()` |
|
|
181
182
|
| `loadingTime` | `boolean` | `true` | 自动计算初始加载和路由稳定耗时 |
|
|
182
|
-
| `
|
|
183
|
+
| `getUrlTemplate` | `(url) => string \| undefined` | 折叠动态段后的 pathname | 生成低基数 `view.url_template` |
|
|
183
184
|
| `excludedActivityUrls` | URL matcher | 无 | 不让长轮询/流式/埋点请求延长 View loading time |
|
|
184
185
|
|
|
185
|
-
`
|
|
186
|
+
`getUrlTemplate` 返回 `undefined` 或抛错时回退到默认规则:取 pathname 并把数字 ID、UUID、长十六进制段折叠为 `:id`。它与 `tracking.request.getUrlTemplate` 共用这套默认折叠,但两者是独立入口——页面路由与 API 路径的模板规则通常不同。自动路由不会因 query-only 变化创建新 View;hash 变化会创建,但纯锚点语义由业务自行决定是否改用 manual。详见[View、路由与页面加载](./views-routing.md)。
|
|
186
187
|
|
|
187
188
|
## action
|
|
188
189
|
|
|
@@ -280,7 +281,7 @@ const rum = new BkOpenTelemetry({
|
|
|
280
281
|
session: { sampleRate: 0.2 },
|
|
281
282
|
tracking: {
|
|
282
283
|
view: {
|
|
283
|
-
|
|
284
|
+
getUrlTemplate(url) {
|
|
284
285
|
return new URL(url, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id');
|
|
285
286
|
},
|
|
286
287
|
excludedActivityUrls: [/\/events\/stream(?:\?|$)/],
|
|
@@ -14,7 +14,7 @@ SDK 不绑定 Vue、React 或具体 Router。框架集成主要解决四件事
|
|
|
14
14
|
tracking: {
|
|
15
15
|
view: {
|
|
16
16
|
tracking: 'auto',
|
|
17
|
-
|
|
17
|
+
getUrlTemplate: groupRoute,
|
|
18
18
|
},
|
|
19
19
|
}
|
|
20
20
|
```
|
|
@@ -73,7 +73,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
73
73
|
transport: { endpoint: window.__RUM_ENDPOINT__ },
|
|
74
74
|
tracking: {
|
|
75
75
|
view: {
|
|
76
|
-
|
|
76
|
+
getUrlTemplate(rawUrl) {
|
|
77
77
|
const path = new URL(rawUrl, location.href).pathname;
|
|
78
78
|
return routeGroups.find(item => item.pattern.test(path))?.group ?? path;
|
|
79
79
|
},
|
|
@@ -98,7 +98,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
98
98
|
tracking: {
|
|
99
99
|
view: {
|
|
100
100
|
tracking: 'manual',
|
|
101
|
-
|
|
101
|
+
getUrlTemplate(rawUrl) {
|
|
102
102
|
const path = new URL(rawUrl, location.href).pathname;
|
|
103
103
|
return path.replace(/\/orders\/[^/]+/, '/orders/:id');
|
|
104
104
|
},
|
|
@@ -154,7 +154,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
154
154
|
transport: { endpoint: window.__RUM_ENDPOINT__ },
|
|
155
155
|
tracking: {
|
|
156
156
|
view: {
|
|
157
|
-
|
|
157
|
+
getUrlTemplate(rawUrl) {
|
|
158
158
|
return new URL(rawUrl, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id');
|
|
159
159
|
},
|
|
160
160
|
},
|
|
@@ -196,7 +196,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
196
196
|
tracking: {
|
|
197
197
|
view: {
|
|
198
198
|
tracking: 'manual',
|
|
199
|
-
|
|
199
|
+
getUrlTemplate: rawUrl =>
|
|
200
200
|
new URL(rawUrl, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id'),
|
|
201
201
|
},
|
|
202
202
|
blankScreen: { rootSelector: '#root' },
|
|
@@ -275,10 +275,10 @@ export const router = createBrowserRouter([
|
|
|
275
275
|
|
|
276
276
|
## Hash Router
|
|
277
277
|
|
|
278
|
-
自动模式会观察 hash。默认 URL 清洗会移除 hash,所以 `view.url` 看不到 hash 内容,但 `
|
|
278
|
+
自动模式会观察 hash。默认 URL 清洗会移除 hash,所以 `view.url` 看不到 hash 内容,但 `getUrlTemplate(rawUrl)` 仍可在清洗前解析它:
|
|
279
279
|
|
|
280
280
|
```ts
|
|
281
|
-
|
|
281
|
+
getUrlTemplate(rawUrl) {
|
|
282
282
|
const url = new URL(rawUrl, location.href);
|
|
283
283
|
const hashPath = url.hash.replace(/^#/, '').split('?')[0] || '/';
|
|
284
284
|
return hashPath.replace(/\/orders\/[^/]+/, '/orders/:id');
|
|
@@ -111,12 +111,12 @@ session: {
|
|
|
111
111
|
|
|
112
112
|
## 6. 治理动态路由
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
默认规则会把 pathname 里的数字 ID、UUID 和长十六进制段折叠为 `:id`,因此 `/orders/1001` 与 `/orders/1002` 会归到同一个 `/orders/:id`。代价是纯数字段无法与语义段区分,`/reports/2024/summary` 也会变成 `/reports/:id/summary`。需要精确模板时自行覆盖:
|
|
115
115
|
|
|
116
116
|
```ts
|
|
117
117
|
tracking: {
|
|
118
118
|
view: {
|
|
119
|
-
|
|
119
|
+
getUrlTemplate(rawUrl) {
|
|
120
120
|
const path = new URL(rawUrl, location.href).pathname;
|
|
121
121
|
return path
|
|
122
122
|
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
@@ -20,12 +20,13 @@ SDK 不采集任何请求 Body、响应 Body、WebSocket 消息内容、消息
|
|
|
20
20
|
|
|
21
21
|
1. 把 URL 转成绝对 URL。
|
|
22
22
|
2. 排除 SDK 自身上报和 `excludedUrls`。
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
26
|
-
6.
|
|
27
|
-
7.
|
|
28
|
-
8.
|
|
23
|
+
3. 按白名单探测既有 Trace Header,规划本次请求的 trace context。
|
|
24
|
+
4. 创建 `browser.resource` CLIENT Span,并把关联后端 Trace 的 Span Link 一并写入。
|
|
25
|
+
5. 需要时注入 `traceparent`。
|
|
26
|
+
6. 把请求开始/结束通知给 View/Action 页面活动。
|
|
27
|
+
7. 根据 Response 或终止原因生成结构化 outcome,并补充结果、异常和 Resource Timing。
|
|
28
|
+
8. 执行请求级 `beforeSend`。
|
|
29
|
+
9. 结束 Span,并进入全局过滤链路。
|
|
29
30
|
|
|
30
31
|
Patch 在插件 shutdown 时仅在全局方法仍是 SDK 安装版本的情况下恢复,避免覆盖 SDK 之后由业务安装的其他 Patch。
|
|
31
32
|
|
|
@@ -38,9 +39,14 @@ Fetch 和 XHR 都生成 `browser.resource`:
|
|
|
38
39
|
| `resource.type` | `fetch` | `xhr` |
|
|
39
40
|
| `http.request.method` | `init.method`、Request method 或 `GET`,转大写 | `open()` method,转大写 |
|
|
40
41
|
| `url.full` | 绝对 URL,经脱敏 | 同左 |
|
|
42
|
+
| `url.template` | 低基数路由模板,只含 path | 同左 |
|
|
41
43
|
| `http.response.status_code` | 获得真实 Response status 时 | `load` 且 `xhr.status>0` 时 |
|
|
42
44
|
| Span Kind | CLIENT | CLIENT |
|
|
43
45
|
|
|
46
|
+
`url.template` 是给后端按 API 路由聚合用的低基数维度(semconv `url.template`,当前仍是 Development 阶段)。默认取 pathname 并把数字 ID、UUID、长十六进制段折叠为 `:id`,`/api/orders/1001` 与 `/api/orders/1002` 都归到 `/api/orders/:id`。两点已知代价:纯数字段无法与语义段区分,`/reports/2024/summary` 会变成 `/reports/:id/summary`;模板按 semconv 定义不含 host,跨域同路径会聚到一起,需要区分来源时配合 `server.address`。需要精确模板时用 `tracking.request.getUrlTemplate` 覆盖,它拿到的是未脱敏 URL(便于按 query 判断路由),返回空值或抛错都回退到默认规则。
|
|
47
|
+
|
|
48
|
+
这套折叠规则与 View 的 `view.url_template` 共用,但入口独立:页面路由和 API 路径的模板规则通常不同,所以 `tracking.view.getUrlTemplate` 与 `tracking.request.getUrlTemplate` 互不影响。
|
|
49
|
+
|
|
44
50
|
Span 开始时间使用请求开始时间,结束时间优先使用匹配到的 `PerformanceResourceTiming.responseEnd`;没有匹配时使用 Fetch resolve/reject 或 XHR `load/abort/timeout/error` 的完成时间。`http.response.status_code` 只表示真实 HTTP Response,不会上报 XHR 的本地占位值 `0`。
|
|
45
51
|
|
|
46
52
|
## Outcome 与 Status
|
|
@@ -82,7 +88,7 @@ Matcher 规则:
|
|
|
82
88
|
|
|
83
89
|
## W3C Trace Context
|
|
84
90
|
|
|
85
|
-
默认不向任何请求注入 Trace Header,包括同源请求。只有 `allowedTracingUrls`
|
|
91
|
+
默认不向任何请求注入 Trace Header,包括同源请求。只有 `allowedTracingUrls` 显式命中时才注入:
|
|
86
92
|
|
|
87
93
|
```ts
|
|
88
94
|
tracking: {
|
|
@@ -94,9 +100,11 @@ tracking: {
|
|
|
94
100
|
}
|
|
95
101
|
```
|
|
96
102
|
|
|
97
|
-
|
|
103
|
+
白名单应使用 URL-aware 函数或有边界的正则,不要用过宽字符串。
|
|
98
104
|
|
|
99
|
-
|
|
105
|
+
### 每个请求一条独立后端 Trace
|
|
106
|
+
|
|
107
|
+
注入的 `traceparent` **不复用** RUM Span 自身的 trace context,而是为每个命中白名单的请求生成一对全新的 trace-id / span-id:
|
|
100
108
|
|
|
101
109
|
```text
|
|
102
110
|
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
@@ -104,22 +112,62 @@ traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
|
104
112
|
└ version=00 parent-id:16 位 ─────┘ sampled=01
|
|
105
113
|
```
|
|
106
114
|
|
|
107
|
-
|
|
115
|
+
这样后端按 trace-id 检索时,一条 Trace 只对应一个 API 请求,也不会把前端的 `browser.resource` Span 混进后端链路。前后端的关联改由 **Span Link** 承担,后端可按 `link.trace_id` 反查对应的 RUM Span。
|
|
116
|
+
|
|
117
|
+
每个命中白名单的请求恒定产出**一条** Link,结构固定为 trace context 加上记录来源的 `attributes`:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"links": [
|
|
122
|
+
{
|
|
123
|
+
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
|
|
124
|
+
"span_id": "00f067aa0ba902b7",
|
|
125
|
+
"attributes": {
|
|
126
|
+
"format": "traceparent",
|
|
127
|
+
"injected": true,
|
|
128
|
+
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`attributes.format` 是命中的传播格式,`attributes.injected` 标记这条 trace context 是否由 SDK 生成——业务自带合法 `traceparent` 时 `format` 与 SDK 注入同值,只能靠 `injected` 区分。其余键是该格式的**原始 Header 名与原始取值**(不做补零或进制转换),例如 Datadog 会带上 `x-datadog-trace-id`、`x-datadog-parent-id`、`x-datadog-sampling-priority` 等。
|
|
136
|
+
|
|
137
|
+
`tracestate` 不做记录:它在本链路上没有消费者(SDK 从不注入 `tracestate`,后端只解析 `traceparent`),而 W3C 允许 32 个成员、每成员 256 字符,最坏情况下会给每个被追踪请求平白增加数 KB 负载。这些 Link Attributes 也不经过 `privacy.redactAttributes` 脱敏。
|
|
138
|
+
|
|
139
|
+
请求 Patch 只在当前 Session 已采样时创建 Span 并注入,因此发出的 flags 恒为 `01`。注入的 span-id 在前端没有对应的已上报 Span,后端 Trace 的根 Span 会以它作为 `parent_span_id`。
|
|
140
|
+
|
|
141
|
+
### 业务已有 Trace Header 时不注入
|
|
142
|
+
|
|
143
|
+
注入前 SDK 会先读取本次请求最终会发出的 Header,按下列优先级探测业务是否已经自行传播链路:
|
|
144
|
+
|
|
145
|
+
| 优先级 | `format` | Header | 能否解析出合法 OTel id |
|
|
146
|
+
| --- | --- | --- | --- |
|
|
147
|
+
| 1 | `traceparent` | `traceparent` | 能 |
|
|
148
|
+
| 2 | `sentry-trace` | `sentry-trace` | 能 |
|
|
149
|
+
| 3 | `b3` | `b3`(单头) | 能,64 位 trace-id 左侧补零到 128 位 |
|
|
150
|
+
| 4 | `b3-multi` | `x-b3-traceid` / `x-b3-spanid` / `x-b3-parentspanid` / `x-b3-sampled` / `x-b3-flags` | 同上 |
|
|
151
|
+
| 5 | `datadog` | `x-datadog-trace-id` / `x-datadog-parent-id` / `x-datadog-sampling-priority` / `x-datadog-origin` / `x-datadog-tags` | 能,十进制换算为 hex,128 位时从 `x-datadog-tags` 的 `_dd.p.tid` 拼接高位 |
|
|
152
|
+
| 6 | `sw8` | `sw8` | **不能**,SkyWalking 的 trace-id 不是 16 字节 hex |
|
|
153
|
+
|
|
154
|
+
一旦探测到上表任一 Header,SDK **完全不注入**,Link Attributes 里 `injected` 为 `false`,并写入命中格式的原始 Header。只记录命中格式自己的 Header——若 `traceparent` 与 `b3` 同时存在,按优先级只记录前者。
|
|
108
155
|
|
|
109
|
-
|
|
156
|
+
几点需要注意:
|
|
110
157
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
158
|
+
- `traceparent` 与 SDK 注入的是同一个 Header,因此**格式非法时视作没有既有链路并覆盖注入**——这种值后端同样无法接续。其余格式只要 Header 存在就一律尊重。
|
|
159
|
+
- 解析不出合法 id 时(`sw8`、或 `b3: 0` 这类只有采样标记的值),SDK 会补一对随机 id 让 Link 结构保持统一,但**不会注入**。这对占位 id 在后端不存在对应 Trace,只有 `attributes` 里的原始 Header 有排查价值。
|
|
160
|
+
- 后端只解析 W3C `traceparent`。如果业务发的是 `b3` / `sw8` / Datadog 这类格式,SDK 不注入意味着后端不会生成 Trace,Link 中的 trace-id 在后端查不到。
|
|
161
|
+
- Fetch 读取的是 `init.headers`,缺省时回退到输入 `Request` 的 Headers;XHR 因为浏览器不提供读取请求头的 API,SDK 会额外 Patch `setRequestHeader()` 做快照,这层 Patch 仅在配置了 `allowedTracingUrls` 时安装,`open()` 时快照同步失效。
|
|
114
162
|
|
|
115
163
|
跨域注入会触发 CORS 预检,服务端至少需要允许:
|
|
116
164
|
|
|
117
165
|
```http
|
|
118
166
|
Access-Control-Allow-Origin: https://your-web.example.com
|
|
119
|
-
Access-Control-Allow-Headers: traceparent
|
|
167
|
+
Access-Control-Allow-Headers: traceparent
|
|
120
168
|
```
|
|
121
169
|
|
|
122
|
-
|
|
170
|
+
如业务还有自定义 Header 或自有的 trace Header,应一并加入允许列表。
|
|
123
171
|
|
|
124
172
|
## 请求级 beforeSend
|
|
125
173
|
|
|
@@ -85,24 +85,26 @@ privacy: {
|
|
|
85
85
|
|
|
86
86
|
SDK 在写入 View、Request、Resource、错误资源、CSP source、Long Task source、referrer 等 URL 字段时调用该 Hook。自定义插件直接写入名为 URL 的任意属性不会被自动识别,插件必须显式调用 `context.config.hooks.redactUrl()`。
|
|
87
87
|
|
|
88
|
-
##
|
|
88
|
+
## 路由模板不是 URL 脱敏
|
|
89
89
|
|
|
90
90
|
```ts
|
|
91
91
|
tracking: {
|
|
92
92
|
view: {
|
|
93
|
-
|
|
93
|
+
getUrlTemplate(url) {
|
|
94
94
|
return new URL(url, location.href).pathname.replace(/\/orders\/[^/]+/, '/orders/:id');
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
`
|
|
100
|
+
`getUrlTemplate` 只生成低基数 `view.url_template`,不会改写 `view.url`。要保护原 URL,仍需 `privacy.redactUrl`。建议两者使用相同的动态段规则,但用途不同:
|
|
101
101
|
|
|
102
102
|
- `redactUrl`:隐私和敏感数据边界;
|
|
103
|
-
- `
|
|
103
|
+
- `getUrlTemplate`:聚合维度和查询基数。
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
请求侧的 `tracking.request.getUrlTemplate` 同理,只生成 `url.template`,不影响 `url.full` 的脱敏。注意它收到的是**未脱敏**的请求 URL,因此自定义实现不要把 query 里的原值拼进返回的模板。
|
|
106
|
+
|
|
107
|
+
未配置 `context.attributes.page` 时默认返回空对象,不存在独立的默认页面属性路径。页面地址统一由经过 `redactUrl` 的 `view.url` 表达,聚合维度使用 `view.url_template`;业务通过该 Hook 添加的属性仍需自行确保不包含敏感信息。
|
|
106
108
|
|
|
107
109
|
## 属性脱敏
|
|
108
110
|
|
|
@@ -267,7 +269,7 @@ SDK 不实现以下能力:
|
|
|
267
269
|
## 上线评审清单
|
|
268
270
|
|
|
269
271
|
1. `redactUrl` 覆盖 path 中的动态 ID,且仍删除 query/fragment/认证信息;
|
|
270
|
-
2. `view.
|
|
272
|
+
2. `view.url_template` 是低基数模板;
|
|
271
273
|
3. `user.id` 已按公司规范处理;
|
|
272
274
|
4. Action 未开启不必要的文本采集;
|
|
273
275
|
5. CSP、错误 stack、自定义字段经过字段评审;
|
|
@@ -26,7 +26,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
26
26
|
},
|
|
27
27
|
tracking: {
|
|
28
28
|
view: {
|
|
29
|
-
|
|
29
|
+
getUrlTemplate(rawUrl) {
|
|
30
30
|
return new URL(rawUrl, location.href).pathname
|
|
31
31
|
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
32
32
|
.replace(/\/users\/[^/]+/g, '/users/:id');
|
|
@@ -97,7 +97,7 @@ Session 采样率控制整体数据量。粗略估算:
|
|
|
97
97
|
|
|
98
98
|
必须排查:
|
|
99
99
|
|
|
100
|
-
- `view.
|
|
100
|
+
- `view.url_template` 是否含订单 ID、用户 ID、UUID;
|
|
101
101
|
- custom/action name 是否拼业务 ID;
|
|
102
102
|
- 自定义属性是否包含时间戳、随机值、整条 URL;
|
|
103
103
|
- error message 是否因为动态值导致无限分组。
|
|
@@ -159,6 +159,8 @@ allowedTracingUrls: [
|
|
|
159
159
|
|
|
160
160
|
不要使用宽泛 `/./` 或所有 URL,避免向第三方发送 Trace ID,也避免触发额外预检。API 端必须允许 `traceparent` header,并正确接续 W3C Trace Context。
|
|
161
161
|
|
|
162
|
+
每个命中白名单的请求都会生成一条独立的后端 Trace,因此后端 Trace 数量约等于被注入的请求数。评估后端存储与采样容量时按这个量级估算,必要时在服务端做二次采样。
|
|
163
|
+
|
|
162
164
|
## 7. 排除长活动与噪声
|
|
163
165
|
|
|
164
166
|
两类配置语义不同:
|
|
@@ -218,7 +220,7 @@ SDK 设计为:
|
|
|
218
220
|
- exporter 失败不会让业务 Fetch/XHR 失败;
|
|
219
221
|
- unsupported Performance API 时跳过对应能力。
|
|
220
222
|
|
|
221
|
-
但自定义 Hook/插件仍是业务代码:必须快速、同步、无副作用,不应发网络请求或抛异常。上线前对 `redactUrl`、`redactAttributes`、`
|
|
223
|
+
但自定义 Hook/插件仍是业务代码:必须快速、同步、无副作用,不应发网络请求或抛异常。上线前对 `redactUrl`、`redactAttributes`、`getUrlTemplate`、两个 `beforeSend` 做异常与性能测试。
|
|
222
224
|
|
|
223
225
|
## 12. 灰度验收
|
|
224
226
|
|
|
@@ -171,7 +171,7 @@ context: {
|
|
|
171
171
|
}
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
未配置时默认返回空对象。页面地址使用 `view.url`,低基数路由使用 `view.
|
|
174
|
+
未配置时默认返回空对象。页面地址使用 `view.url`,低基数路由使用 `view.url_template`;业务需要额外页面维度时可自行返回。
|
|
175
175
|
|
|
176
176
|
Hook 每次执行,应保持低成本且不要抛错。它可能包含高基数字段,但服务端聚合维度应只选择稳定、低基数属性。
|
|
177
177
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
| 领域属性 | `resource.*`、`error.*`、`vital.*`、`long_task.*` 等 | 具体发生了什么,耗时、来源和诊断细节是什么? |
|
|
17
17
|
| OTLP Envelope 与 Event | `traceId`、`spanId`、时间戳、`status`、`events` | 如何定位单条记录、关联调用链和读取异常/脚本归因? |
|
|
18
18
|
|
|
19
|
-
推荐先用 Resource 字段限定应用和环境,再以 `span_type` 选择信号类型,最后使用领域字段细分。Session/View 聚合优先使用 `session.id`、`view.id`;路由聚合优先使用低基数的 `view.
|
|
19
|
+
推荐先用 Resource 字段限定应用和环境,再以 `span_type` 选择信号类型,最后使用领域字段细分。Session/View 聚合优先使用 `session.id`、`view.id`;路由聚合优先使用低基数的 `view.url_template`,不要直接按完整 URL 或原始 path 建立高基数索引。
|
|
20
20
|
|
|
21
21
|
## 阅读约定
|
|
22
22
|
|
|
@@ -50,9 +50,10 @@
|
|
|
50
50
|
|
|
51
51
|
| OTLP 字段 | 类型/格式 | 条件 | 详细说明 |
|
|
52
52
|
| ------------------- | ------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
53
|
-
| `traceId` | 32 位十六进制字符串 | 必有 | 16 字节 Trace ID。同一条调用链上的 Span
|
|
53
|
+
| `traceId` | 32 位十六进制字符串 | 必有 | 16 字节 Trace ID。同一条调用链上的 Span 使用同一个值。注意注入到后端的 `traceparent` 使用的是另一个独立 trace-id,不等于本字段,两者通过 `links` 关联。 |
|
|
54
54
|
| `spanId` | 16 位十六进制字符串 | 必有 | 当前 Span 的 8 字节唯一 ID,与 `traceId` 一起唯一定位本次 Span。 |
|
|
55
55
|
| `parentSpanId` | 16 位十六进制字符串 | 有活动父 Span 时 | 父 Span ID。没有活动父上下文的 RUM 根 Span不包含该字段;缺失不代表数据异常。 |
|
|
56
|
+
| `links` | link[] | 注入或探测到 Trace Header 时 | 关联的其他 Trace。`browser.resource` Span 用它指向本次请求对应的后端 Trace,每项含 `traceId`、`spanId`、`traceFlags`。后端可按 `link.trace_id` 反查 RUM Span。 |
|
|
56
57
|
| `name` | string | 必有 | Span 名称,例如 `browser.view`、`browser.resource`。稳定一级分类使用 `span_type`,具体类别使用各领域字段查询。 |
|
|
57
58
|
| `kind` | enum number/string | 必有 | OpenTelemetry Span Kind。SDK 内置值为 `INTERNAL` 或 `CLIENT`;不同 OTLP JSON 实现可能编码为枚举数字或名称。 |
|
|
58
59
|
| `startTimeUnixNano` | epoch ns 字符串 | 必有 | Span 开始时间。OTLP JSON 使用十进制字符串保存纳秒整数,避免 JavaScript Number 精度丢失。 |
|
|
@@ -94,9 +95,9 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
|
|
|
94
95
|
| `session.type` | string | Session 有效 | 当前固定为 `user`,为未来区分其他 Session 类型保留。 |
|
|
95
96
|
| `session.has_replay` | boolean | Session 有效 | 当前固定为 `false`,表示 SDK 没有随该 Session 上报 Session Replay 数据。 |
|
|
96
97
|
| `view.id` | string | View 有效 | 当前页面视图的关联 ID。首次加载、有效 SPA 路由变化、BFCache 恢复或 Session 续建都会创建新 View。 |
|
|
97
|
-
| `view.name` | string | View 有效 | View
|
|
98
|
+
| `view.name` | string | View 有效 | View 的可读名称。默认取路由模板,也可由 `startView` 或 `setViewName` 设置,适合展示和聚合。 |
|
|
98
99
|
| `view.url` | string | View 有效 | 创建 View 时的完整 URL,经 `redactUrl` 脱敏。与当前实时 `location.href` 不一定相同。 |
|
|
99
|
-
| `view.
|
|
100
|
+
| `view.url_template` | string | View 有效 | 低基数路由模板。默认把数字 ID、UUID 和长十六进制路径段归一为 `:id`,也可由 `getUrlTemplate` 自定义。 |
|
|
100
101
|
| `view.loading_type` | string | View 有效 | View 创建类型:`initial_load` 首次文档加载、`route_change` SPA 路由、`bf_cache` BFCache 恢复、`session_renewal` Session 到期后续建。 |
|
|
101
102
|
| `action.id` | string[] | 自动 Action 活动中 | 与当前 Span 同时相关的自动 Action ID 数组;允许多个点击 Action 生命周期重叠。注意 Action Span 自身的同名字段是单个 string。 |
|
|
102
103
|
| `device.id` | string | Device 插件开启 | SDK 生成的匿名设备关联 ID。默认仅在本次插件生命周期内稳定;`persistentId: true` 时写入 localStorage,从而跨页面和 Session 保持。 |
|
|
@@ -108,7 +109,7 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
|
|
|
108
109
|
| `network.effective_type` | string | Network Information API 支持 | 浏览器估算的有效网络类型,常见为 `slow-2g`、`2g`、`3g`、`4g`。它反映体验模型,不等同于真实无线制式。 |
|
|
109
110
|
| `network.connection.type` | string | 浏览器提供 `connection.type` 时 | 浏览器返回的原始连接类型,例如 `wifi`、`cellular`、`ethernet`;多数 Safari/Firefox 环境可能缺失。 |
|
|
110
111
|
|
|
111
|
-
默认 `context.attributes.page()` 返回空对象,不附加独立页面属性。页面地址使用 View 创建时冻结并经过 `redactUrl` 的 `view.url`,低基数路由聚合使用 `view.
|
|
112
|
+
默认 `context.attributes.page()` 返回空对象,不附加独立页面属性。页面地址使用 View 创建时冻结并经过 `redactUrl` 的 `view.url`,低基数路由聚合使用 `view.url_template`;业务需要额外页面维度时可自定义该 Hook。
|
|
112
113
|
|
|
113
114
|
## RUM 公共分类字段
|
|
114
115
|
|
|
@@ -165,9 +166,9 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
|
|
|
165
166
|
| `view.id` | string | 所有阶段 | View 关联 ID。同一 View 的 start/update/end 使用相同值,可与该 View 内其他 Span 关联。 |
|
|
166
167
|
| `view.version` | number | 从 1 递增 | 每次 `emitViewEvent` 递增;用于恢复同一 View 生命周期快照的先后顺序。 |
|
|
167
168
|
| `view.started_at` | number | epoch ms | View 开始时间。初始 View 使用 `performance.timeOrigin`,路由/BFCache/续建 View 使用创建时刻。 |
|
|
168
|
-
| `view.name` | string | 所有阶段 | 默认取 `view.
|
|
169
|
+
| `view.name` | string | 所有阶段 | 默认取 `view.url_template`,也可由 `startView({ name })` 或 `setViewName` 设置。 |
|
|
169
170
|
| `view.url` | string | 所有阶段 | 创建 View 时的 URL,经 `redactUrl` 脱敏;在该 View 生命周期内保持不变。 |
|
|
170
|
-
| `view.
|
|
171
|
+
| `view.url_template` | string | 所有阶段 | 低基数路由模板。数字 ID、UUID、长十六进制段默认折叠为 `:id`,用于稳定聚合动态路由。 |
|
|
171
172
|
| `view.loading_type` | string | 所有阶段 | `initial_load`、`route_change`、`bf_cache` 或 `session_renewal`,含义见运行时公共属性。 |
|
|
172
173
|
| `view.loading_time` | number | 计算完成后,ms | 从 `view.started_at` 到页面活动稳定的耗时。初始加载同时等待 load event 和页面活动,以较晚者为准;可由 `setViewLoadingTime()` 手动结束。 |
|
|
173
174
|
| `view.loading_time_source` | string | 有 `view.loading_time` 时 | `auto` 表示 SDK 自动观察页面活动;`manual` 表示业务调用 `setViewLoadingTime()`。 |
|
|
@@ -189,7 +190,8 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
|
|
|
189
190
|
| 字段 | 类型 | 条件/单位 | 来源与详细说明 |
|
|
190
191
|
| --------------------------------- | ------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
191
192
|
| `url.full` | string | 有有效请求/资源 URL | 绝对 URL,经 `redactUrl` 脱敏。用于定位请求目标;不要假设 query 中仍保留原始参数。 |
|
|
192
|
-
| `
|
|
193
|
+
| `url.template` | string | Fetch/XHR | 低基数路由模板,只含 path,例如 `/api/orders/:id`。默认把数字 ID、UUID、长十六进制段折叠为 `:id`,可由 `tracking.request.getUrlTemplate` 覆盖。按 API 路由聚合请求时用它,不要用 `url.full`。静态资源 Span 没有该字段。 |
|
|
194
|
+
| `server.address` | string | URL 可解析 | URL 的 `hostname`,不含端口。相对 URL 会基于当前页面地址解析。模板不含 host,跨域同路径会聚到一起,需要区分来源时配合该字段。 |
|
|
193
195
|
| `server.port` | number | URL 显式包含端口 | URL 的显式端口号。使用协议默认端口且 URL 未写端口时缺失。 |
|
|
194
196
|
| `resource.type` | string | 必有 | Fetch/XHR 为 `fetch`/`xhr`;静态资源使用 `PerformanceResourceTiming.initiatorType`,为空时为 `other`,常见还有 `script`、`link`、`img`、`css`。 |
|
|
195
197
|
| `http.request.method` | string | Fetch/XHR | 归一为大写的 HTTP 方法,例如 `GET`、`POST`。静态资源通常没有可用的请求方法,因此缺失。 |
|
|
@@ -203,6 +205,18 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
|
|
|
203
205
|
| `resource.decoded_body_size` | number | 有 Resource Timing | 解码/解压后的响应体大小,单位 bytes,可与 encoded size 对比压缩收益。 |
|
|
204
206
|
| `resource.transfer_size` | number | 有 Resource Timing | `transferSize`,本次网络实际传输字节数(含响应头);受缓存和 Timing-Allow-Origin 影响可能为 `0`,可与 body size 对比判断是否命中缓存。 |
|
|
205
207
|
|
|
208
|
+
命中 `allowedTracingUrls` 的请求还会带一条 Span Link,用于关联后端 Trace。Trace 来源不记在 Span Attributes 上,而是记在 Link Attributes 上:
|
|
209
|
+
|
|
210
|
+
| 字段 | 类型 | 条件 | 说明 |
|
|
211
|
+
| ----------- | ------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
212
|
+
| `format` | string | 恒有 | 命中的传播格式,取值为 `traceparent`、`sentry-trace`、`b3`、`b3-multi`、`datadog`、`sw8`。 |
|
|
213
|
+
| `injected` | boolean | 恒有 | 这条 trace context 是否由 SDK 生成并注入。`true` 表示请求原本没有任何 trace Header;`false` 表示业务已自行传播,SDK 未注入。业务自带合法 `traceparent` 时 `format` 与 SDK 注入同值,只能靠该字段区分。 |
|
|
214
|
+
| Header 原名 | string | 该 Header 存在 | 命中格式的原始 Header 名与原始取值,未做补零或进制转换,例如 `traceparent`、`b3`、`x-datadog-trace-id`、`sw8`。仅记录命中格式自己的 Header。 |
|
|
215
|
+
|
|
216
|
+
Link 的 `trace_id` / `span_id` 优先取自解析结果;`sw8` 这类无法映射为合法 OTel id 的格式会补一对随机占位 id,此时后端不存在对应 Trace。
|
|
217
|
+
|
|
218
|
+
两点数据口径需要注意:Link Attributes 不经过 `privacy.redactAttributes` 脱敏;`tracestate` 不做记录,它在本链路上没有消费者,且体积最坏可达数 KB。
|
|
219
|
+
|
|
206
220
|
网络阶段字段均为 number、单位 ms。每个 `*.start` 相对该 Resource Entry 的 `startTime`,每个 `*.duration` 为对应阶段结束值减开始值:
|
|
207
221
|
|
|
208
222
|
| 字段 | 条件 | 计算口径与使用方式 |
|
|
@@ -62,7 +62,7 @@ https://rum.example.com/collector/v1/rum
|
|
|
62
62
|
{ "key": "view.id", "value": { "stringValue": "view-01" } },
|
|
63
63
|
{ "key": "view.name", "value": { "stringValue": "/orders/:id" } },
|
|
64
64
|
{ "key": "view.url", "value": { "stringValue": "https://app.example.com/orders/123" } },
|
|
65
|
-
{ "key": "view.
|
|
65
|
+
{ "key": "view.url_template", "value": { "stringValue": "/orders/:id" } },
|
|
66
66
|
{ "key": "view.loading_type", "value": { "stringValue": "initial_load" } },
|
|
67
67
|
{ "key": "span_type", "value": { "stringValue": "resource" } },
|
|
68
68
|
{ "key": "outcome.type", "value": { "stringValue": "success" } },
|
|
@@ -277,6 +277,16 @@ tracking: {
|
|
|
277
277
|
|
|
278
278
|
跨域还需要服务端 CORS 允许请求头 `traceparent`。如果预检失败,缩小白名单并修复 API 服务的 CORS;不要把所有第三方 URL 加入白名单。
|
|
279
279
|
|
|
280
|
+
命中白名单却依然没有注入时,看 Span Link 的 `attributes.injected`。为 `false` 说明业务已经自行设置了 trace Header,SDK 尊重既有链路而不注入,此时 `attributes.format` 告诉你是哪种格式,同组的原始 Header 也一并记在 Link Attributes 里。注意不能只看 `format`:业务自带合法 `traceparent` 时它同样是 `traceparent`,与 SDK 注入无法区分。
|
|
281
|
+
|
|
282
|
+
## 后端按 `traceparent` 的 trace-id 查不到 RUM Span
|
|
283
|
+
|
|
284
|
+
注入的 trace-id 与 RUM Span 自身的 `traceId` **不是同一个值**,两者通过 Span Link 关联。后端应按 `browser.resource` Span 的 `link.trace_id` 反查,而不是直接用 `traceId` 匹配。
|
|
285
|
+
|
|
286
|
+
如果 Link 的 `attributes.injected` 为 `false` 且 `attributes.format` 不是 `traceparent`,说明业务用的是 `b3` / `sw8` / Datadog 等格式。后端只解析 W3C `traceparent`,这种情况下后端不会生成 Trace,Link 里的 trace-id 自然查不到。
|
|
287
|
+
|
|
288
|
+
`sw8` 以及 `b3: 0` 这类只有采样标记的值,SDK 解析不出合法 OTel id,会补一对**随机占位 id** 让 Link 结构保持统一。这对 id 在后端一定查不到,判断依据仍是 `attributes.format` 与其中的原始 Header。
|
|
289
|
+
|
|
280
290
|
## 请求 Span 太多或 View loading 一直不结束
|
|
281
291
|
|
|
282
292
|
使用两个不同的排除入口:
|
|
@@ -397,7 +407,7 @@ tracking: {
|
|
|
397
407
|
- pathname 或非纯锚点 hash 变化会触发;
|
|
398
408
|
- Router 同时手动 `startView()` 且使用 auto 会重复;
|
|
399
409
|
- 微前端多个实例会重复;
|
|
400
|
-
-
|
|
410
|
+
- 默认模板只按形状折叠数字 ID、UUID 和长十六进制段,识别不了 `/orders/abc-slug` 这类非数字动态段,需要用 `getUrlTemplate` 显式提供;
|
|
401
411
|
- `setViewName()` 是改名,不创建新 View;
|
|
402
412
|
- Session 续期和 BFCache 恢复会创建具有特定 loading type 的 View。
|
|
403
413
|
|
|
@@ -13,7 +13,7 @@ View 表示一次可独立分析的页面体验。初始文档加载、SPA 路
|
|
|
13
13
|
| `bf_cache` | 从 Back/Forward Cache 恢复 | `view` |
|
|
14
14
|
| `session_renewal` | Session 过期后新 Session 接管当前页面 | `view` |
|
|
15
15
|
|
|
16
|
-
每个 View 都生成新的 `view.id`。View 名称、URL
|
|
16
|
+
每个 View 都生成新的 `view.id`。View 名称、URL、路由模板和自定义属性作为运行时上下文挂到其间发生的普通 Span。
|
|
17
17
|
|
|
18
18
|
## 自动路由模式
|
|
19
19
|
|
|
@@ -52,14 +52,14 @@ bkOT.startView({
|
|
|
52
52
|
|
|
53
53
|
`attributes` 会经过 `redactAttributes`,并删除 SDK 所有保留字段;业务无法通过 View attributes 覆盖 `session.*`、`view.*`、`span_type` 或 `outcome.*`。
|
|
54
54
|
|
|
55
|
-
## View
|
|
55
|
+
## View 名称和路由模板
|
|
56
56
|
|
|
57
|
-
默认 `view.
|
|
57
|
+
默认 `view.url_template` 取 URL pathname 并把数字 ID、UUID、长十六进制段折叠为 `:id`,`view.name` 默认等于该分组。请求 Span 的 `url.template` 复用同一套折叠规则,但走独立的 `tracking.request.getUrlTemplate`。
|
|
58
58
|
|
|
59
59
|
```ts
|
|
60
60
|
tracking: {
|
|
61
61
|
view: {
|
|
62
|
-
|
|
62
|
+
getUrlTemplate(url) {
|
|
63
63
|
return new URL(url, location.href).pathname
|
|
64
64
|
.replace(/\/orders\/[^/]+/, '/orders/:id')
|
|
65
65
|
.replace(/\/users\/[^/]+/, '/users/:id');
|
|
@@ -68,7 +68,7 @@ tracking: {
|
|
|
68
68
|
}
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
`
|
|
71
|
+
`getUrlTemplate()` 应返回低基数、稳定的路由模板。默认实现已经会把数字 ID、UUID 和长十六进制段替换为 `:id`,但它只能按形状猜:纯数字段无法与语义段区分,`/reports/2024/summary` 会被折成 `/reports/:id/summary`。路由规则明确的应用应显式提供模板,不要依赖猜测。
|
|
72
72
|
|
|
73
73
|
运行期可修改名称:
|
|
74
74
|
|
|
@@ -81,7 +81,7 @@ bkOT.setViewName('订单详情-只读');
|
|
|
81
81
|
## URL 与前序页面
|
|
82
82
|
|
|
83
83
|
- `view.url`:当前 URL,经 `privacy.redactUrl`。
|
|
84
|
-
- `view.
|
|
84
|
+
- `view.url_template`:聚合路由模板。
|
|
85
85
|
- `url.previous`:前一个原始 URL 经脱敏;初始加载为空字符串。
|
|
86
86
|
- `document.referrer`:仅初始自动加载写入并脱敏。
|
|
87
87
|
|