@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.
- package/README.md +67 -57
- package/dist/bk-rum.global.js +2 -2
- package/dist/bk-rum.global.js.map +1 -1
- package/dist/core/action-activity.d.ts +5 -1
- package/dist/core/action-target.d.ts +19 -0
- package/dist/core/config.d.ts +15 -5
- package/dist/core/event-time.d.ts +7 -0
- package/dist/core/performance-timing.d.ts +13 -0
- package/dist/core/plugin.d.ts +37 -2
- package/dist/core/processor.d.ts +24 -2
- package/dist/core/request-timing.d.ts +3 -2
- package/dist/core/runtime-context.d.ts +62 -2
- package/dist/core/sdk.d.ts +23 -1
- package/dist/core/session-transition.d.ts +19 -0
- package/dist/core/trace-context.d.ts +6 -7
- package/dist/core/view-location.d.ts +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2955 -1483
- package/dist/index.js.map +1 -1
- package/dist/integrations/vue-router.d.ts +25 -0
- package/dist/plugins/action.d.ts +1 -1
- package/dist/plugins/blank-screen-detection.d.ts +11 -0
- package/dist/plugins/blank-screen.d.ts +10 -18
- package/dist/plugins/common.d.ts +4 -2
- package/dist/plugins/document-vitals.d.ts +25 -0
- package/dist/plugins/page-view.d.ts +1 -1
- package/dist/plugins/resource.d.ts +14 -1
- package/dist/plugins/session-state.d.ts +14 -2
- package/dist/plugins/session-store.d.ts +12 -0
- package/dist/plugins/session.d.ts +1 -0
- package/dist/plugins/web-vitals-metrics.d.ts +80 -0
- package/dist/plugins/web-vitals.d.ts +2 -59
- package/dist/schema/attributes.d.ts +63 -0
- package/dist/schema/span.d.ts +5 -2
- package/package.json +9 -4
- package/skills/bk-rum-otele/references/actions.md +54 -37
- package/skills/bk-rum-otele/references/api.md +72 -51
- package/skills/bk-rum-otele/references/architecture.md +16 -16
- package/skills/bk-rum-otele/references/blank-screen.md +72 -142
- package/skills/bk-rum-otele/references/capabilities.md +66 -60
- package/skills/bk-rum-otele/references/configuration.md +101 -98
- package/skills/bk-rum-otele/references/data-model.md +22 -17
- package/skills/bk-rum-otele/references/errors-security.md +13 -13
- package/skills/bk-rum-otele/references/extensions.md +5 -3
- package/skills/bk-rum-otele/references/framework-integration.md +7 -24
- package/skills/bk-rum-otele/references/network.md +62 -49
- package/skills/bk-rum-otele/references/performance.md +62 -30
- package/skills/bk-rum-otele/references/privacy.md +5 -5
- package/skills/bk-rum-otele/references/production.md +9 -13
- package/skills/bk-rum-otele/references/session-context.md +67 -38
- package/skills/bk-rum-otele/references/span-protocol.md +771 -315
- package/skills/bk-rum-otele/references/telemetry-reference.md +288 -213
- package/skills/bk-rum-otele/references/troubleshooting.md +2 -2
- package/skills/bk-rum-otele/references/views-routing.md +103 -27
|
@@ -18,7 +18,7 @@ SDK 不采集任何请求 Body、响应 Body、WebSocket 消息内容、消息
|
|
|
18
18
|
|
|
19
19
|
`tracking.request=false` 时完全不 Patch Fetch/XHR。开启时,同一层实现负责:
|
|
20
20
|
|
|
21
|
-
1. 把 URL 转成绝对 URL
|
|
21
|
+
1. 按 `document.baseURI` 把 URL 转成绝对 URL,保留当前页面目录和 `<base href>` 的语义。
|
|
22
22
|
2. 排除 SDK 自身上报和 `excludedUrls`。
|
|
23
23
|
3. 按白名单探测既有 Trace Header,规划本次请求的 trace context。
|
|
24
24
|
4. 创建 `span_type=resource` 的 CLIENT Span,并把关联后端 Trace 的 Span Link 一并写入。
|
|
@@ -30,6 +30,8 @@ SDK 不采集任何请求 Body、响应 Body、WebSocket 消息内容、消息
|
|
|
30
30
|
|
|
31
31
|
Patch 在插件 shutdown 时仅在全局方法仍是 SDK 安装版本的情况下恢复,避免覆盖 SDK 之后由业务安装的其他 Patch。
|
|
32
32
|
|
|
33
|
+
请求开始阶段的采集 Hook 异常会丢弃本条遥测,原生请求仍执行一次。SDK 不重试业务请求。XHR 每次 `send` 独立保存响应元数据,业务在完成回调中复用实例不会改写上一请求的结果。
|
|
34
|
+
|
|
33
35
|
## 请求 Span
|
|
34
36
|
|
|
35
37
|
Fetch 和 XHR 都生成名称为 `<http.request.method> <url.template>` 的 Resource Span:
|
|
@@ -49,7 +51,7 @@ Fetch 和 XHR 都生成名称为 `<http.request.method> <url.template>` 的 Reso
|
|
|
49
51
|
|
|
50
52
|
这套折叠规则与 View 的 `view.url_template` 共用,但入口独立:页面路由和 API 路径的模板规则通常不同,所以 `tracking.view.getUrlTemplate` 与 `tracking.request.getUrlTemplate` 互不影响。
|
|
51
53
|
|
|
52
|
-
Span
|
|
54
|
+
Span 开始时间使用捕获的 epoch 起点,结束时间用该起点加 Performance 相对耗时;有 RT 时优先采用其结束点,不再与固定 `timeOrigin` 混算。没有匹配时使用已知的 Fetch resolve/reject 或 XHR 终止时刻;shutdown 时仍在飞行的请求使用停止时刻。回退写入 `resource.timing.incomplete=true`;Fetch resolve 只代表响应头可用,这种回退耗时不能作为完整下载耗时。`http.response.status_code` 不上报 XHR 的本地占位值 `0`。
|
|
53
55
|
|
|
54
56
|
## Outcome 与 Status
|
|
55
57
|
|
|
@@ -61,7 +63,12 @@ Span 开始时间使用请求开始时间,结束时间优先使用匹配到的
|
|
|
61
63
|
| Fetch TimeoutError / XHR `timeout` | `timeout` | ERROR,Fetch 记录 exception |
|
|
62
64
|
| Fetch 其他 reject / XHR `error` | `error` | ERROR,Fetch 记录 exception |
|
|
63
65
|
| XHR `load` 但无法取得有效状态 | `error` | ERROR |
|
|
64
|
-
|
|
|
66
|
+
| 无可用 HTTP 状态且无明确失败证据 | `unknown` | UNSET |
|
|
67
|
+
| 有效的其他 HTTP 响应 | `success` | UNSET |
|
|
68
|
+
|
|
69
|
+
静态资源与 Fetch opaque 响应无法取得有效 HTTP 状态时同样为 `unknown`,不因 `responseStatus=0` 推断成功或失败。
|
|
70
|
+
|
|
71
|
+
Fetch 使用 `init.signal` 覆盖后的有效 signal;等待 RT 期间的显式取消可识别为 abort/timeout。`success` 只描述已观测的 HTTP 结果,不保证正文完整传输或业务解析成功。SDK 不读取正文,因此响应头后断流、JSON 解析失败等需要业务侧补充诊断;RT 到达本身不能证明正文消费成功。
|
|
65
72
|
|
|
66
73
|
当前 SDK **不写** `outcome.reason`。HTTP 失败请用 `http.response.status_code` 细分。SDK 不根据业务响应 JSON 中的 code 判断成功或失败;需要业务口径时使用 `request.beforeSend` 增加属性,或上报自定义事件。
|
|
67
74
|
|
|
@@ -101,7 +108,7 @@ tracking: {
|
|
|
101
108
|
}
|
|
102
109
|
```
|
|
103
110
|
|
|
104
|
-
|
|
111
|
+
字符串白名单必须是绝对 HTTP(S) URL,按 origin 和路径段边界匹配。例如 `https://api.example.com/v1` 匹配 `/v1`、`/v1/orders`,不匹配 `/v10` 或其他域名 query 中的该地址。字符串配置不接受用户名、密码、query、hash;复杂条件使用函数或正则。`excludedUrls` 保留子串匹配语义。
|
|
105
112
|
|
|
106
113
|
### 每个请求一条独立后端 Trace
|
|
107
114
|
|
|
@@ -115,7 +122,7 @@ traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
|
115
122
|
|
|
116
123
|
这样后端按 trace-id 检索时,一条 Trace 只对应一个 API 请求,也不会把前端 Resource Span 混进后端链路。前后端的关联由 **Span Link** 承担,后端可按 `link.trace_id` 反查对应的 RUM Span。
|
|
117
124
|
|
|
118
|
-
|
|
125
|
+
SDK 注入或能解析为合法 OTel id 的既有上下文会产出一条 Link:
|
|
119
126
|
|
|
120
127
|
```json
|
|
121
128
|
{
|
|
@@ -125,17 +132,16 @@ traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
|
125
132
|
"span_id": "00f067aa0ba902b7",
|
|
126
133
|
"attributes": {
|
|
127
134
|
"format": "traceparent",
|
|
128
|
-
"injected": true
|
|
129
|
-
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
|
135
|
+
"injected": true
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
]
|
|
133
139
|
}
|
|
134
140
|
```
|
|
135
141
|
|
|
136
|
-
`attributes.format` 是命中的传播格式,`attributes.injected`
|
|
142
|
+
`attributes.format` 是命中的传播格式,`attributes.injected` 标记该上下文是否由 SDK 生成。自动 Link 仅保存这两个属性及规范化 id,不上报原始厂商 Header。
|
|
137
143
|
|
|
138
|
-
`tracestate`
|
|
144
|
+
`tracestate` 不注入、不记录。Link Attributes 与 Span、Event 属性统一经过 `privacy.redactAttributes`,全局 `tracking.beforeSend` 可通过 `links`、`events` 检查或移除对应导出副本。
|
|
139
145
|
|
|
140
146
|
请求 Patch 只在当前 Session 已采样时创建 Span 并注入,因此发出的 flags 恒为 `01`。注入的 span-id 在前端没有对应的已上报 Span,后端 Trace 的根 Span 会以它作为 `parent_span_id`。
|
|
141
147
|
|
|
@@ -143,21 +149,22 @@ traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
|
|
|
143
149
|
|
|
144
150
|
注入前 SDK 会先读取本次请求最终会发出的 Header,按下列优先级探测业务是否已经自行传播链路:
|
|
145
151
|
|
|
146
|
-
| 优先级 | `format`
|
|
147
|
-
|
|
|
148
|
-
| 1
|
|
149
|
-
| 2
|
|
150
|
-
| 3
|
|
151
|
-
| 4
|
|
152
|
-
| 5
|
|
153
|
-
| 6
|
|
152
|
+
| 优先级 | `format` | Header | 能否解析出合法 OTel id |
|
|
153
|
+
| ------ | -------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
154
|
+
| 1 | `traceparent` | `traceparent` | 能 |
|
|
155
|
+
| 2 | `sentry-trace` | `sentry-trace` | 能 |
|
|
156
|
+
| 3 | `b3` | `b3`(单头) | 能,64 位 trace-id 左侧补零到 128 位 |
|
|
157
|
+
| 4 | `b3-multi` | `x-b3-traceid` / `x-b3-spanid` / `x-b3-parentspanid` / `x-b3-sampled` / `x-b3-flags` | 同上 |
|
|
158
|
+
| 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` 拼接高位 |
|
|
159
|
+
| 6 | `sw8` | `sw8` | **不能**,SkyWalking 的 trace-id 不是 16 字节 hex |
|
|
154
160
|
|
|
155
|
-
|
|
161
|
+
探测到有效 W3C 上下文或其他厂商 Header 时,SDK 保留业务传播方式;能够解析合法 id 时写入 `injected=false` 的 Link。多种格式共存时按上述优先级处理。
|
|
156
162
|
|
|
157
163
|
几点需要注意:
|
|
158
164
|
|
|
159
165
|
- `traceparent` 与 SDK 注入的是同一个 Header,因此**格式非法时视作没有既有链路并覆盖注入**——这种值后端同样无法接续。其余格式只要 Header 存在就一律尊重。
|
|
160
|
-
-
|
|
166
|
+
- W3C v00 必须是固定长度的小写十六进制格式,不接受扩展后缀或大写 id。
|
|
167
|
+
- 解析不出合法 id 时(`sw8`、或 `b3: 0` 这类只有采样标记的值),SDK 不生成 Link,也不额外注入,不创建虚假的可跳转 id。
|
|
161
168
|
- 后端只解析 W3C `traceparent`。如果业务发的是 `b3` / `sw8` / Datadog 这类格式,SDK 不注入意味着后端不会生成 Trace,Link 中的 trace-id 在后端查不到。
|
|
162
169
|
- Fetch 读取的是 `init.headers`,缺省时回退到输入 `Request` 的 Headers;XHR 因为浏览器不提供读取请求头的 API,SDK 会额外 Patch `setRequestHeader()` 做快照,这层 Patch 仅在配置了 `allowedTracingUrls` 时安装,`open()` 时快照同步失效。
|
|
163
170
|
|
|
@@ -202,44 +209,50 @@ type BkOTRequestOutcome =
|
|
|
202
209
|
第二个参数保留原始浏览器上下文:
|
|
203
210
|
|
|
204
211
|
- Fetch:`request`、可选 `response`、可选 `error`。
|
|
205
|
-
- XHR:原始 `XMLHttpRequest`
|
|
212
|
+
- XHR:原始 `XMLHttpRequest` 实例,以及本次 send 的 `responseSnapshot`(status/statusText/responseURL/responseType)。原始实例可能已被业务复用,需要历史响应元数据时读取快照;快照不保存正文。
|
|
206
213
|
|
|
207
|
-
Hook
|
|
214
|
+
Hook 在 Resource Timing 合并或回退完成后调用,可以读取 `event.attributes` 中的缓存、大小及阶段字段;Timing 缺失时通过 `resource.timing.incomplete=true` 识别。Hook 可原地修改、删除 `event.attributes`;删除也会移除请求开始时已写入的对应字段。返回 `false` 时 Span 正常结束但不会进入 Exporter。请求级 Hook 抛错时默认继续后续脱敏,`debug=true` 输出 warning。
|
|
208
215
|
|
|
209
216
|
之后仍会执行 `privacy.redactAttributes` 和全局 `tracking.beforeSend`。
|
|
210
217
|
|
|
211
218
|
## Resource Timing 匹配
|
|
212
219
|
|
|
213
|
-
Fetch resolve
|
|
220
|
+
成功 Fetch 的 Promise resolve 只代表响应头可用,SDK 继续等待浏览器在正文完成后产生的 Resource Timing,不主动克隆或读取业务响应体。XHR 终止事件和 Fetch reject 已有结束证据,只额外等待最多 200ms 补齐 Observer 通知。
|
|
214
221
|
|
|
215
|
-
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
222
|
+
- 使用去掉 fragment 后的绝对 URL 和 `initiatorType` 匹配。
|
|
223
|
+
- 以 `performance.now()` 记录原生 `fetch` / `send` 的调用窗口,只接收该窗口内开始的 Entry;不将 Date 毫秒时间用于匹配。
|
|
224
|
+
- 同 URL 请求按开始时间消歧,时钟精度不足而无法区分时放弃补全,不按入队顺序猜测。
|
|
225
|
+
- 已结束记录暂时保留以拦截迟到 Entry,防止它被其他请求认领;记录总量最多 1000 条,超出时淘汰最旧记录;已取得响应或终止结果的请求立即回退,尚未取得结果的请求在结果到达后回退。
|
|
226
|
+
- 成功 Fetch 从响应头可用起最多等待 60 秒。浏览器不支持 Resource Timing、等待超限、容量释放或 SDK shutdown 时使用有界回退,并标记 `resource.timing.incomplete=true`。
|
|
219
227
|
|
|
220
|
-
匹配成功后,请求 Span 使用 Resource Timing 的结束时间,并增加 DNS、连接、TLS、TTFB
|
|
228
|
+
匹配成功后,请求 Span 使用 Resource Timing 的结束时间,并增加 DNS、连接、TLS、TTFB、下载、大小和缓存字段。页面活动在 Resource 完成或回退时结束,Session/View/Action 归属仍按请求起点固定。回退保留基础请求信息,不伪造下载完成时间或缺失的 Timing 字段。
|
|
221
229
|
|
|
222
230
|
## 静态资源
|
|
223
231
|
|
|
224
|
-
`tracking.resource=true` 时,Resource PerformanceObserver 为非 Fetch/XHR Entry 创建独立 Resource CLIENT Span。
|
|
232
|
+
`tracking.resource=true` 时,Resource PerformanceObserver 为非 Fetch/XHR Entry 创建独立 Resource CLIENT Span。Timing-only 资源不猜测 HTTP method;Beacon 可明确标记 POST。缺少 method 时 Span 名为 `resource.<type>`。资源按 Performance 相对区间关联 Session/View/Action。
|
|
233
|
+
|
|
234
|
+
Fetch/XHR Entry 优先回填已有请求 Span。仅首次即允许采集时,SDK 安装前的 buffered API 可补报 Timing-only Resource;仍遵守请求开关和 URL 排除。配置请求级 `beforeSend` 时关闭这种补报,因为历史 RT 无法提供真实 Request/XHR 上下文,也不能绕过过滤规则。运行期匹配失败不会再次生成独立资源。
|
|
235
|
+
|
|
236
|
+
重新授权仅采集新授权区间,旧条目和未授权期间开始的请求不重放。`flush`/`shutdown` 先同步读取 Observer 队列,再执行聚合检查点和请求结算。单条 Hook 异常不会阻断其他资源的处理。
|
|
225
237
|
|
|
226
|
-
|
|
238
|
+
| 字段 | 说明 |
|
|
239
|
+
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
240
|
+
| `url.full` | 绝对 URL,经 `redactUrl` 脱敏 |
|
|
241
|
+
| `url.template` | 脱敏后的低基数 pathname;默认折叠数字 ID、UUID 和长十六进制段 |
|
|
242
|
+
| `resource.type` | 归一化类型:document/xhr/fetch/beacon/css/js/image/font/media/other |
|
|
243
|
+
| `resource.initiator_type` | 浏览器原始 initiatorType,例如 script/link/img/xmlhttprequest |
|
|
244
|
+
| `resource.size` | `decodedBodySize`(解压后 Body Size) |
|
|
245
|
+
| `resource.encoded_body_size` | 编码后 Body Size |
|
|
246
|
+
| `resource.decoded_body_size` | 解码后 Body Size |
|
|
247
|
+
| `resource.transfer_size` | `transferSize`(规范化传输大小;本地缓存为 `0`,协商缓存为 `300`,普通网络响应为 encoded size + `300`,不是精确流量) |
|
|
248
|
+
| `resource.protocol` | `nextHopProtocol`,例如 `h2` |
|
|
249
|
+
| `resource.cache.hit` | 确认 HTTP 缓存命中时写 `true`;先排除有 Service Worker 或其静态路由参与证据的条目,再判断交付类型及兜底条件 |
|
|
250
|
+
| `resource.delivery_type` | 浏览器提供的 delivery type;空字符串归一为 `other`,不支持时省略 |
|
|
251
|
+
| `resource.render_blocking_status` | blocking / non-blocking,浏览器支持时 |
|
|
227
252
|
|
|
228
|
-
|
|
229
|
-
| --------------------------------- | ---------------------------------------------------------- |
|
|
230
|
-
| `url.full` | 绝对 URL,经 `redactUrl` 脱敏 |
|
|
231
|
-
| `url.template` | 脱敏后的低基数 pathname;默认折叠数字 ID、UUID 和长十六进制段 |
|
|
232
|
-
| `resource.type` | initiator type |
|
|
233
|
-
| `resource.size` | `decodedBodySize`(解压后 Body Size) |
|
|
234
|
-
| `resource.encoded_body_size` | 编码后 Body Size |
|
|
235
|
-
| `resource.decoded_body_size` | 解码后 Body Size |
|
|
236
|
-
| `resource.transfer_size` | `transferSize`(网络传输字节数,缓存命中可能为 `0`) |
|
|
237
|
-
| `resource.protocol` | `nextHopProtocol`,例如 `h2` |
|
|
238
|
-
| `resource.cache.hit` | deliveryType=cache,或 transferSize=0 且 decodedBodySize>0 |
|
|
239
|
-
| `resource.delivery_type` | 浏览器提供的 delivery type |
|
|
240
|
-
| `resource.render_blocking_status` | blocking / non-blocking,浏览器支持时 |
|
|
253
|
+
当 `transferSize`、`encodedBodySize`、`decodedBodySize` 均为 `0`,同时 `requestStart`、`responseStart` 为 `0` 且 `nextHopProtocol` 为空时,SDK 将其视为浏览器未暴露 Resource Timing 详情,不上报大小和协议字段,避免把“未知”误报为真实的 `0`。
|
|
241
254
|
|
|
242
|
-
|
|
255
|
+
`resource.cache.hit` 缺失表示无法确认 HTTP 缓存命中,不能按 `false` 统计。`delivery_type=other` 只表示浏览器返回空交付类型,也不代表明确未命中。原始 SW 路由来源统一映射到 `resource.timing.worker_matched_router_source` / `worker_final_router_source`,同时识别规范的 `*RouterSource` 名称和浏览器的 `*SourceType` 名称。
|
|
243
256
|
|
|
244
257
|
## 网络阶段字段
|
|
245
258
|
|
|
@@ -274,12 +287,12 @@ Timing-Allow-Origin: https://your-web.example.com
|
|
|
274
287
|
|
|
275
288
|
`tracking.websocket=true` 时,SDK 使用 Proxy 包装全局 `WebSocket` 构造器,并保持静态常量、`instanceof` 和子类构造行为。每条连接生成 `websocket.connection.id`,随后发送四类瞬时 CLIENT Span:
|
|
276
289
|
|
|
277
|
-
| phase | 时机 | 额外字段
|
|
278
|
-
| --------- | --------------------- |
|
|
279
|
-
| `connect` | 构造 WebSocket 后立即 | 基础目标字段
|
|
280
|
-
| `open` | `open` Event | 无
|
|
290
|
+
| phase | 时机 | 额外字段 |
|
|
291
|
+
| --------- | --------------------- | ----------------------------------------------- |
|
|
292
|
+
| `connect` | 构造 WebSocket 后立即 | 基础目标字段 |
|
|
293
|
+
| `open` | `open` Event | 无 |
|
|
281
294
|
| `error` | `error` Event | `websocket.error.phase`:`connect` 或 `runtime` |
|
|
282
|
-
| `close` | `close` Event | code、reason、was_clean
|
|
295
|
+
| `close` | `close` Event | code、reason、was_clean |
|
|
283
296
|
|
|
284
297
|
Span 名按 `websocket.<websocket.phase>` 生成,不使用长连接 Span。基础字段包括:
|
|
285
298
|
|
|
@@ -303,7 +316,7 @@ Span 名按 `websocket.<websocket.phase>` 生成,不使用长连接 Span。基
|
|
|
303
316
|
|
|
304
317
|
### 有请求 Span 但没有网络阶段
|
|
305
318
|
|
|
306
|
-
|
|
319
|
+
先检查 `resource.timing.incomplete`:为 `true` 时表示没有可用的匹配 Entry,例如浏览器不支持、同 URL 消歧失败、等待或容量达到上限、SDK 已停止。字段未标记但详细阶段缺失时,再检查跨域 TAO 限制或浏览器返回的时间点顺序。
|
|
307
320
|
|
|
308
321
|
### 后端没有收到 traceparent
|
|
309
322
|
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
`span_type=vital` 覆盖以下指标,Span 名使用大写指标名:
|
|
10
10
|
|
|
11
|
-
| 指标
|
|
12
|
-
|
|
|
13
|
-
| Cumulative Layout Shift
|
|
14
|
-
| First Contentful Paint
|
|
15
|
-
| Interaction to Next Paint | `inp`
|
|
16
|
-
| Largest Contentful Paint
|
|
17
|
-
| Time to First Byte
|
|
11
|
+
| 指标 | `vital.metric` | 单位 | 当前采集方式 |
|
|
12
|
+
| ------------------------- | -------------- | ------ | ------------------------------------- |
|
|
13
|
+
| Cumulative Layout Shift | `cls` | 无量纲 | 每个 SDK View 独立计算 session window |
|
|
14
|
+
| First Contentful Paint | `fcp` | ms | 原生 Paint Timing observer |
|
|
15
|
+
| Interaction to Next Paint | `inp` | ms | 每个 SDK View 维护交互候选近似 p98 |
|
|
16
|
+
| Largest Contentful Paint | `lcp` | ms | 原生 LCP observer 与候选快照 |
|
|
17
|
+
| Time to First Byte | `ttfb` | ms | 文档 Navigation Timing |
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
SDK 自行管理这些 observer、事件监听和任务;停止采集时会结算已观测值并释放它们,不再依赖第三方 `onFCP/onLCP/onTTFB` 回调的生命周期。浏览器不支持某项 API 时跳过该项,不用 0 伪造支持。
|
|
20
20
|
|
|
21
21
|
## 公共 Vital 字段
|
|
22
22
|
|
|
@@ -25,29 +25,45 @@
|
|
|
25
25
|
- `vital.metric`
|
|
26
26
|
- `vital.value`
|
|
27
27
|
- `vital.id`
|
|
28
|
+
- `vital.version`:同一指标快照递增版本
|
|
29
|
+
- `vital.scope`:`document`、`activation` 或 `view`
|
|
28
30
|
- `span_type=vital`
|
|
29
31
|
- `outcome.type=success`,仅内部 rating=good
|
|
30
32
|
- `outcome.type=warning`,其他 rating
|
|
31
33
|
|
|
32
|
-
Vital Span 是瞬时 INTERNAL Span
|
|
34
|
+
Vital Span 是瞬时 INTERNAL Span,时间表示生成本次快照的时刻;Session/View 关联仍使用原归属时间。非法、负数值不报。当前不写 `vital.rating` 或 `navigationType` Attribute;good/poor 只通过 `outcome.type` 体现。
|
|
35
|
+
|
|
36
|
+
`vital.id` 在一个作用域中的同一指标上保持稳定;值、归因或 View 上下文变化时增加版本。服务端按 `vital.id` 取最大 `vital.version`,**不能把修订值相加,也不能把每次快照当成一个新的页面样本**。重复 flush 没有变化时不重复发;同一 View 替换上下文时删除的业务字段不会在后续指标中残留。没有 `vital.final` 字段。
|
|
37
|
+
|
|
38
|
+
Session/View 身份固定在原作用域;仍活跃的所属 View 在生成快照前刷新用户、View 名称和业务上下文,结束后冻结最终上下文。文档指标晚于 SPA 导航到达时继续使用已结束初始 View 的上下文,不借用新页面的用户或业务字段。
|
|
33
39
|
|
|
34
40
|
## Navigation Type
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
当前插件不写 `navigationType`,使用 `vital.scope` 和所属 View 的加载类型区分文档、BFCache 恢复与逻辑 View。不要按 `navigationType` 查询 Collector 数据。
|
|
37
43
|
|
|
38
44
|
## FCP、LCP 与 TTFB 的 View 归属
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
文档初始 FCP/LCP/TTFB 固定关联文档初始 View,`vital.scope=document`。即使 SPA 首屏重定向发生在第一次 paint 之前,也不会把文档累计值挂到新的 route_change View。缺少合法的文档初始 View 时不向当前 View 补报这些指标。
|
|
47
|
+
|
|
48
|
+
BFCache 的 `back-forward-cache` 指标绑定本次恢复的 View,`vital.scope=activation`,也不会随恢复后的 SPA 路由漂移。普通 SPA 导航没有新的文档 Navigation Timing;当前没有开启 Soft Navigation 采集,不能将这些文档指标理解为每次 SPA 路由的 FCP/LCP。
|
|
49
|
+
|
|
50
|
+
BFCache 恢复时的 FCP/LCP 使用 `pageshow` 后双 `requestAnimationFrame` 近似恢复绘制时间,不代表浏览器重新产生了文档首次绘制;TTFB 为 0。恢复指标按本次 activation 时间匹配恢复 View,View 尚未就绪时先有界暂存。
|
|
51
|
+
|
|
52
|
+
初始化会恢复保留范围内的 View 历史,再归属浏览器 buffered 条目;首次手动 View 尚未建立时也会有界暂存待关联指标。首次手动 View 建立后可接收文档指标,不能无限追溯已被浏览器或 SDK 裁剪的条目。撤销同意会停止采集,再授权继续当前文档,不会重新制造 `initial_load` 或重复采集该文档的 FCP/LCP/TTFB;重新加载文档仍是新的首屏。
|
|
53
|
+
|
|
54
|
+
文档 LCP 会保留当前候选,检查点可在首次交互之前上报;首次可信 click/keydown、页面隐藏或结束会收束观测窗口。显式 shutdown 会先取出已排队条目并导出最后已知候选。FCP/LCP 排除首次隐藏后的首屏绘制;prerender 的文档指标以激活时间为基准。
|
|
41
55
|
|
|
42
56
|
Attribution 字段:
|
|
43
57
|
|
|
44
|
-
| 指标 | 字段
|
|
45
|
-
|
|
|
46
|
-
| LCP
|
|
47
|
-
| FCP
|
|
48
|
-
| TTFB | `vital.ttfb.waiting_duration`、`dns_duration`、`connection_duration`、`request_duration`
|
|
58
|
+
| 指标 | 字段 |
|
|
59
|
+
| ---- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
60
|
+
| LCP | `vital.lcp.url`、`target`、`time_to_first_byte`、`resource_load_delay`、`element_render_delay`、`resource_load_duration` |
|
|
61
|
+
| FCP | 当前无独立归因字段 |
|
|
62
|
+
| TTFB | `vital.ttfb.waiting_duration`、`cache_duration`、`dns_duration`、`connection_duration`、`request_duration` |
|
|
63
|
+
|
|
64
|
+
LCP URL 经过 `redactUrl`;目标 selector 在观测候选时按 Action 的节点隐私与结构定位规则快照,之后节点移除不会清空已经安全捕获的 selector。无法安全定位时省略,不回退透传原始 DOM ID。LCP 资源关联选择该候选前最后一条同 URL 的 Resource Timing。
|
|
49
65
|
|
|
50
|
-
|
|
66
|
+
TTFB 五段按 Navigation Timing 的相邻边界裁剪,均非负,合计等于 TTFB。`vital.ttfb.cache_duration` 表示请求开始准备后至 DNS 阶段前的耗时;它不是缓存命中标记,也不能据此推断 memory/disk cache。
|
|
51
67
|
|
|
52
68
|
## 每个 View 的 CLS
|
|
53
69
|
|
|
@@ -57,8 +73,10 @@ SDK 不直接使用整页生命周期累计的 web-vitals CLS,而是按 SDK Vi
|
|
|
57
73
|
- 相邻 Shift 间隔小于 1 秒且窗口总长小于 5 秒时进入同一 session window;
|
|
58
74
|
- 取所有 session window 中累计值最大的一个;
|
|
59
75
|
- 数值保留四位小数;
|
|
60
|
-
-
|
|
61
|
-
-
|
|
76
|
+
- 浏览器支持 Layout Shift 时,检查点可以发送值为 0 的 CLS;不支持时不伪造 0;
|
|
77
|
+
- 归因选取最大累计窗口内最大的单次 Shift;同一窗口后续的小位移不会覆盖主要来源;
|
|
78
|
+
- 从该 Shift 的 sources 中按 previous/current 两个矩形的并集面积选择节点,覆盖节点消失等情况;不把两个矩形间的空白算进面积;
|
|
79
|
+
- 同时记录该 Shift 的相对 View 时间、前后矩形和当时的 DPR;累计最大窗口改变时同步切换归因。
|
|
62
80
|
|
|
63
81
|
Rating 阈值(只影响 `outcome.type`,不写 `vital.rating`):
|
|
64
82
|
|
|
@@ -66,19 +84,19 @@ Rating 阈值(只影响 `outcome.type`,不写 `vital.rating`):
|
|
|
66
84
|
- `<= 0.25`:needs-improvement → `warning`
|
|
67
85
|
- `> 0.25`:poor → `warning`
|
|
68
86
|
|
|
69
|
-
|
|
87
|
+
归因字段为 `vital.cls.time`(相对 View 起点的 ms)、`vital.cls.target_selector`、`vital.cls.previous_rect.x/y/width/height`、`vital.cls.current_rect.x/y/width/height`(CSS px)和 `vital.cls.device_pixel_ratio`。DPR 不改变矩形原始 CSS 像素值。浏览器没有 source/矩形或节点无法安全定位时,对应字段缺失。不输出 `vital.cls.load_state` 或 `vital.cls.largest_shift_*`。
|
|
70
88
|
|
|
71
89
|
## 每个 View 的 INP
|
|
72
90
|
|
|
73
|
-
SDK
|
|
91
|
+
SDK 将交互计数与慢交互候选分开:
|
|
74
92
|
|
|
75
|
-
1. 按 interactionId
|
|
76
|
-
2. duration 上限保护为 60,000ms
|
|
93
|
+
1. 按 interactionId 选择同次交互中 duration 最大的候选;归因额外合并同交互,以及渲染时刻落在固定参考帧 ±8ms 内的条目,取最早输入/处理开始与最晚处理结束。
|
|
94
|
+
2. duration 上限保护为 60,000ms;三段耗时共用这个值对应的终点并裁剪处理区间,保证非负且总和等于上报值。模态对话框等导致 processingEnd 超出绘制终点时也遵守此约束。
|
|
77
95
|
3. 保留当前 View 最慢的 10 个候选。
|
|
78
|
-
4.
|
|
79
|
-
5.
|
|
96
|
+
4. 候选 observer 的 durationThreshold 为 40ms,并用 first-input 覆盖第一次较快交互。
|
|
97
|
+
5. 独立低阈值 observer(配置 durationThreshold=0,实际分辨率受浏览器约束)维护 interactionId 范围,避免只有慢候选参与计数;原生 interactionCount 可用时优先结合它,View 结束冻结原生边界并校正跨边界迟到交互。
|
|
80
98
|
6. 取排序候选中接近 p98 的位置,而不是简单最大值。
|
|
81
|
-
7.
|
|
99
|
+
7. 无交互或 API 不支持时不发 INP;明确观测到交互但尚无候选时可发 0,之后迟到候选以更高版本修订。它不是“未支持”的替代值。
|
|
82
100
|
|
|
83
101
|
Rating 阈值:
|
|
84
102
|
|
|
@@ -90,15 +108,29 @@ Attribution:
|
|
|
90
108
|
|
|
91
109
|
- `vital.inp.interaction_target`
|
|
92
110
|
- `vital.inp.interaction_type`
|
|
111
|
+
- `vital.inp.target_selector`
|
|
112
|
+
- `vital.inp.time`:相对所属 View 起点的 ms
|
|
93
113
|
- `vital.inp.input_delay`
|
|
94
114
|
- `vital.inp.processing_duration`
|
|
95
115
|
- `vital.inp.presentation_delay`
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
同一 observer 批次先完成处理区间分组,再裁剪分组状态;较短条目也能补全保留候选的处理阶段。跨批次只保留与最慢 10 个候选相关的分组,内存不随交互总数增长。
|
|
118
|
+
|
|
119
|
+
Target 采用 Action 的显式命名模式:显式 Action 名称或标签回退,不自动采集整段 DOM 文本;selector 使用同一节点隐私策略。可信输入发生时先捕获经过隐私处理的字符串,快照匹配有效期为 10 秒,缓存最多 100 项;条目到达时按事件类型和时间匹配,用于目标已被路由卸载的情况。匹配到“禁止采集”结果时不会回退读取 DOM,定位歧义或信息不足时允许缺失。计数降级仍基于 interactionId 间隔估算,受浏览器实现和可交付条目限制,并非精确的业务点击计数。
|
|
98
120
|
|
|
99
121
|
## SPA 语义
|
|
100
122
|
|
|
101
|
-
FCP、LCP、TTFB
|
|
123
|
+
FCP、LCP、TTFB 使用文档/恢复作用域;CLS 和 INP 为 `vital.scope=view`。同 ID 的名称或上下文修改不清空指标;新 View 创建时关闭旧 View 的时间区间,开始新的累计。
|
|
124
|
+
|
|
125
|
+
View 另存与 `PerformanceEntry.startTime` 同一时钟的相对起止时间,用于条目归属和 CLS/INP 的相对时间;epoch 时间保留给 Session 上下文和 OTLP 时间戳。系统墙钟调整不会直接移动性能条目的 View 边界。Hash、History 和手动 SPA View 使用同样的区间规则;MPA 新文档重新开始文档指标。
|
|
126
|
+
|
|
127
|
+
结束 View 的 CLS/INP 状态最多接受 5 分钟内到达的条目,并限制总保留状态最多 100 个;过期状态在后续处理时裁剪。条目按 startTime 落入的 View 半开区间归属,迟到修订保持原 Session/View,超出保留范围的条目不改挂当前 View。
|
|
128
|
+
|
|
129
|
+
`flush()`、hidden、freeze、View 边界和显式 shutdown 会先读取 observer 已排队条目,再生成有变化的快照;结束 View 的迟到条目到达后也会更新快照。普通 flush/hidden 不结束 View、不为 Session 续期。shutdown 结算后才关闭回调;它无法等待尚未由浏览器产生的未来条目,也不保证系统强杀前一定发送成功。
|
|
130
|
+
|
|
131
|
+
活跃 View 的 CLS/INP 变化和文档 LCP 候选更新会调度一个约 3 秒的合并检查点,多次变化共用待执行任务;没有变化不会持续发定时快照。浏览器后台节流可能延迟任务,网络发送还遵循导出器批处理,3 秒不是服务端可见时间保证。检查点不算用户活动。
|
|
132
|
+
|
|
133
|
+
当前不提供 Soft Navigation 指标、自定义 duration vital 或自动将 INP 关联到 LoAF 脚本根因;下面的 Long Task/LoAF 是独立采集能力。
|
|
102
134
|
|
|
103
135
|
## Long Task 启用
|
|
104
136
|
|
|
@@ -179,8 +211,8 @@ Long Task 会为每个 Entry 建 Span,并可能附带多个脚本 Event;在
|
|
|
179
211
|
|
|
180
212
|
在控制台检查 `PerformanceObserver.supportedEntryTypes`。不支持两种 API时是正常降级;还要确认插件已开启、Session 被采样、存在有效 View、Entry duration 达到阈值。
|
|
181
213
|
|
|
182
|
-
### CLS/INP
|
|
214
|
+
### 查看当前 CLS/INP
|
|
183
215
|
|
|
184
|
-
|
|
216
|
+
调用 `await bkOT.flush()` 可以生成当前指标检查点,不需要切换 View 或关闭 SDK。检索时按 `vital.id` 选择最大版本;检查点之后仍可能出现同一 View 的指标修订。
|
|
185
217
|
|
|
186
218
|
完整字段见[遥测字段字典](./telemetry-reference.md#web-vitals-字段)和[Long Task 字段](./telemetry-reference.md#long-task-字段)。
|
|
@@ -128,16 +128,16 @@ privacy: {
|
|
|
128
128
|
- SDK 构造 Resource attributes 时调用一次;
|
|
129
129
|
- `BkOpenTelemetry.startSpan()` 合并运行时与显式属性后调用;
|
|
130
130
|
- 内置/自定义插件也可以显式调用 `context.applyRedact()`;
|
|
131
|
-
- Filter processor
|
|
131
|
+
- Filter processor 在全局 `tracking.beforeSend` 前后统一处理 Span、Event 和 Link 属性;同一对象可能经过多次脱敏,Hook 应保持幂等。
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
每次调用接收一个 Attributes 对象,包括第三方 Instrumentation 的字段和 `recordException()` 产生的 exception message/stacktrace。任一最终脱敏调用抛错时,整条遥测会丢弃,不回退发送原始数据。
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
`tracking.beforeSend` 的新增字段也会再次脱敏:
|
|
136
136
|
|
|
137
137
|
```ts
|
|
138
138
|
tracking: {
|
|
139
139
|
beforeSend(event) {
|
|
140
|
-
//
|
|
140
|
+
// 导出前仍会经过 redactAttributes
|
|
141
141
|
event.attributes['biz.region'] = 'ap-guangzhou';
|
|
142
142
|
},
|
|
143
143
|
}
|
|
@@ -232,7 +232,7 @@ tracking: {
|
|
|
232
232
|
错误可能包含:
|
|
233
233
|
|
|
234
234
|
- `error.message`;
|
|
235
|
-
- exception message、type 和 stacktrace
|
|
235
|
+
- exception message、type 和 stacktrace;可通过 `redactAttributes` 或 `tracking.beforeSend` 的 events 导出副本治理;
|
|
236
236
|
- 源文件 URL、行列号;
|
|
237
237
|
- Promise rejection 的字符串化内容;
|
|
238
238
|
- 资源加载失败 URL。
|
|
@@ -35,9 +35,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
35
35
|
},
|
|
36
36
|
request: {
|
|
37
37
|
excludedUrls: [/\/health(?:\?|$)/],
|
|
38
|
-
allowedTracingUrls: [
|
|
39
|
-
rawUrl => new URL(rawUrl, location.href).origin === 'https://api.example.com',
|
|
40
|
-
],
|
|
38
|
+
allowedTracingUrls: [rawUrl => new URL(rawUrl, location.href).origin === 'https://api.example.com'],
|
|
41
39
|
},
|
|
42
40
|
blankScreen: {
|
|
43
41
|
rootSelector: '#app',
|
|
@@ -50,9 +48,7 @@ export const rum = new BkOpenTelemetry({
|
|
|
50
48
|
url.password = '';
|
|
51
49
|
url.search = '';
|
|
52
50
|
url.hash = '';
|
|
53
|
-
url.pathname = url.pathname
|
|
54
|
-
.replace(/\/orders\/[^/]+/g, '/orders/:id')
|
|
55
|
-
.replace(/\/users\/[^/]+/g, '/users/:id');
|
|
51
|
+
url.pathname = url.pathname.replace(/\/orders\/[^/]+/g, '/orders/:id').replace(/\/users\/[^/]+/g, '/users/:id');
|
|
56
52
|
return url.href;
|
|
57
53
|
},
|
|
58
54
|
redactAttributes(attributes) {
|
|
@@ -154,7 +150,7 @@ allowedTracingUrls: [
|
|
|
154
150
|
const url = new URL(rawUrl, location.href);
|
|
155
151
|
return url.origin === 'https://api.example.com' && url.pathname.startsWith('/v2/');
|
|
156
152
|
},
|
|
157
|
-
]
|
|
153
|
+
];
|
|
158
154
|
```
|
|
159
155
|
|
|
160
156
|
不要使用宽泛 `/./` 或所有 URL,避免向第三方发送 Trace ID,也避免触发额外预检。API 端必须允许 `traceparent` header,并正确接续 W3C Trace Context。
|
|
@@ -190,11 +186,11 @@ Action:
|
|
|
190
186
|
|
|
191
187
|
默认关闭项应按问题启用:
|
|
192
188
|
|
|
193
|
-
| 能力
|
|
194
|
-
|
|
|
195
|
-
| Long Task | 主线程卡顿和脚本归因 | 事件量、脚本 URL/函数信息
|
|
196
|
-
| CSP
|
|
197
|
-
| WebSocket | 连接失败/断开分析
|
|
189
|
+
| 能力 | 适合场景 | 主要风险 |
|
|
190
|
+
| --------- | -------------------- | --------------------------------- |
|
|
191
|
+
| Long Task | 主线程卡顿和脚本归因 | 事件量、脚本 URL/函数信息 |
|
|
192
|
+
| CSP | 安全策略诊断 | `original_policy`、高频 violation |
|
|
193
|
+
| WebSocket | 连接失败/断开分析 | 全局 Proxy、长连接生命周期 |
|
|
198
194
|
|
|
199
195
|
先小流量评估平均每 Session 增量,再扩大采样。
|
|
200
196
|
|
|
@@ -241,7 +237,7 @@ SDK 设计为:
|
|
|
241
237
|
服务端需要理解:
|
|
242
238
|
|
|
243
239
|
- Session/View 生命周期通过多条 Span 表达,`session.phase`、`view.phase` 与 `view.version` 用于重建状态;
|
|
244
|
-
- `action.id`
|
|
240
|
+
- Action 自身为单值 `action.id`,Resource/Error/Long Task 用 `action.ids` 数组关联;服务端需按数组展开和去重派生 count,客户端不双写旧字段;
|
|
245
241
|
- `vital.value` 是原始指标;分位数服务端计算;
|
|
246
242
|
- 资源网络阶段只在浏览器可见时出现;
|
|
247
243
|
- IP/geo、错误指纹、聚合数不是 SDK 字段;
|