@blueking/open-telemetry 0.0.34 → 0.0.35-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +67 -57
  2. package/dist/bk-rum.global.js +2 -2
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/action-activity.d.ts +5 -1
  5. package/dist/core/action-target.d.ts +19 -0
  6. package/dist/core/config.d.ts +15 -5
  7. package/dist/core/event-time.d.ts +7 -0
  8. package/dist/core/performance-timing.d.ts +13 -0
  9. package/dist/core/plugin.d.ts +37 -2
  10. package/dist/core/processor.d.ts +24 -2
  11. package/dist/core/request-timing.d.ts +3 -2
  12. package/dist/core/runtime-context.d.ts +62 -2
  13. package/dist/core/sdk.d.ts +23 -1
  14. package/dist/core/session-transition.d.ts +19 -0
  15. package/dist/core/trace-context.d.ts +6 -7
  16. package/dist/core/view-location.d.ts +10 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +2933 -1505
  19. package/dist/index.js.map +1 -1
  20. package/dist/integrations/vue-router.d.ts +25 -0
  21. package/dist/plugins/action.d.ts +1 -1
  22. package/dist/plugins/blank-screen-detection.d.ts +11 -0
  23. package/dist/plugins/blank-screen.d.ts +10 -18
  24. package/dist/plugins/common.d.ts +4 -2
  25. package/dist/plugins/document-vitals.d.ts +25 -0
  26. package/dist/plugins/page-view.d.ts +1 -1
  27. package/dist/plugins/resource.d.ts +3 -1
  28. package/dist/plugins/session-state.d.ts +14 -2
  29. package/dist/plugins/session-store.d.ts +12 -0
  30. package/dist/plugins/session.d.ts +1 -0
  31. package/dist/plugins/web-vitals-metrics.d.ts +80 -0
  32. package/dist/plugins/web-vitals.d.ts +2 -59
  33. package/dist/schema/attributes.d.ts +45 -0
  34. package/dist/schema/span.d.ts +5 -2
  35. package/package.json +9 -4
  36. package/skills/bk-rum-otele/references/actions.md +54 -37
  37. package/skills/bk-rum-otele/references/api.md +72 -51
  38. package/skills/bk-rum-otele/references/architecture.md +16 -16
  39. package/skills/bk-rum-otele/references/blank-screen.md +72 -142
  40. package/skills/bk-rum-otele/references/capabilities.md +66 -60
  41. package/skills/bk-rum-otele/references/configuration.md +101 -98
  42. package/skills/bk-rum-otele/references/data-model.md +22 -17
  43. package/skills/bk-rum-otele/references/errors-security.md +13 -13
  44. package/skills/bk-rum-otele/references/extensions.md +5 -3
  45. package/skills/bk-rum-otele/references/framework-integration.md +7 -24
  46. package/skills/bk-rum-otele/references/network.md +62 -49
  47. package/skills/bk-rum-otele/references/performance.md +62 -30
  48. package/skills/bk-rum-otele/references/privacy.md +5 -5
  49. package/skills/bk-rum-otele/references/production.md +9 -13
  50. package/skills/bk-rum-otele/references/session-context.md +67 -38
  51. package/skills/bk-rum-otele/references/span-protocol.md +692 -421
  52. package/skills/bk-rum-otele/references/telemetry-reference.md +288 -213
  53. package/skills/bk-rum-otele/references/troubleshooting.md +2 -2
  54. package/skills/bk-rum-otele/references/views-routing.md +103 -27
@@ -10,11 +10,11 @@
10
10
 
11
11
  如果两份文档对不上,先查「遥测字段字典」确认 SDK 现在上报了什么。代码中出现了某个字段,并不表示它已经稳定;只有在本页标记为 Stable,前后端才需要长期兼容这个字段。
12
12
 
13
- | 状态 | 描述 |
14
- | -------------------------------------------------------------- | -------------- |
15
- | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | 当前 SDK 已上报,保持现状。 |
16
- | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | 已上报,但需要废弃。 |
17
- | ![Development](https://img.shields.io/badge/-development-blue) | 新补充或字段位置变更。 |
13
+ | 状态 | 描述 |
14
+ | -------------------------------------------------------------- | ---------------------------- |
15
+ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | 当前 SDK 已上报,保持现状。 |
16
+ | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | 已上报,但需要废弃。 |
17
+ | ![Development](https://img.shields.io/badge/-development-blue) | 新补充或字段位置变更。 |
18
18
  | ![Backend](https://img.shields.io/badge/-backend-orange) | 由后端生成,前端不直接上报。 |
19
19
 
20
20
  原则:
@@ -39,87 +39,87 @@ Session
39
39
 
40
40
  ### a. 顶层字段
41
41
 
42
- | 字段 | 状态 | 类型 | 描述 | 备注 |
43
- | ---------------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
44
- | `time` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 数据上报时间(毫秒时间戳字符串) | -- |
45
- | `app_name` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 应用 | -- |
46
- | `bk_biz_id` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 业务 ID | -- |
47
- | `trace_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Trace ID | -- |
48
- | `trace_state` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Trace 扩展信息 | -- |
49
- | `span_name` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 可读的低基数 Span 名称 | 由 SDK 根据 `span_type` 和领域字段生成。 |
50
- | `span_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Span ID | -- |
51
- | `parent_span_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 父 Span ID | -- |
52
- | `status` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | Status | Span 执行状态 | 包含 `code` 和 `message`。 |
53
- | `kind` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | [调用类型](https://opentelemetry.io/zh/docs/concepts/signals/traces/#span-kind) | 枚举值:<br>- 未定义:0<br>- 内部调用:1<br>- 同步被调:2<br>- 同步主调:3<br>- 异步主调:4<br>- 异步被调:5 |
54
- | `resource` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | object | 资源信息 | 服务、环境、SDK 等描述信息。 |
55
- | `events` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | Event[] | 事件列表 | 异常详情和 Long Task 脚本明细通过 Span Event 承载。 |
56
- | `links` | ![Development](https://img.shields.io/badge/-development-blue) | Link[] | [Span 链接](https://opentelemetry.io/docs/concepts/signals/traces/#span-links) | 链接的存在是为了 Span 同其他 Span 建立关联,从而表明存在因果关系。 |
57
- | `attributes` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | object | 属性 | 浏览器、设备、网络、异常等各类语义标签和度量。 |
58
- | `start_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 开始时间(微秒) | 后端入库字段。SDK 线上传输使用 OTLP `startTimeUnixNano`(纳秒十进制字符串)。 |
59
- | `end_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 结束时间(微秒) | 同上,对应 `endTimeUnixNano`。 |
60
- | `elapsed_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 耗时(微秒) | 后端由起止时间相减;浏览器 SDK 不单独上报该 Attribute。 |
42
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
43
+ | ----------------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
44
+ | `time` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 数据上报时间(毫秒时间戳字符串) | -- |
45
+ | `app_name` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 应用 | -- |
46
+ | `bk_biz_id` | ![Backend](https://img.shields.io/badge/-backend-orange) | str | 业务 ID | -- |
47
+ | `trace_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Trace ID | -- |
48
+ | `trace_state` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Trace 扩展信息 | -- |
49
+ | `span_name` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 可读的低基数 Span 名称 | 由 SDK 根据 `span_type` 和领域字段生成。 |
50
+ | `span_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Span ID | -- |
51
+ | `parent_span_id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 父 Span ID | -- |
52
+ | `status` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | Status | Span 执行状态 | 包含 `code` 和 `message`。 |
53
+ | `kind` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | [调用类型](https://opentelemetry.io/zh/docs/concepts/signals/traces/#span-kind) | 枚举值:<br>- 未定义:0<br>- 内部调用:1<br>- 同步被调:2<br>- 同步主调:3<br>- 异步主调:4<br>- 异步被调:5 |
54
+ | `resource` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | object | 资源信息 | 服务、环境、SDK 等描述信息。 |
55
+ | `events` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | Event[] | 事件列表 | 异常详情和 Long Task 脚本明细通过 Span Event 承载。 |
56
+ | `links` | ![Development](https://img.shields.io/badge/-development-blue) | Link[] | [Span 链接](https://opentelemetry.io/docs/concepts/signals/traces/#span-links) | 链接的存在是为了 Span 同其他 Span 建立关联,从而表明存在因果关系。 |
57
+ | `attributes` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | object | 属性 | 浏览器、设备、网络、异常等各类语义标签和度量。 |
58
+ | `start_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 开始时间(微秒) | 后端入库字段。SDK 线上传输使用 OTLP `startTimeUnixNano`(纳秒十进制字符串)。 |
59
+ | `end_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 结束时间(微秒) | 同上,对应 `endTimeUnixNano`。 |
60
+ | `elapsed_time` | ![Backend](https://img.shields.io/badge/-backend-orange) | int | 耗时(微秒) | 后端由起止时间相减;浏览器 SDK 不单独上报该 Attribute。 |
61
61
 
62
62
  **[1] `span_name`**:
63
63
 
64
- | `attributes.span_type` | 生成规则 | 示例 |
65
- | --- | --- | --- |
66
- | `session` | `session.<attributes.session.phase>` | `session.start` |
67
- | `view` | `attributes.view.name` | `订单详情` |
68
- | `resource` | `<attributes.http.request.method> <attributes.url.template>` | `GET /api/orders/:id` |
69
- | `action` | `attributes.action.name` | `click 提交订单` |
70
- | `error` | 异常类型;白屏和 CSP 使用稳定分类 | `TypeError`、`blank_screen.empty_viewport`、`csp.script-src-elem` |
71
- | `vital` | 大写的 `attributes.vital.metric` | `LCP` |
72
- | `long_task` | `attributes.long_task.entry_type` | `long-animation-frame` |
73
- | `websocket` | `websocket.<attributes.websocket.phase>` | `websocket.connect` |
74
- | `custom` | `custom.<name>` | `custom.checkout_success` |
64
+ | `attributes.span_type` | 生成规则 | 示例 |
65
+ | ---------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------- |
66
+ | `session` | `session.<attributes.session.phase>` | `session.start` |
67
+ | `view` | `attributes.view.name` | `订单详情` |
68
+ | `resource` | `<attributes.http.request.method> <attributes.url.template>` | `GET /api/orders/:id` |
69
+ | `action` | `attributes.action.name` | `click 提交订单` |
70
+ | `error` | 异常类型;白屏和 CSP 使用稳定分类 | `TypeError`、`blank_screen.empty_viewport`、`csp.script-src-elem` |
71
+ | `vital` | 大写的 `attributes.vital.metric` | `LCP` |
72
+ | `long_task` | `attributes.long_task.entry_type` | `long-animation-frame` |
73
+ | `websocket` | `websocket.<attributes.websocket.phase>` | `websocket.connect` |
74
+ | `custom` | `custom.<name>` | `custom.checkout_success` |
75
75
 
76
76
  名称不包含 ID、完整 URL、错误消息、时间戳或数值。业务传入的 View、Action 和 Custom 名称必须保持稳定。
77
77
 
78
78
  ### b. Resource
79
79
 
80
- | 字段 | 状态 | 类型 | 描述 | 备注 |
81
- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------ | ----------- | ---------------------------------------------- |
82
- | `resource.service.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 服务 | -- |
83
- | `resource.service.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 版本 | -- |
84
- | [`resource.deployment.environment.name`](https://opentelemetry.io/docs/specs/semconv/resource/deployment-environment/) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 环境 | 如 `development`、`production`、`staging`、`test`。 |
85
- | `resource.session.sample_rate` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 会话采样率 | 取值范围为 `0`~`1`。 |
86
- | `resource.telemetry.sdk.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | SDK 版本 | -- |
87
- | [`resource.telemetry.sdk.language`](https://opentelemetry.io/docs/specs/semconv/resource/#telemetry-sdk) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | SDK 语言 | `webjs`。 |
88
- | `resource.telemetry.sdk.name` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | SDK 名称 | -- |
89
- | `resource.device.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 设备类型 | 当前仅为 `desktop`、`mobile`。 |
90
- | `resource.user_agent.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 浏览器 | 通常指的是浏览器的名称,如 `Chrome`、`Edge`。 |
91
- | `resource.user_agent.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 浏览器版本 | 通常指的是浏览器的名称,如 `149`、`151`。 |
92
- | `resource.user_agent.os.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作系统 | 如 `macOS`、`Windows`、`Android`。 |
80
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
81
+ | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------ | ---------- | --------------------------------------------------- |
82
+ | `resource.service.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 服务 | -- |
83
+ | `resource.service.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 版本 | -- |
84
+ | [`resource.deployment.environment.name`](https://opentelemetry.io/docs/specs/semconv/resource/deployment-environment/) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 环境 | 如 `development`、`production`、`staging`、`test`。 |
85
+ | `resource.session.sample_rate` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 会话采样率 | 取值范围为 `0`~`1`。 |
86
+ | `resource.telemetry.sdk.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | SDK 版本 | -- |
87
+ | [`resource.telemetry.sdk.language`](https://opentelemetry.io/docs/specs/semconv/resource/#telemetry-sdk) | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | SDK 语言 | `webjs`。 |
88
+ | `resource.telemetry.sdk.name` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | SDK 名称 | -- |
89
+ | `resource.device.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 设备类型 | 当前仅为 `desktop`、`mobile`。 |
90
+ | `resource.user_agent.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 浏览器 | 通常指的是浏览器的名称,如 `Chrome`、`Edge`。 |
91
+ | `resource.user_agent.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 浏览器版本 | 通常指的是浏览器的名称,如 `149`、`151`。 |
92
+ | `resource.user_agent.os.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作系统 | 如 `macOS`、`Windows`、`Android`。 |
93
93
 
94
94
  **[1] `resource.telemetry.sdk.name`**:当前浏览器 SDK 固定为 `blueking`。Aegis 等其他生产端可使用各自名称,不要把 npm 包名 `@blueking/open-telemetry` 当作该字段值。
95
95
 
96
96
  ### c. Status
97
97
 
98
- | 字段 | 状态 | 类型 | 描述 | 备注 |
99
- | ---------------- | ---------------------------------------------------------- | --- | ---- | ---------------------------- |
100
- | `status.code` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 状态码 | 0(未设置)<br />1(正常)<br />2(异常) |
101
- | `status.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 状态描述 | 如 `Failed to fetch` |
98
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
99
+ | ---------------- | ---------------------------------------------------------- | ---- | -------- | ----------------------------------------- |
100
+ | `status.code` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 状态码 | 0(未设置)<br />1(正常)<br />2(异常) |
101
+ | `status.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 状态描述 | 如 `Failed to fetch` |
102
102
 
103
103
  ### d. Event
104
104
 
105
- | 字段 | 状态 | 类型 | 描述 | 备注 |
106
- | ----------------------------------------------------------------------- | ---------------------------------------------------------- | ------ | ------------- | -------------------- |
107
- | `events[].name` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 事件 | |
108
- | `events[].timestamp` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 事件发生时间 | SDK 传输为 OTLP Event UnixNano;后端可转为微秒。 |
109
- | `events[].attributes.exception.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常类型 | 如 `TypeError`。 |
110
- | `events[].attributes.exception.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常消息 | 如 `Failed to fetch`。 |
111
- | `events[].attributes.exception.stacktrace` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常堆栈 | |
112
- | `events[].attributes.long_task.script.duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本耗时(ms) | |
113
- | `events[].attributes.long_task.script.execution_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本执行开始时间(ms) | |
114
- | `events[].attributes.long_task.script.forced_style_and_layout_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 强制样式与布局耗时(ms) | |
115
- | `events[].attributes.long_task.script.pause_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本暂停耗时(ms) | |
116
- | `events[].attributes.long_task.script.source_char_position` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 源码字符位置 | |
117
- | `events[].attributes.long_task.script.start_time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本开始时间(ms) | |
118
- | `events[].attributes.long_task.script.invoker` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本触发来源 | |
119
- | `events[].attributes.long_task.script.invoker_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本触发类型 | |
120
- | `events[].attributes.long_task.script.source_function_name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本函数名 | |
121
- | `events[].attributes.long_task.script.source_url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 已脱敏的脚本 URL | |
122
- | `events[].attributes.long_task.script.window_attribution` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本窗口关系 | |
105
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
106
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------- | ------ | ------------------------ | ------------------------------------------------ |
107
+ | `events[].name` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 事件 | |
108
+ | `events[].timestamp` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 事件发生时间 | SDK 传输为 OTLP Event UnixNano;后端可转为微秒。 |
109
+ | `events[].attributes.exception.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常类型 | 如 `TypeError`。 |
110
+ | `events[].attributes.exception.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常消息 | 如 `Failed to fetch`。 |
111
+ | `events[].attributes.exception.stacktrace` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 异常堆栈 | |
112
+ | `events[].attributes.long_task.script.duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本耗时(ms) | |
113
+ | `events[].attributes.long_task.script.execution_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本执行开始时间(ms) | |
114
+ | `events[].attributes.long_task.script.forced_style_and_layout_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 强制样式与布局耗时(ms) | |
115
+ | `events[].attributes.long_task.script.pause_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本暂停耗时(ms) | |
116
+ | `events[].attributes.long_task.script.source_char_position` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 源码字符位置 | |
117
+ | `events[].attributes.long_task.script.start_time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 脚本开始时间(ms) | |
118
+ | `events[].attributes.long_task.script.invoker` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本触发来源 | |
119
+ | `events[].attributes.long_task.script.invoker_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本触发类型 | |
120
+ | `events[].attributes.long_task.script.source_function_name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本函数名 | |
121
+ | `events[].attributes.long_task.script.source_url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 已脱敏的脚本 URL | |
122
+ | `events[].attributes.long_task.script.window_attribution` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 脚本窗口关系 | |
123
123
 
124
124
  **[1] `events[].name`**:「异常」需将事件名固定为 `exception`。
125
125
 
@@ -127,74 +127,71 @@ Session
127
127
 
128
128
  ### f. Link
129
129
 
130
- | 字段 | 状态 | 类型 | 描述 | 备注 |
131
- | ------------------ | -------------------------------------------------------------- | --- | ---------- | --- |
132
- | `links[].trace_id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 关联 TraceID | |
133
- | `links[].span_id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 关联 SpanID | |
134
-
135
- **[1] `links[].trace_id`**:`span_type=resource` 且 `resource.type` 为 `xhr` 或 `fetch`,并注入/探测到 Trace Header 时,把对应后端 Trace ID 记到 Link 上。
130
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
131
+ | ------------------ | -------------------------------------------------------------- | ---- | ------------ | ---- |
132
+ | `links[].trace_id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 关联 TraceID | |
133
+ | `links[].span_id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 关联 SpanID | |
136
134
 
135
+ **[1] `links[].trace_id`**:`span_type=resource` 且 `resource.type` 为 `xhr` 或 `fetch`,并生成或解析到合法 OTel trace context 时,把对应后端 Trace ID 记到 Link 上。
137
136
 
138
137
  ## 0x03 Attributes
139
138
 
140
139
  ### a. 基础字段
141
140
 
142
- | 字段 | 状态 | 类型 | 描述 | 备注 |
143
- | ---------------------------- | ---------------------------------------------------------- | ---- | ------- | ---------------------------------------------- |
144
- | `attributes.user.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 用户 ID | -- |
145
- | `attributes.span_type` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 事件类型 | -- |
146
- | `attributes.outcome.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 执行结果 | `success`、`warning`(警告)、`error`、`timeout`、`abort`。 |
147
-
141
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
142
+ | ---------------------------- | ---------------------------------------------------------- | ---- | -------- | ------------------------------------------------------------------------------------------------------------- |
143
+ | `attributes.user.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 用户 ID | -- |
144
+ | `attributes.span_type` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 事件类型 | -- |
145
+ | `attributes.outcome.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 执行结果 | `success`、`warning`(警告)、`error`、`timeout`、`abort`、`unknown`(Resource 无可用状态且无明确失败证据)。 |
148
146
 
149
147
  **[1] `attributes.span_type`**:
150
148
 
151
- | 值 | 描述 |
152
- | ----------- | -------------------- |
153
- | `session` | Session 创建、轮换或结束。 |
154
- | `view` | 页面首次加载或路由视图生命周期。 |
155
- | `resource` | 静态资源、Fetch 或 XHR 请求。 |
149
+ | 值 | 描述 |
150
+ | ----------- | -------------------------------- |
151
+ | `session` | Session 创建、轮换或结束。 |
152
+ | `view` | 页面首次加载或路由视图生命周期。 |
153
+ | `resource` | 静态资源、Fetch 或 XHR 请求。 |
156
154
  | `error` | 浏览器错误、白屏或 CSP 违规。 |
157
- | `vital` | Web 性能指标。 |
158
- | `long_task` | Long Task 或长动画帧。 |
159
- | `action` | 用户操作或主动上报的 Action。 |
160
- | `websocket` | WebSocket 生命周期事件。 |
161
- | `custom` | 主动上报的自定义事件。 |
155
+ | `vital` | Web 性能指标。 |
156
+ | `long_task` | Long Task 或长动画帧。 |
157
+ | `action` | 用户操作或主动上报的 Action。 |
158
+ | `websocket` | WebSocket 生命周期事件。 |
159
+ | `custom` | 主动上报的自定义事件。 |
162
160
 
163
161
  ### b. [error](https://opentelemetry.io/docs/specs/semconv/registry/attributes/error/)
164
162
 
165
-
166
- | 字段 | 状态 | 类型 | 描述 | 备注 |
167
- | ------------------------------- | ----------------------------------------------------------- | ------- | ---------- | -------------------------------------------------------------------- |
168
- | `attributes.error.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 错误信息 | -- |
169
- | `attributes.error.handled` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 错误是否被捕获 | -- |
170
- | `attributes.error.source` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 错误来源 | 枚举值:<br/>- window.error(脚本错误,固定值)<br/>- resource(资源加载错误)<br/>- unhandledrejection(未处理的 Promise 异常) |
171
- | `attributes.code.column` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 代码列号 | |
172
- | `attributes.code.filepath` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 代码文件路径 | |
173
- | `attributes.code.lineno` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 代码行号 | |
163
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
164
+ | -------------------------- | ---------------------------------------------------------- | ------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
165
+ | `attributes.error.message` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 错误信息 | -- |
166
+ | `attributes.error.handled` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 错误是否被捕获 | -- |
167
+ | `attributes.error.source` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 错误来源 | 枚举值:<br/>- window.error(脚本错误,固定值)<br/>- resource(资源加载错误)<br/>- unhandledrejection(未处理的 Promise 异常) |
168
+ | `attributes.code.column` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 代码列号 | |
169
+ | `attributes.code.filepath` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 代码文件路径 | |
170
+ | `attributes.code.lineno` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 代码行号 | |
174
171
 
175
172
  ### c. [browser](https://opentelemetry.io/docs/specs/semconv/registry/attributes/browser/)
176
173
 
177
- | 字段 | 状态 | 类型 | 描述 | 备注 |
178
- | ------------------------------------ | ---------------------------------------------------------- | --- | ------- | ---------------------------- |
179
- | `attributes.browser.screen.height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 屏幕尺寸的高度 | Aegis 使用 `sr = 1728 * 1117`。 |
180
- | `attributes.browser.screen.width` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 屏幕尺寸的宽度 | -- |
181
- | `attributes.browser.viewport.height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 可视区域高度 | Aegis 使用 `vp = 576 * 918`。 |
182
- | `attributes.browser.viewport.width` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 可视区域宽度 | -- |
174
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
175
+ | ------------------------------------ | ---------------------------------------------------------- | ---- | -------------- | ------------------------------- |
176
+ | `attributes.browser.screen.height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 屏幕尺寸的高度 | Aegis 使用 `sr = 1728 * 1117`。 |
177
+ | `attributes.browser.screen.width` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 屏幕尺寸的宽度 | -- |
178
+ | `attributes.browser.viewport.height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 可视区域高度 | Aegis 使用 `vp = 576 * 918`。 |
179
+ | `attributes.browser.viewport.width` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 可视区域宽度 | -- |
183
180
 
184
181
  ### d. [device](https://opentelemetry.io/docs/specs/semconv/registry/attributes/device/)
185
182
 
186
- | 字段 | 状态 | 类型 | 描述 | 备注 |
187
- | ---------------------- | ---------------------------------------------------------- | --- | ---- | ----------------------------------------- |
188
- | `attributes.device.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 设备标识 | 如 `fd136680-a37b-45ea-80ee-365bfdc7f82e`。 |
183
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
184
+ | ---------------------- | ---------------------------------------------------------- | ---- | -------- | ------------------------------------------- |
185
+ | `attributes.device.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 设备标识 | 如 `fd136680-a37b-45ea-80ee-365bfdc7f82e`。 |
189
186
 
190
187
  ### e. [network](https://opentelemetry.io/docs/specs/semconv/registry/attributes/network/)
191
188
 
192
- | 字段 | 状态 | 类型 | 描述 | 备注 |
193
- | ------------------------------------ | -------------------------------------------------------------- | ---- | ------- | ----------------------------------------------------------- |
194
- | `attributes.network.connection.type` | ![Development](https://img.shields.io/badge/-development-blue) | enum | 网络连接类型 | 直接使用浏览器 `navigator.connection.type` 的原始值;字段不存在时不上报。 |
195
- | `attributes.network.effective_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 网络质量 | -- |
196
- | `attributes.network.status` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 网络状态 | `connected`、`not_connected`。 |
197
- | `attributes.network.protocol.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 应用层协议 | 仅 WebSocket Span 上报,固定为 `websocket`;HTTP Resource Span 不上报。 |
189
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
190
+ | ------------------------------------ | -------------------------------------------------------------- | ---- | ------------ | ------------------------------------------------------------------------- |
191
+ | `attributes.network.connection.type` | ![Development](https://img.shields.io/badge/-development-blue) | enum | 网络连接类型 | 直接使用浏览器 `navigator.connection.type` 的原始值;字段不存在时不上报。 |
192
+ | `attributes.network.effective_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 网络质量 | -- |
193
+ | `attributes.network.status` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 网络状态 | `connected`、`not_connected`。 |
194
+ | `attributes.network.protocol.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 应用层协议 | 仅 WebSocket Span 上报,固定为 `websocket`;HTTP Resource Span 不上报。 |
198
195
 
199
196
  **[1] `attributes.network.connection.type`**:表示设备当前使用的物理网络连接方式。SDK 直接上报
200
197
  [`navigator.connection.type`](https://wicg.github.io/netinfo/#connectiontype-enum);浏览器不支持该 API
@@ -203,83 +200,94 @@ Session
203
200
  Aegis 将「连接类型」「网络质量」整合成 `netType`(`wifi`、`wired`、`2G`、`3G`、`5G`、`6G`),不推荐这种做法。
204
201
  转换 Aegis 数据时,`wifi` 保持不变,`wired` 映射为 `ethernet`,移动网络代际映射为 `cellular`。
205
202
 
206
- | 值 | 描述 | 备注 |
207
- | ---------- | -------- | --------------------------------------- |
203
+ | 值 | 描述 | 备注 |
204
+ | ----------- | ------------ | ------------------------------------------------ |
208
205
  | `bluetooth` | 蓝牙网络 | 通过蓝牙网络连接。 |
209
- | `cellular` | 蜂窝移动网络 | 不表示具体移动网络代际。 |
210
- | `ethernet` | 以太网 | Aegis 的 `wired` 映射为该值。 |
211
- | `mixed` | 混合连接 | 浏览器同时使用多种连接方式。 |
212
- | `none` | 无网络连接 | 通常与 `network.status=not_connected` 同时出现。 |
213
- | `other` | 其他连接方式 | 浏览器知道连接类型,但不属于已列出的类型。 |
214
- | `unknown` | 未知连接方式 | 已建立网络连接,但浏览器无法或不愿提供连接类型。 |
215
- | `wifi` | Wi-Fi 网络 | 仅表示通过 Wi-Fi 连接,不代表网络一定快。 |
216
- | `wimax` | WiMAX 网络 | 通过 WiMAX 连接。 |
206
+ | `cellular` | 蜂窝移动网络 | 不表示具体移动网络代际。 |
207
+ | `ethernet` | 以太网 | Aegis 的 `wired` 映射为该值。 |
208
+ | `mixed` | 混合连接 | 浏览器同时使用多种连接方式。 |
209
+ | `none` | 无网络连接 | 通常与 `network.status=not_connected` 同时出现。 |
210
+ | `other` | 其他连接方式 | 浏览器知道连接类型,但不属于已列出的类型。 |
211
+ | `unknown` | 未知连接方式 | 已建立网络连接,但浏览器无法或不愿提供连接类型。 |
212
+ | `wifi` | Wi-Fi 网络 | 仅表示通过 Wi-Fi 连接,不代表网络一定快。 |
213
+ | `wimax` | WiMAX 网络 | 通过 WiMAX 连接。 |
217
214
 
218
215
  **[2] `attributes.network.effective_type`**:表示浏览器根据延迟和下载速度估算出的实际网络质量,等同与 DataDog(`connectivity.effective_type`)、Aegis(`netType`)。
219
216
 
220
- | 值 | 描述 | 备注 |
221
- | --------- | ---- | -------------------------- |
222
- | `slow-2g` | 极慢 | 页面和图片加载非常慢,通常只能满足少量文本传输。 |
217
+ | 值 | 描述 | 备注 |
218
+ | --------- | ---- | ---------------------------------------------------- |
219
+ | `slow-2g` | 极慢 | 页面和图片加载非常慢,通常只能满足少量文本传输。 |
223
220
  | `2g` | 较慢 | 简单页面可以打开,图片、脚本和接口请求可能明显缓慢。 |
224
- | `3g` | 中等 | 普通网页基本可用,但大资源和复杂页面仍可能等待。 |
225
- | `4g` | 较快 | 延迟和带宽表现较好,适合大多数 Web 应用。 |
221
+ | `3g` | 中等 | 普通网页基本可用,但大资源和复杂页面仍可能等待。 |
222
+ | `4g` | 较快 | 延迟和带宽表现较好,适合大多数 Web 应用。 |
226
223
 
227
224
  ### f. session
228
225
 
229
- | 字段 | 状态 | 类型 | 描述 | 备注 |
230
- | ------------------------------------- | ----------------------------------------------------------- | ------- | -------- | ----------------------------------------------- |
231
- | `attributes.session.has_replay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 有无回放 | -- |
232
- | `attributes.session.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 会话 ID | -- |
233
- | `attributes.session.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 会话类型 | 当前固定为 `user`。 |
234
- | `attributes.session.phase` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 会话阶段 | -- |
226
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
227
+ | --------------------------------------- | -------------------------------------------------------------- | ------- | ---------------- | ---------------------------------------------- |
228
+ | `attributes.session.has_replay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 有无回放 | -- |
229
+ | `attributes.session.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 会话 ID | -- |
230
+ | `attributes.session.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 会话类型 | 当前固定为 `user`。 |
231
+ | `attributes.session.phase` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 会话阶段 | -- |
232
+ | `attributes.session.start_time` | ![Development](https://img.shields.io/badge/-development-blue) | number | 会话创建时间 | epoch 毫秒,续期不改变;接收侧兼容需联调。 |
233
+ | `attributes.session.last_activity_time` | ![Development](https://img.shields.io/badge/-development-blue) | number | 最后有效活动时间 | epoch 毫秒,后台请求不更新;接收侧兼容需联调。 |
234
+ | `attributes.tab.id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 标签页分组标识 | 与 Session/View 分开,不用于结束去重。 |
235
235
 
236
236
  **[1] `attributes.session.phase`**:
237
237
 
238
- | 值 | 描述 |
239
- | ------- | ---------------------- |
240
- | `start` | 创建首个 Session。 |
241
- | `rotate` | 旧 Session 到期后创建新 Session。 |
242
- | `end` | 当前 Session 结束。 |
238
+ | 值 | 描述 |
239
+ | -------- | --------------------------------------------------------------- |
240
+ | `start` | 创建首个 Session。 |
241
+ | `rotate` | 旧 Session 到期后创建新 Session。 |
242
+ | `end` | 共享状态提交者确认 Session 超时结束,使用旧 ID 和逻辑截止时间。 |
243
+
244
+ 生命周期 Span 为瞬时事件。多个 Tab 的本地 View 结束不等于多次 Session 结束;接收侧按应用隔离范围、Session ID 与 phase 幂等处理,并允许网络重试或缺少 end。
243
245
 
244
246
  ### g. view
245
247
 
246
- | 字段 | 状态 | 类型 | 描述 | 备注 |
247
- | ------------------------------------- | -------------------------------------------------------------- | ------ | ----------------------- | --------------------------------------------- |
248
- | `attributes.view.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 ID | |
249
- | `attributes.view.name` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面名称 | 如 `/apm/home`。 |
250
- | `attributes.view.loading_type` *[2]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面加载类型 | -- |
251
- | `attributes.view.url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 URL | 如 `https://example.com/cur`。 |
252
- | `attributes.view.previous` | ![Development](https://img.shields.io/badge/-development-blue) | str | 上一页面 URL | 如 `https://example.com/pre`。 |
253
- | `attributes.view.previous_url_template` | ![Development](https://img.shields.io/badge/-development-blue) | str | 上一个页面 | 与 `view.url_template` 使用同一规则;初始 View 为空字符串。 |
254
- | `attributes.view.referrer` | ![Development](https://img.shields.io/badge/-development-blue) | str | 初始来源 URL | 仅首次加载且值非空时上报,需进行 URL 脱敏。 |
255
- | `attributes.view.url_template` *[3]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 | 如 `/apm/home`。 |
256
- | `attributes.view.loading_time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面加载耗时(ms) | 加载时间计算完成后上报。 |
257
- | `attributes.view.loading_time_source` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 页面加载计时方式 | `auto`、`manual`。 |
258
- | `attributes.view.first_byte` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面首字节耗时(ms) | 仅初始导航存在。 |
259
- | `attributes.view.dom_interactive` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DOM 可交互时间(ms) | 仅初始导航存在。 |
260
- | `attributes.view.dom_content_loaded` | ![Stable\|43](https://img.shields.io/badge/-stable-lightgreen) | number | DOMContentLoaded 时间(ms) | 仅初始导航存在。 |
261
- | `attributes.view.dom_complete` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DOM 完成时间(ms) | 仅初始导航存在。 |
262
- | `attributes.view.load_event` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | Load 事件时间(ms) | 仅初始导航存在。 |
263
- | `attributes.view.phase` *[4]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 页面阶段 | 枚举值:<br>- start<br>- update<br>- end |
264
- | `attributes.view.started_at` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面开始时间(ms) | 初始 View 取 `performance.timeOrigin`(epoch ms);后续 View 取创建时刻。 |
265
- | `attributes.view.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 页面快照版本 | 同一 `attributes.view.id` 从 `1` 开始递增,用于排序和幂等合并。 |
266
- | `attributes.view.end_reason` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面结束原因 | -- |
248
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
249
+ | --------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------- |
250
+ | `attributes.view.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 ID | |
251
+ | `attributes.view.name` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面名称 | 如 `/apm/home`。 |
252
+ | `attributes.view.loading_type` _[2]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面加载类型 | -- |
253
+ | `attributes.view.url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 URL | 如 `https://example.com/cur`。 |
254
+ | `attributes.view.previous` | ![Development](https://img.shields.io/badge/-development-blue) | str | 上一页面 URL | 如 `https://example.com/pre`。 |
255
+ | `attributes.view.previous_url_template` | ![Development](https://img.shields.io/badge/-development-blue) | str | 上一个页面 | 与 `view.url_template` 使用同一规则;初始 View 为空字符串。 |
256
+ | `attributes.view.referrer` | ![Development](https://img.shields.io/badge/-development-blue) | str | 初始来源 URL | 仅首次加载且值非空时上报,需进行 URL 脱敏。 |
257
+ | `attributes.view.url_template` _[3]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面 | 如 `/apm/home`。 |
258
+ | `attributes.view.loading_time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面加载耗时(ms) | 加载时间计算完成后上报。 |
259
+ | `attributes.view.loading_time_source` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 页面加载计时方式 | `auto`、`manual`。 |
260
+ | `attributes.view.first_byte` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面首字节耗时(ms) | 仅初始导航存在。 |
261
+ | `attributes.view.dom_interactive` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DOM 可交互时间(ms) | 仅初始导航存在。 |
262
+ | `attributes.view.dom_content_loaded` | ![Stable | 43](https://img.shields.io/badge/-stable-lightgreen) | number | DOMContentLoaded 时间(ms) | 仅初始导航存在。 |
263
+ | `attributes.view.dom_complete` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DOM 完成时间(ms) | 仅初始导航存在。 |
264
+ | `attributes.view.load_event` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | Load 事件时间(ms) | 仅初始导航存在。 |
265
+ | `attributes.view.phase` _[4]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 页面阶段 | 枚举值:<br>- start<br>- update<br>- end |
266
+ | `attributes.view.started_at` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 页面开始时间(ms) | 仅合法的初始 View 回溯到 `performance.timeOrigin`(epoch ms);不得早于所属 Session 的有效区间;其他 View 取创建或恢复时刻。 |
267
+ | `attributes.view.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 页面快照版本 | 同一 `attributes.view.id` 从 `1` 开始递增,用于排序和幂等合并。 |
268
+ | `attributes.view.end_reason` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 页面结束原因 | -- |
269
+ | `attributes.view.time_spent` | ![Development](https://img.shields.io/badge/-development-blue) | number | 累计停留时长(ms) | 当前快照时刻减 started_at,包含后台时间。 |
270
+ | `attributes.view.foreground_time` | ![Development](https://img.shields.io/badge/-development-blue) | number | 累计前台时长(ms) | 仅累加 SDK 已观察到的 active/passive 区间。 |
271
+ | `attributes.view.is_active` | ![Development](https://img.shields.io/badge/-development-blue) | bool | View 尚未结束 | 不是页面可见性;end 为 false。 |
272
+ | `attributes.view.page_states` | ![Development](https://img.shields.io/badge/-development-blue) | str | 页面状态 JSON | 最多 100 项;state 为 active/passive/hidden/frozen,start 为相对 View 起点的 ms。 |
273
+ | `attributes.view.custom_timings.<name>` | ![Development](https://img.shields.io/badge/-development-blue) | number | 业务耗时(ms) | 相对当前 View 起点;同名更新,最多 100 项。 |
267
274
 
268
275
  **[1] `attributes.view.name`**:优先使用 `startView({ name })` 或 `setViewName()` 设置的名称;未显式设置时,默认取 `attributes.view.url_template`。
269
276
 
270
277
  **[2] `attributes.view.loading_type`**:
271
278
 
272
- | 值 | 描述 |
273
- | ----------------- | --------------- |
274
- | `initial_load` | 初始加载 |
275
- | `route_change` | 路由切换 |
276
- | `session_renewal` | 会话续期后重建 |
279
+ | 值 | 描述 |
280
+ | ----------------- | ---------------- |
281
+ | `initial_load` | 初始加载 |
282
+ | `route_change` | 路由切换 |
283
+ | `session_renewal` | 会话续期后重建 |
277
284
  | `bf_cache` | 前进后退缓存恢复 |
278
285
 
279
- **[3] `attributes.view.url_template`**:用于聚合的页面路径。默认把数字 ID、UUID 和长十六进制段替换为 `:id`,也可由 `tracking.view.getUrlTemplate` 自定义。
286
+ **[3] `attributes.view.url_template`**:用于聚合的页面路径。Hash 模式取逻辑路由路径,History/document 取 pathname;默认把数字 ID、UUID 和长十六进制段替换为 `:id`。显式 `startView({ urlTemplate })` 优先于 `tracking.view.getUrlTemplate`,可由 Router matched 路由提供准确模板。query-only 变化只更新 URL 上下文,不建立新 View;URL 本身仍经过隐私脱敏。
280
287
 
281
288
  **[4] `attributes.view.phase`**:当前 View Span 的生命周期阶段,Schema v3 不再用一条长 Span 表达整个 View,而是发送多条瞬时生命周期 Span。
282
289
 
290
+ 除 Loading Time、名称与上下文变化外,每 60 秒、flush、页面隐藏和冻结也会产生 update 检查点。接收端按应用、Session、View ID 及 version 合并,累计时长与自定义 timing 取最新版本,不对多份快照求和;缺失 end 时最新检查点只提供已观察下界。检查点不更新 Session 用户活动时间。以下三条 Span 是简化示例,实际 update 可以有多条。
283
291
 
284
292
  ```text
285
293
  逻辑 View:view.id=view-A
@@ -312,7 +320,7 @@ Aegis 将「连接类型」「网络质量」整合成 `netType`(`wifi`、`wir
312
320
  │ └── 页面请求、资源和 DOM 活动结束
313
321
  │
314
322
  │ 然后重新读取 PerformanceNavigationTiming,
315
- │ 将六个字段一起放入 update Span。
323
+ │ 将导航字段、timing.* 和 Loading Time 一起放入 update Span。
316
324
  │
317
325
  └── Span #3:version=3,phase=end
318
326
  │
@@ -324,11 +332,10 @@ Aegis 将「连接类型」「网络质量」整合成 `netType`(`wifi`、`wir
324
332
  ├── view.dom_complete = 680
325
333
  └── view.load_event = 700
326
334
 
327
- end Span 不会重新计算这些字段,
328
- 只是携带 View 当前的最终属性快照。
335
+ end 前补读初始导航已产生的时间点,再携带最终属性快照。
336
+ view.loading_time 沿用 update 时的值。
329
337
  ```
330
338
 
331
-
332
339
  ```text
333
340
  时间 ───────────────────────────────────────────────────────────>
334
341
 
@@ -343,75 +350,82 @@ View B █████████████
343
350
 
344
351
  ### h. resource
345
352
 
346
- | 字段 | 状态 | 类型 | 描述 | 备注 |
347
- | -------------------------------------------- | ---------------------------------------------------------- | ------- | ------------------- | ----------------------------------------------------------------------- |
348
- | `attributes.resource.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 资源类型 | -- |
349
- | `attributes.resource.size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 资源大小 | -- |
350
- | `attributes.resource.transfer_size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 传输大小 | -- |
351
- | `attributes.resource.decoded_body_size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 解压后大小 | -- |
352
- | `attributes.resource.encoded_body_size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 压缩后大小 | -- |
353
- | `attributes.resource.protocol` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源协议 | 浏览器提供下一跳协议时存在,如 `h2`、`h3`、`http/1.1`。 |
354
- | `attributes.resource.cache.hit` *[3]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 缓存命中 | 命中时为 `true`,未命中或无法判断时不写入。 |
355
- | `attributes.resource.delivery_type` *[4]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源获取方式 | 浏览器返回非空值时存在。 |
356
- | `attributes.resource.render_blocking_status` *[5]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 渲染阻塞状态 | 浏览器支持该字段时存在。 |
357
- | `attributes.resource.redirect.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 重定向开始时间 | 可由 `redirectStart - startTime` 得到。 |
358
- | `attributes.resource.redirect.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 重定向耗时 | 可由 `redirectEnd - redirectStart` 得到。 |
359
- | `attributes.resource.worker.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | Service Worker 开始时间 | 可由 `workerStart - startTime` 得到。 |
360
- | `attributes.resource.worker.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | Service Worker 耗时 | 可由 `fetchStart - workerStart` 得到。 |
361
- | `attributes.resource.dns.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | DNS 解析开始时间 | 可由 `domainLookupStart - startTime` 得到。 |
362
- | `attributes.resource.dns.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | DNS 解析耗时 | 可由 `domainLookupEnd - domainLookupStart` 得到。 |
363
- | `attributes.resource.connect.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 连接开始时间 | 可由 `connectStart - startTime` 得到。 |
364
- | `attributes.resource.connect.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 连接耗时(含 TLS) | 可由 `connectEnd - connectStart` 得到。 |
365
- | `attributes.resource.ssl.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | TLS 握手开始时间 | 可由 `secureConnectionStart - startTime` 得到。 |
366
- | `attributes.resource.ssl.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | TLS 握手耗时 | 可由 `connectEnd - secureConnectionStart` 得到。 |
367
- | `attributes.resource.first_byte.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 首字节等待开始时间 | 可由 `requestStart - startTime` 得到。 |
368
- | `attributes.resource.first_byte.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 首字节等待耗时 | 可由 `responseStart - requestStart` 得到。 |
369
- | `attributes.resource.download.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 内容下载开始时间 | 可由 `responseStart - startTime` 得到。 |
370
- | `attributes.resource.download.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 内容下载耗时 | 可由 `responseEnd - responseStart` 得到。 |
371
- | `attributes.resource.timing.start_time` | ![Development](https://img.shields.io/badge/-development-blue) | number | 资源开始时间 | 与 `responseEnd` 计算总耗时;也是阶段偏移基准。 |
372
- | `attributes.resource.timing.redirect_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向开始时间 | 与 `redirectEnd` 计算可见重定向链耗时。 |
373
- | `attributes.resource.timing.redirect_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向结束时间 | -- |
374
- | `attributes.resource.timing.fetch_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 最后一跳获取开始时间 | 划分重定向后的前置等待。 |
375
- | `attributes.resource.timing.worker_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 介入时间 | 标记 Service Worker 参与,不代表实际执行耗时。 |
376
- | `attributes.resource.timing.worker_router_evaluation_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 路由评估时间 | 标记静态路由评估。 |
377
- | `attributes.resource.timing.worker_cache_lookup_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 缓存查询时间 | 标记缓存查询,不代表命中。 |
378
- | `attributes.resource.timing.domain_lookup_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询开始时间 | 与 `domainLookupEnd` 计算 DNS 耗时。 |
379
- | `attributes.resource.timing.domain_lookup_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询结束时间 | -- |
380
- | `attributes.resource.timing.connect_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接开始时间 | 与 `connectEnd` 计算连接耗时(含 TLS)。 |
381
- | `attributes.resource.timing.secure_connection_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | TLS 开始时间 | 与 `connectEnd` 计算 TLS 耗时。 |
382
- | `attributes.resource.timing.connect_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接完成时间 | -- |
383
- | `attributes.resource.timing.request_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 请求开始时间 | 与 `responseStart` 计算等待首个响应的耗时。 |
384
- | `attributes.resource.timing.response_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 首个响应时间 | 早于 `finalResponseHeadersStart` 时可识别 1xx;相等或最终响应头缺失,不能排除 1xx。 |
385
- | `attributes.resource.timing.final_response_headers_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 最终响应头时间 | 与 `responseEnd` 计算最终响应交付耗时。 |
386
- | `attributes.resource.timing.response_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 响应结束时间 | -- |
387
- | `attributes.resource.timing.worker_matched_router_source` | ![Development](https://img.shields.io/badge/-development-blue) | str | Service Worker 命中来源 | 用于区分路由命中路径,可能不是最终来源。 |
388
- | `attributes.resource.timing.worker_final_router_source` | ![Development](https://img.shields.io/badge/-development-blue) | str | Service Worker 最终来源 | 用于确定最终交付路径。 |
353
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
354
+ | ----------------------------------------------------------- | -------------------------------------------------------------- | ------- | --------------------------- | ------------------------------------------------------------------------------------------------- |
355
+ | `attributes.resource.initiator_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 原始发起方式 | PerformanceResourceTiming.initiatorType。 |
356
+ | `attributes.resource.type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 资源类型 | -- |
357
+ | `attributes.resource.size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 资源大小 | -- |
358
+ | `attributes.resource.transfer_size` _[6]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 传输大小 | -- |
359
+ | `attributes.resource.decoded_body_size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 解压后大小 | -- |
360
+ | `attributes.resource.encoded_body_size` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 压缩后大小 | -- |
361
+ | `attributes.resource.timing.incomplete` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | Timing 补全状态 | Fetch/XHR 回退时为 `true`;耗时可能只到响应头或终止事件,不能视作完整下载耗时。匹配成功时不写入。 |
362
+ | `attributes.resource.protocol` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源协议 | 浏览器提供下一跳协议时存在,如 `h2`、`h3`、`http/1.1`。 |
363
+ | `attributes.resource.cache.hit` _[3]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | boolean | 缓存命中 | 确认 HTTP 缓存命中时为 `true`;缺失表示无法确认,不能按 `false` 统计。 |
364
+ | `attributes.resource.delivery_type` _[4]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源获取方式 | 浏览器支持时存在;空字符串归一为 `other`,不支持时省略。 |
365
+ | `attributes.resource.render_blocking_status` _[5]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 渲染阻塞状态 | 浏览器支持该字段时存在。 |
366
+ | `attributes.resource.redirect.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 重定向开始时间 | 可由 `redirectStart - startTime` 得到。 |
367
+ | `attributes.resource.redirect.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 重定向耗时 | 可由 `redirectEnd - redirectStart` 得到。 |
368
+ | `attributes.resource.worker.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | Service Worker 开始时间 | 可由 `workerStart - startTime` 得到。 |
369
+ | `attributes.resource.worker.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | Service Worker 耗时 | 可由 `fetchStart - workerStart` 得到。 |
370
+ | `attributes.resource.dns.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | DNS 解析开始时间 | 可由 `domainLookupStart - startTime` 得到。 |
371
+ | `attributes.resource.dns.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | DNS 解析耗时 | 可由 `domainLookupEnd - domainLookupStart` 得到。 |
372
+ | `attributes.resource.connect.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 连接开始时间 | 可由 `connectStart - startTime` 得到。 |
373
+ | `attributes.resource.connect.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 连接耗时(含 TLS) | 可由 `connectEnd - connectStart` 得到。 |
374
+ | `attributes.resource.ssl.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | TLS 握手开始时间 | 可由 `secureConnectionStart - startTime` 得到。 |
375
+ | `attributes.resource.ssl.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | TLS 握手耗时 | 可由 `connectEnd - secureConnectionStart` 得到。 |
376
+ | `attributes.resource.first_byte.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 首字节等待开始时间 | 可由 `requestStart - startTime` 得到。 |
377
+ | `attributes.resource.first_byte.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 首字节等待耗时 | 可由 `responseStart - requestStart` 得到。 |
378
+ | `attributes.resource.download.start` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 内容下载开始时间 | 可由 `responseStart - startTime` 得到。 |
379
+ | `attributes.resource.download.duration` | ![Deprecated](https://img.shields.io/badge/-deprecated-red) | number | 内容下载耗时 | 可由 `responseEnd - responseStart` 得到。 |
380
+ | `attributes.resource.timing.start_time` | ![Development](https://img.shields.io/badge/-development-blue) | number | 资源开始时间 | 与 `responseEnd` 计算总耗时;也是阶段偏移基准。 |
381
+ | `attributes.resource.timing.redirect_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向开始时间 | 与 `redirectEnd` 计算可见重定向链耗时。 |
382
+ | `attributes.resource.timing.redirect_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向结束时间 | -- |
383
+ | `attributes.resource.timing.fetch_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 最后一跳获取开始时间 | 划分重定向后的前置等待。 |
384
+ | `attributes.resource.timing.worker_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 介入时间 | 标记 Service Worker 参与,不代表实际执行耗时。 |
385
+ | `attributes.resource.timing.worker_router_evaluation_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 路由评估时间 | 标记静态路由评估。 |
386
+ | `attributes.resource.timing.worker_cache_lookup_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 缓存查询时间 | 标记缓存查询,不代表命中。 |
387
+ | `attributes.resource.timing.domain_lookup_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询开始时间 | 与 `domainLookupEnd` 计算 DNS 耗时。 |
388
+ | `attributes.resource.timing.domain_lookup_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询结束时间 | -- |
389
+ | `attributes.resource.timing.connect_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接开始时间 | 与 `connectEnd` 计算连接耗时(含 TLS)。 |
390
+ | `attributes.resource.timing.secure_connection_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | TLS 开始时间 | 与 `connectEnd` 计算 TLS 耗时。 |
391
+ | `attributes.resource.timing.connect_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接完成时间 | -- |
392
+ | `attributes.resource.timing.request_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 请求开始时间 | 与 `responseStart` 计算等待首个响应的耗时。 |
393
+ | `attributes.resource.timing.response_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 首个响应时间 | 早于 `finalResponseHeadersStart` 时可识别 1xx;相等或最终响应头缺失,不能排除 1xx。 |
394
+ | `attributes.resource.timing.final_response_headers_start` | ![Development](https://img.shields.io/badge/-development-blue) | number | 最终响应头时间 | 与 `responseEnd` 计算最终响应交付耗时。 |
395
+ | `attributes.resource.timing.response_end` | ![Development](https://img.shields.io/badge/-development-blue) | number | 响应结束时间 | -- |
396
+ | `attributes.resource.timing.worker_matched_router_source` | ![Development](https://img.shields.io/badge/-development-blue) | str | Service Worker 命中来源 | 用于区分路由命中路径,可能不是最终来源。 |
397
+ | `attributes.resource.timing.worker_final_router_source` | ![Development](https://img.shields.io/badge/-development-blue) | str | Service Worker 最终来源 | 用于确定最终交付路径。 |
389
398
 
390
399
  **[1] `attributes.resource.type`**:
391
400
 
392
- | 值 | 描述 |
393
- | ------------------ | -------------------------------------------- |
394
- | `fetch` | Fetch 请求。 |
395
- | `xhr` | XHR 请求。 |
396
- | `script` | 脚本加载:`<script>`、模块或 Worker 加载的脚本资源。 |
397
- | `link` | Link 标签加载:`<link>` 加载的资源,如样式表、预加载和预取资源。 |
398
- | `img` / `image` | 图片:HTML 或 SVG 图片元素加载的资源。 |
399
- | `css` | CSS 规则加载:CSS `url()`、`@import` 等规则加载的资源,不表示 CSS 文件本身。 |
400
- | `iframe` / `frame` | 内嵌页面加载的文档资源。 |
401
- | `other` | 其他:浏览器未识别发起方式、`initiatorType` 为空或未单列的其他类型。 |
402
- | ... | .. |
401
+ | 值 | 描述 |
402
+ | --- | --- |
403
+ | `fetch` / `xhr` | API 请求。 |
404
+ | `document` | 文档类型,例如 frame/iframe 发起的资源;不表示已单独采集初始 HTML。 |
405
+ | `js` / `css` | 脚本与样式文件。 |
406
+ | `image` / `font` / `media` | 图片、字体和音视频。 |
407
+ | `beacon` | Beacon 请求,方法为 POST。 |
408
+ | `other` | 无法确认的资源类型。 |
409
+
410
+ `attributes.resource.initiator_type` 单独保留浏览器原始发起方式;例如 CSS 发起图片请求时,type 为 image,initiator_type 为 css。Timing-only 资源无法确认 HTTP method 时省略该字段。
403
411
 
404
412
  **[2] 单位**:`xx_size` 为 bytes,`duration` & `start` 为毫秒。
405
413
 
406
414
  **[3] `attributes.resource.cache.hit`**
407
415
 
408
- 满足任一条件时,SDK 写入 `true`:
416
+ 表示 SDK 能确认资源使用了 HTTP 缓存,包括网络校验后复用正文的协商缓存。SDK 按下表从上到下判断,命中一行后不再继续:
409
417
 
410
- | 条件 | 结果 |
411
- | --- | --- |
412
- | `deliveryType=cache` | `true` |
413
- | `transferSize=0 && decodedBodySize>0` | `true` |
414
- | 其他 | 不写入,不写 `false` |
418
+ | 条件 | 结果 |
419
+ | --------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
420
+ | `workerStart>0`、`workerRouterEvaluationStart>0`、`workerCacheLookupStart>0`,或 `workerMatchedRouterSource` / `workerFinalRouterSource` 非空 | 不写入 |
421
+ | `deliveryType=cache` | `true` |
422
+ | 其他非空 `deliveryType`,包括 `cache-storage`、`navigational-prefetch` 和未知值 | 不写入 |
423
+ | `deliveryType` 为空或未提供,且 `transferSize=0 && decodedBodySize>0 && requestStart>0 && responseStart>0` | `true` |
424
+ | 其他 | 不写入 |
425
+
426
+ SDK 读取 SW 来源时优先使用规范名 `workerMatchedRouterSource` / `workerFinalRouterSource`,不可用时读取浏览器的 `workerMatchedSourceType` / `workerFinalSourceType`,统一写入协议中的 `*_router_source` 字段。
427
+
428
+ 字段缺失表示“无法确认 HTTP 缓存命中”,不代表未使用缓存。Service Worker 参与的请求即使实际复用了 HTTP 缓存,也按此保守规则不确认命中。
415
429
 
416
430
  ETag(实体标签)是服务器提供的资源版本标识。浏览器按以下流程校验缓存:
417
431
 
@@ -423,128 +437,199 @@ ETag(实体标签)是服务器提供的资源版本标识。浏览器按以
423
437
 
424
438
  **[4] `attributes.resource.delivery_type`**:
425
439
 
426
- | 常见值 | 描述 |
427
- | ----------------------- | ---------------------------------------------------------- |
428
- | `cache` | 由浏览器 HTTP 缓存交付,包括本地缓存和网络校验缓存。 |
429
- | `navigational-prefetch` | 由导航预取缓冲区交付。 |
440
+ | 常见值 | 描述 |
441
+ | ----------------------- | ------------------------------------------------------------------------- |
442
+ | `cache` | 由浏览器 HTTP 缓存交付,包括本地缓存和网络校验缓存。 |
443
+ | `other` | 浏览器返回空交付类型;不能据此确认是否使用缓存。 |
444
+ | `navigational-prefetch` | 由导航预取缓冲区交付。 |
430
445
  | `cache-storage` | 由 Cache Storage 交付,包括 Service Worker Fetch Handler 和静态路由命中。 |
431
446
 
432
447
  规范来源:[Resource Timing](https://www.w3.org/TR/resource-timing/)、[Prefetch](https://wicg.github.io/nav-speculation/prefetch.html)、[Chromium Cache Storage Timing](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/experiments/service-worker-static-routing-api-timing-info.md)。
433
448
 
434
- SDK 原样上报浏览器返回的非空值,空值不写入。
449
+ SDK 原样上报浏览器返回的非空值,空字符串归一为 `other`,浏览器不支持时不写入。`other` 不代表明确未命中缓存。
435
450
 
436
451
  **[5] `attributes.resource.render_blocking_status`**:
437
452
 
438
- | 值 | 描述 |
439
- | -------------- | ----------- |
453
+ | 值 | 描述 |
454
+ | -------------- | -------------- |
440
455
  | `blocking` | 可能阻塞渲染。 |
441
- | `non-blocking` | 不阻塞渲染。 |
456
+ | `non-blocking` | 不阻塞渲染。 |
442
457
 
443
458
  取值定义见 [Resource Timing](https://www.w3.org/TR/resource-timing/)。浏览器不支持该字段时,SDK 不写入。
444
459
 
445
- ### i. action
460
+ **[6] `attributes.resource.transfer_size`**:
461
+
462
+ 这是浏览器按规范返回的传输大小,响应头部分使用固定 `300` 字节估值,不是抓包得到的精确网络流量。字段是否可见还受浏览器实现和 Timing-Allow-Origin 影响。
463
+
464
+ 根据 [Resource Timing 的 `transferSize` 定义](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-transfersize),浏览器按以下规则返回值:
446
465
 
447
- | 字段 | 状态 | 类型 | 描述 |
448
- | ------------------------------------------ | ---------------------------------------------------------- | ----- | ------ |
449
- | `attributes.action.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作 ID |
450
- | `attributes.action.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 可读的低基数动作名称,也是 `span_name` |
451
- | `attributes.action.type` *[2]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作类型 |
452
- | `attributes.action.target.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作元素 |
453
- | `attributes.action.target.tag` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作元素标签 |
454
- | `attributes.action.frustration.type` *[3]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str[] | 异常点击类型 |
466
+ | 缓存模式 | 返回值 |
467
+ | --------------------------------- | ------------------------------------------------- |
468
+ | `local`:直接使用本地缓存 | `0` |
469
+ | `validated`:经网络校验后复用缓存 | `300` |
470
+ | 其他情况 | 编码后的响应正文大小(`encodedBodySize`)加 `300` |
455
471
 
472
+ 其中,`300` 是规范用于替代实际 HTTP 响应头总字节数的固定值,避免通过响应头大小推断某些 Cookie 是否存在,详见 [隐私问题讨论](https://github.com/w3c/resource-timing/issues/238)。
473
+
474
+ ### i. action
456
475
 
457
- **[1] `attributes.action.loading_time`**:当前浏览器 SDK 不写该 Attribute。有页面活动时,用 Span 起止时间(后端 `elapsed_time`)表达持续时长。
476
+ | 字段 | 状态 | 类型 | 描述 |
477
+ | ------------------------------------------ | -------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------- |
478
+ | `attributes.action.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | Action 自身的操作 ID;不用于子事件关联 |
479
+ | `attributes.action.ids` | ![Development](https://img.shields.io/badge/-development-blue) | str[] | Resource/Error/Long Task 关联的全部 Action ID;无关联时不写 |
480
+ | `attributes.action.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 可读的低基数动作名称,也是 `span_name` |
481
+ | `attributes.action.type` _[2]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作类型 |
482
+ | `attributes.action.target.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作元素 |
483
+ | `attributes.action.target.tag` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 操作元素标签 |
484
+ | `attributes.action.target.selector` | ![Development](https://img.shields.io/badge/-development-blue) | str | 自动点击目标唯一定位结果,最长 512 字符;稳定属性/ID 优先,结构回退,Shadow 边界为非标准 CSS 的 `::shadow` |
485
+ | `attributes.action.target.path` | ![Development](https://img.shields.io/badge/-development-blue) | str[] | 自动点击 composedPath 中 Element 的 selector,目标到祖先最多 10 项、总长 2048 字符 |
486
+ | `attributes.action.target.width` | ![Development](https://img.shields.io/badge/-development-blue) | number | 自动点击目标宽度,CSS px |
487
+ | `attributes.action.target.height` | ![Development](https://img.shields.io/badge/-development-blue) | number | 自动点击目标高度,CSS px |
488
+ | `attributes.action.position.x` | ![Development](https://img.shields.io/badge/-development-blue) | number | 自动点击相对目标的横坐标,CSS px |
489
+ | `attributes.action.position.y` | ![Development](https://img.shields.io/badge/-development-blue) | number | 自动点击相对目标的纵坐标,CSS px |
490
+ | `attributes.action.name_source` | ![Development](https://img.shields.io/badge/-development-blue) | enum | 自动命名来源:`explicit`、`accessible_name`、`text`、`fallback` |
491
+ | `attributes.action.loading_time` _[1]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 正常页面稳定耗时,单位 ms;仅 `end_reason=activity_end` 时写入 |
492
+ | `attributes.action.end_reason` _[4]_ | ![Development](https://img.shields.io/badge/-development-blue) | enum | 自动 Action 结束观察的原因 |
493
+ | `attributes.action.frustration.type` _[3]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str[] | 异常点击类型 |
494
+
495
+ Action 自身的 `action.id` 始终为单字符串;Resource/Error/Long Task 只使用 `action.ids` 数组,不双写旧 `action.id`。逐 Action 记录有效区间及所属 Session/View,按子事件发生时间匹配全部关联;无 `span_type` 的通用 OpenTelemetry Span 不自动推测 Action 归属。View/Session 边界关闭自动 Action,已开始请求晚到结束仍保留原关联。计数 `action.error.count`、`action.resource.count`、`action.long_task.count` 由服务端派生,客户端不写。
496
+
497
+ 目标快照在 click 捕获时生成,不保证跨发布稳定,也不能还原浏览器未暴露的关闭 Shadow Root。名称默认使用 explicit 模式;text 模式不读取输入值或可编辑内容。`data-bk-privacy=mask` 阻止文本/可访问名称但允许显式业务标签;目标或祖先为 `data-bk-privacy=hidden` 或被隐藏时跳过整个 Action。selector/path 也遵循目标隐私规则:mask 下不采集 ID/test data 属性,只保留显式标签和结构。`aria-hidden` 仅过滤文本,不丢弃可见目标点击;键盘激活不填鼠标位置。无法在上限内唯一定位时省略,不截断为无效定位字符串。
498
+
499
+ **[1] `attributes.action.loading_time`**:单位为**毫秒**,与 `view.loading_time` 一致,与 OTLP Envelope 的纳秒时间戳区分。仅当已出现页面活动并正常稳定时写入,终点不包含尾部 100ms 安静等待。Error/Long Task 不延长页面加载窗口。无活动、超时或中断时缺失,不补 `0`;Span 起止时间(后端 `elapsed_time`)记录已观察区间,不能替代页面稳定结果。
458
500
 
459
501
  **[2] `attributes.action.type`**:
460
502
 
461
- | 常见值 | 描述 |
462
- | -------------------- | ---------------------------------- |
463
- | `click` | 鼠标或指针设备触发的点击,蓝鲸 Web 自动 Action 当前使用该值。 |
464
- | `custom` | 通过 `reportAction({ name })` 主动上报;Span 名使用 `action.name`。 |
465
- | `tap` | 触屏设备上的单次轻触。 |
466
- | `scroll` | 页面或滚动容器的滚动操作。 |
467
- | `swipe` | 触屏设备上的滑动手势。 |
468
- | `application_start` | 应用启动,常用于移动端或桌面端。 |
469
- | `back` | 返回上一页面或上一导航状态,常用于移动端。 |
503
+ | 常见值 | 描述 |
504
+ | ------------------- | ----------------------------------------------------------------------------------------------------- |
505
+ | `click` | 可见页面中的可信主键 click,包括浏览器由键盘激活控件产生的 click。蓝鲸 Web 自动 Action 当前使用该值。 |
506
+ | `custom` | 通过 `reportAction({ name })` 主动上报;Span 名使用 `action.name`。 |
507
+ | `tap` | 触屏设备上的单次轻触。 |
508
+ | `scroll` | 页面或滚动容器的滚动操作。 |
509
+ | `swipe` | 触屏设备上的滑动手势。 |
510
+ | `application_start` | 应用启动,常用于移动端或桌面端。 |
511
+ | `back` | 返回上一页面或上一导航状态,常用于移动端。 |
470
512
 
471
513
  以上是跨端常见值,不是封闭枚举。蓝鲸 Web 当前产生 `click` 和 `custom`。转换 Aegis 数据时,还可能保留接入方配置的 DOM 事件名。
472
514
 
473
515
  **[3] `attributes.action.frustration.type`**:
474
516
 
475
- | 值 | 描述 | 备注 |
476
- | ------------- | ---- | ------------------------------------------------------------------------------------ |
477
- | `rage_click` | 愤怒点击 | [a] `1 s` 内对同一 DOM 元素连续点击至少 `3` 次,且相邻点击距离不超过 `100 px`。<br />[b] 滚动或文本选择会中断或撤销判定。 |
478
- | `dead_click` | 无响应点击 | [a] 点击后未检测到请求、资源加载、长任务、DOM 变化、打开窗口或错误,也没有输入、滚动或文本选择。<br />[b] 链接、文本输入框等难以可靠判断的目标会排除。 |
479
- | `error_click` | 报错点击 | Action 生命周期内检测到前端错误。 |
517
+ | 值 | 描述 | 备注 |
518
+ | ------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
519
+ | `rage_click` | 愤怒点击 | [a] `1 s` 内对同一 DOM 元素连续点击至少 `3` 次,且相邻点击距离不超过 `100 px`。<br />[b] 滚动或文本选择会中断或撤销判定。 |
520
+ | `dead_click` | 无响应点击 | [a] 点击后未检测到请求、资源加载、DOM 变化或打开窗口,也没有输入、滚动或文本选择。<br />[b] 链接、文本输入框等难以可靠判断的目标会排除;Error/Long Task 不作为加载活动。 |
521
+ | `error_click` | 报错点击 | 通过采样和 beforeSend 等过滤进入 SDK 发送流,且 `action.ids` 包含该 Action 的前端错误。 |
480
522
 
481
523
  该字段为数组,同一个 Action 可以同时命中多个值;未命中时不写入。消费端应按集合处理,不依赖数组顺序。这些信号是 SDK 的启发式判断,不等同于业务操作失败。
482
524
 
525
+ Rage 当前仍保留三次独立 Action 各自标记,不合并、不输出挫败分组 ID。`reportAction()` 只产生瞬时动作,不建立关联窗口;持续型手动 Action API 不属于当前协议。
526
+
527
+ **[4] `attributes.action.end_reason`**:
528
+
529
+ | 值 | 含义 |
530
+ | ----------------- | ------------------------------------------- |
531
+ | `activity_end` | 有页面活动并正常稳定,允许写入 Loading Time |
532
+ | `no_activity` | 验证窗口内无页面活动 |
533
+ | `timeout` | 到达配置的最长观察时间 |
534
+ | `view_change` | 所属 View 结束或切换 |
535
+ | `session_expired` | 所属 Session 结束 |
536
+ | `page_hidden` | 页面切到后台 |
537
+ | `page_exit` | 页面退出 |
538
+ | `shutdown` | 插件停止 |
539
+
540
+ 该字段仅用于自动 Action。普通 flush 只发送已准备好的 Span,不强制结束观察或把它标记为加载完成。`outcome.type` 的无错误/挫败结果不代替该结束原因,也不表示业务成功。
541
+
483
542
  ### j. http & [url](https://opentelemetry.io/docs/specs/semconv/registry/attributes/url/) & server
484
543
 
485
- | 字段 | 状态 | 类型 | 描述 | |
486
- | -------------------------------------- | ---------------------------------------------------------- | --- | ------ | ---------------------------- |
487
- | `attributes.url.full` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 完整 URL | 如 `https://example.com/apm`。 |
488
- | `attributes.url.scheme` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | URL 协议 | 如 `ws`、`wss`。 |
489
- | `attributes.url.template` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源路径 | 如 `/api/users/`。 |
490
- | `attributes.http.request.method` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 请求方法 | Fetch/XHR 使用实际方法;其他 Resource 固定为 `GET`。 |
491
- | `attributes.http.response.status_code` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | HTTP 状态码 | 如 `200`、`404`。 |
492
- | `attributes.server.address` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 服务器地址 | 如 `example.com`。 |
493
- | `attributes.server.port` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 服务器端口 | -- |
544
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
545
+ | -------------------------------------- | ---------------------------------------------------------- | ---- | ----------- | ---------------------------------------------------- |
546
+ | `attributes.url.full` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 完整 URL | 如 `https://example.com/apm`。 |
547
+ | `attributes.url.scheme` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | URL 协议 | 如 `ws`、`wss`。 |
548
+ | `attributes.url.template` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 资源路径 | 如 `/api/users/`。 |
549
+ | `attributes.http.request.method` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 请求方法 | Fetch/XHR 使用实际方法;其他 Resource 固定为 `GET`。 |
550
+ | `attributes.http.response.status_code` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | HTTP 状态码 | 如 `200`、`404`。 |
551
+ | `attributes.server.address` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 服务器地址 | 如 `example.com`。 |
552
+ | `attributes.server.port` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 服务器端口 | -- |
494
553
 
495
554
  ### k. vital
496
555
 
497
- | 字段 | 状态 | 类型 | 描述 | 备注 |
498
- | --------------------------------------------- | ---------------------------------------------------------- | ------ | -------------------- | ------------------------------------ |
499
- | `attributes.vital.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 指标 ID | |
500
- | `attributes.vital.metric` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 指标 | |
501
- | `attributes.vital.value` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 指标值 | |
502
- | `attributes.vital.inp.input_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 输入延迟(ms) | 用户发起交互(如点击)到事件处理器开始执行的等待时间,反映主线程繁忙程度 |
503
- | `attributes.vital.inp.interaction_target` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 交互目标元素 | 如 `div`。 |
504
- | `attributes.vital.inp.interaction_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 交互类型 | -- |
505
- | `attributes.vital.inp.processing_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 交互处理耗时(ms) | -- |
506
- | `attributes.vital.inp.presentation_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 呈现延迟(ms) | -- |
507
- | `attributes.vital.lcp.target` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | LCP 元素选择器 | 如 `div`。 |
508
- | `attributes.vital.lcp.url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | LCP 资源 URL(已脱敏) | -- |
509
- | `attributes.vital.lcp.resource_load_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | LCP 资源加载耗时(ms) | -- |
510
- | `attributes.vital.lcp.element_render_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | LCP 元素渲染延迟(ms) | -- |
511
- | `attributes.vital.ttfb.waiting_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 请求准备耗时(ms) | -- |
512
- | `attributes.vital.ttfb.dns_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DNS 阶段耗时(ms) | -- |
513
- | `attributes.vital.ttfb.connection_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 连接耗时(含 TLS)(ms) | -- |
514
- | `attributes.vital.ttfb.request_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 请求阶段耗时(ms) | -- |
556
+ Vital 是可修订的瞬时指标快照。相同作用域中的同一指标保持 `vital.id`,快照变化时递增 `vital.version`。接收端按 ID 取最大版本后,再计算分布和跨 View 聚合;不能累加各版本 value 或将修订重复计为新样本。Span 时间为本次快照生成时刻,Session/View 关联使用原归属时间,没有 `vital.final` 字段。
557
+
558
+ `vital.scope=document` 表示文档 FCP/LCP/TTFB,固定关联文档初始 View,即使首次 paint 晚于 SPA 重定向也不改挂 route_change;`activation` 表示 BFCache 恢复指标,关联恢复 View;`view` 表示按逻辑 View 汇总的 CLS/INP。当前没有 Soft Navigation 指标采集。
559
+
560
+ 所属 View 活跃时每次快照刷新用户、View 名称及业务上下文,结束后冻结最终元数据;Session/View 身份不变。性能条目归属及 CLS/INP 相对时间使用 View 独立保存的相对起止时间,与 Performance API 共用时钟;epoch 时间仅用于上下文关联及 OTLP 时间戳。
561
+
562
+ 活跃 CLS/INP 变化及文档 LCP 候选更新通过约 3 秒合并检查点发布;flush、hidden、freeze、View 边界、shutdown 也可生成变化快照。检查点本身不结束 View 或为 Session 续期;后台任务节流及导出器批处理可能延迟实际发送。结束 View 的 CLS/INP 状态允许迟到修订 5 分钟,总保留状态最多 100 个;条目按 startTime 所在的半开区间归属,过期条目不会改挂当前 View。shutdown 先导出最后已观测的 LCP 等指标,再断开原生 observer、监听和待执行任务,不等待浏览器尚未产生的未来条目。
563
+
564
+ 初始化先恢复保留范围内的 View 历史,再处理 buffered 条目;首次 manual View、BFCache 恢复 View 尚未就绪时有界等待关联。撤权再授权不重复采集同一文档的 FCP/LCP/TTFB。BFCache 的 FCP/LCP 是恢复后双 animation frame 的绘制近似值,TTFB 为 0;不要与新文档首屏样本混为一类。当前没有自定义 duration vital 或自动 INP–LoAF 脚本关联。
565
+
566
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
567
+ | ----------------------------------------------------- | ---------------------------------------------------------- | ------ | --------------------------------- | ------------------------------------------------------------------------ |
568
+ | `attributes.vital.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 指标 ID | |
569
+ | `attributes.vital.version` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 指标快照版本 | 从 1 递增;同 ID 取最大版本覆盖。 |
570
+ | `attributes.vital.scope` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 指标作用域 | document / activation / view。 |
571
+ | `attributes.vital.metric` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | enum | 指标 | |
572
+ | `attributes.vital.value` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 指标值 | |
573
+ | `attributes.vital.inp.input_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 输入延迟(ms) | 用户发起交互(如点击)到事件处理器开始执行的等待时间,反映主线程繁忙程度 |
574
+ | `attributes.vital.inp.interaction_target` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 交互目标元素 | 如 `div`。 |
575
+ | `attributes.vital.inp.target_selector` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 目标 selector | 使用 Action 相同的节点隐私和结构定位策略;可能缺失。 |
576
+ | `attributes.vital.inp.time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 候选分组最早输入时间(ms) | 相对所属 View 起点。 |
577
+ | `attributes.vital.inp.interaction_type` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 交互类型 | -- |
578
+ | `attributes.vital.inp.processing_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 交互处理耗时(ms) | -- |
579
+ | `attributes.vital.inp.presentation_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 呈现延迟(ms) | -- |
580
+ | `attributes.vital.lcp.target` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | LCP 元素选择器 | 如 `div`。 |
581
+ | `attributes.vital.lcp.url` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | LCP 资源 URL(已脱敏) | -- |
582
+ | `attributes.vital.lcp.resource_load_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | LCP 资源加载耗时(ms) | -- |
583
+ | `attributes.vital.lcp.resource_load_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 资源加载延迟(ms) | 首字节到 LCP 资源开始加载。 |
584
+ | `attributes.vital.lcp.time_to_first_byte` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | LCP 拆分的首字节时间(ms) | 浏览器/指标实现提供时写入。 |
585
+ | `attributes.vital.lcp.element_render_delay` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | LCP 元素渲染延迟(ms) | -- |
586
+ | `attributes.vital.cls.time` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 最大窗口内主要偏移的时刻(ms) | 相对所属 View 起点;取窗口内最大单次 Shift。 |
587
+ | `attributes.vital.cls.target_selector` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 主要偏移的目标 selector | 该 Shift 中前后矩形并集面积最大的 source,遵守 Action 隐私规则。 |
588
+ | `attributes.vital.cls.previous_rect.x/y/width/height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 偏移前矩形(CSS px) | 展开为四个独立标量字段;source 不可用时省略。 |
589
+ | `attributes.vital.cls.current_rect.x/y/width/height` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 偏移后矩形(CSS px) | 展开为四个独立标量字段;source 不可用时省略。 |
590
+ | `attributes.vital.cls.device_pixel_ratio` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 设备像素比 | 捕获主要 Shift 时的 DPR;矩形仍保留 CSS px。 |
591
+ | `attributes.vital.ttfb.waiting_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 请求准备耗时(ms) | -- |
592
+ | `attributes.vital.ttfb.cache_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 请求准备后至 DNS 前耗时(ms) | workerStart/fetchStart 至 domainLookupStart,不表示缓存命中。 |
593
+ | `attributes.vital.ttfb.dns_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | DNS 阶段耗时(ms) | -- |
594
+ | `attributes.vital.ttfb.connection_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 连接耗时(含 TLS)(ms) | -- |
595
+ | `attributes.vital.ttfb.request_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 请求阶段耗时(ms) | -- |
515
596
 
516
597
  **[1] `attributes.vital.metric`**:
517
598
 
518
- | 值 | 描述 | 备注 |
519
- | ---- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
520
- | cls | [CLS(累积布局偏移)](https://web.dev/articles/cls) | 在整个页面生命周期中,每次出现的意外布局变化所导致的最大布局变化得分的累积值,为了提供良好的用户体验,网站的 CLS 得分应控制在 0.1 或更低。 |
521
- | inp | [INP(交互到下一次绘制)](https://web.dev/articles/inp) | 记录用户与页面进行的所有交互的延迟情况,并给出一个综合评分(通常是 P98,忽略极端值),较低的 INP 值意味着页面能够快速响应所有或绝大多数用户交互,INP 值在用户离开页面时会被计算出来。 |
522
- | lcp | [LCP(最大内容绘制)](https://web.dev/articles/lcp) | Core Web Vital 中的一个重要且稳定的指标,测量从页面开始加载,到视窗中可见的最大图像、文本块或视频的渲染时间,用于衡量页面加载的速度(用户感受:页面主要内容出来了)。 |
523
- | fcp | [FCP(首次内容绘制)](https://web.dev/articles/fcp) | 从用户首次访问页面,到页面第一次显示出任何内容的耗时(用户感受:不是白屏了)。 |
524
- | ttfb | [TTFB(首字节耗时)](https://web.dev/articles/ttfb) | 从用户开始导航到页面到响应首字节开始传输之间所经历的时间。 |
599
+ | 值 | 描述 | 备注 |
600
+ | ---- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
601
+ | cls | [CLS(累积布局偏移)](https://web.dev/articles/cls) | SDK 按逻辑 View 的布局偏移窗口计算最大累计分数,值越低表示布局越稳定。 |
602
+ | inp | [INP(交互到下一次绘制)](https://web.dev/articles/inp) | SDK 按逻辑 View 的交互数量选近似 p98 候选,在检查点和结束后迟到条目到达时持续修订。 |
603
+ | lcp | [LCP(最大内容绘制)](https://web.dev/articles/lcp) | Core Web Vital 中的一个重要且稳定的指标,测量从页面开始加载,到视窗中可见的最大图像、文本块或视频的渲染时间,用于衡量页面加载的速度(用户感受:页面主要内容出来了)。 |
604
+ | fcp | [FCP(首次内容绘制)](https://web.dev/articles/fcp) | 文档首次内容绘制耗时;不代表业务主体已经可用,也不能单独用于白屏判定。 |
605
+ | ttfb | [TTFB(首字节耗时)](https://web.dev/articles/ttfb) | 从用户开始导航到页面到响应首字节开始传输之间所经历的时间。 |
525
606
 
526
607
  **[2] `attributes.vital.value`**:CLS 单位为 `1`,FCP、INP、LCP、TTFB 单位为 `ms`。
527
608
 
528
- **[3] `attributes.vital.cls.largest_shift_value` & `attributes.vital.cls.largest_shift_target`**:当前浏览器 SDK 不上报;也不上报 `vital.cls.load_state`。CLS 只带公共 `vital.metric` / `vital.value` / `vital.id`。
609
+ **[3] CLS 归因**:按 SDK View 使用“相邻偏移间隔小于 1 秒、窗口最长 5 秒”规则取最大累计窗口,归因选择该窗口内最大的单次 Shift;后续较小位移不覆盖主要来源。source 按前后矩形并集面积选择,节点消失时仍计算原矩形面积,不计算两矩形间的空白。记录 time、target_selector、前后矩形和 DPR;累计值输出四位小数,窗口比较保留原始精度。浏览器支持 Layout Shift 但没有偏移时可发 0;不支持时不伪造 0。`vital.cls.largest_shift_value`、`vital.cls.largest_shift_target` 和 `vital.cls.load_state` 不上报。
529
610
 
530
- **[4] `attributes.vital.inp.interaction_type`**:交互类型。
611
+ **[4] `attributes.vital.inp.interaction_type`**:有效候选的交互类型。候选 observer 阈值为 40ms,并观察 first-input;计数使用独立低阈值 observer 与原生 interactionCount,结束 View 冻结并校正跨边界迟到计数。明确有交互但尚无候选可发 INP 0,后续候选以更高版本修订;没有交互或 API 不支持时不发。降级计数仍为受浏览器能力约束的估算。
531
612
 
532
- | 值 | 描述 |
533
- | ------------- | ------------- |
534
- | `keyup` | 松开按键 |
535
- | `keydown` | 按下按键 |
613
+ 每个 interactionId 取最慢条目作为候选,保留最慢 10 个,按交互次数选近似 p98。分段归因合并同 interactionId 或固定参考渲染时刻 ±8ms 内的条目;同批次完成合并后再裁剪分组状态。值限制为最多 60,000ms,三段使用同一终点裁剪,均非负且合计等于上报值。
614
+
615
+ 目标名称/selector 优先使用可信输入时按 Action 隐私策略捕获的字符串,最多缓存 100 项、只匹配 10 秒内的输入,不保留 DOM 节点。匹配到禁止采集结果时不回退读取 DOM;无法唯一匹配或安全定位时允许字段缺失。
616
+
617
+ | 值 | 描述 |
618
+ | ------------- | -------- |
619
+ | `keyup` | 松开按键 |
620
+ | `keydown` | 按下按键 |
536
621
  | `pointerdown` | 指针按下 |
537
- | `pointerup` | 指针松开 |
622
+ | `pointerup` | 指针松开 |
538
623
 
539
- **[5] `attributes.vital.inp.processing_duration`**:事件处理回调(如 click handler)本身的执行时间,JS 逻辑过重时这个值会变大。
624
+ **[5] `attributes.vital.inp.processing_duration`**:分组内最早处理开始到最晚处理结束的区间,按上报值对应的绘制终点裁剪。它可包含同交互/同帧多个事件之间的间隔,不能当成某个 click handler 独占的 CPU 执行时间。
540
625
 
541
- **[6] `attributes.vital.inp.presentation_delay`**:回调操作完成之后到该帧最终显示在用户屏幕上所需的时间。
626
+ **[6] `attributes.vital.inp.presentation_delay`**:分组处理结束之后至共同绘制终点的剩余时间。处理结束超过终点时归零,避免与处理耗时重复计入。
542
627
 
543
628
  **[7] `attributes.vital.lcp.element_render_delay`**:LCP 元素资源加载完成后,到浏览器真正渲染该元素之间的等待时间(主要由主线程阻塞(长任务/JS 执行)导致)。
544
629
 
545
- **[8] `attributes.vital.lcp.resource_load_duration`**:LCP 元素依赖的外部资源(图片/字体等)从请求到下载完成的时间(如果 LCP 是纯文本节点,此项可能缺失),用于排查 CDN/网络/资源体积问题。
630
+ **[8] `attributes.vital.lcp.resource_load_duration`**:候选 LCP URL 关联资源从请求开始到响应结束的时间,选择候选出现前最后一条同 URL 的 Resource Timing。无可关联资源时加载段为 0,剩余时间归入渲染段;不能据此断定页面没有资源开销。
546
631
 
547
- **[9] `attributes.vital.lcp.time_to_first_byte`**:当前浏览器 SDK 不上报该字段。LCP 归因只包含 url / target / element_render_delay / resource_load_duration。
632
+ **[9] `attributes.vital.lcp.time_to_first_byte`**:按 Navigation Timing 计算并裁剪到 LCP 的首字节时间(ms);与 resource_load_delay、resource_load_duration、element_render_delay 共同用于定位等待阶段。LCP URL 经 redactUrl 脱敏,target 在观测候选时按 Action 隐私策略快照;节点后续移除不清空已有安全 selector,无法安全采集时省略,不回退原始 DOM ID。
548
633
 
549
634
  **[10] `attributes.vital.ttfb.waiting_duration`**:页面激活到浏览器开始 Fetch,或开始启动 Service Worker 前的时间(包含重定向及浏览器前置处理)。
550
635
 
@@ -554,119 +639,216 @@ SDK 原样上报浏览器返回的非空值,空值不写入。
554
639
 
555
640
  **[13] `attributes.vital.ttfb.request_duration`**:建连结束到收到首字节,包含调度空档、请求发送、网络 RTT 和服务端处理。
556
641
 
642
+ **[14] `attributes.vital.ttfb.cache_duration`**:从 workerStart(无此值时使用 fetchStart)到 domainLookupStart 的阶段耗时,不是 memory/disk cache 的命中证据。TTFB 五个阶段使用激活后的相邻边界并作非负裁剪,总和等于 TTFB;BFCache 恢复时各段均为 0。
557
643
 
558
644
  ### l. blank_screen
559
- > _**白屏(Blank Screen)**:非 Web 标准指标。页面可见且活动稳定后,SDK 对指定根元素范围内的视口进行采样;排除加载态样本后,如果空白样本占有效样本的比例达到阈值,并在二次检测中仍然成立,则判定为白屏。_
560
645
 
561
- | 字段 | 状态 | 类型 | 描述 | 备注 |
562
- | ---------------------------------------------- | --------------------------------------------------------------- | ------- | ---------------- | ------------------ |
563
- | `attributes.blank_screen.reason` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 白屏判定原因 | |
564
- | `attributes.blank_screen.empty_ratio` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 空白点占比 | 回退根节点检测时仍为实际比例,不是固定 `1`。 |
565
- | `attributes.blank_screen.empty_sample_count` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 空白点数量 | |
646
+ > _**白屏(Blank Screen)**:非 Web 标准指标。文档就绪、页面可见且活动稳定后,对主要内容区域采样;至少 5 个点有可解释证据、空白比例达到阈值,且在无新活动的二次检测中仍成立时,才确认故障。加载态与证据不足不能作为白屏错误。_
647
+
648
+ 当前协议不保留旧版每 View 最多一次的限制。`phase=detected` 是 `span_type=error / outcome.type=error`;`recovered` 是 `custom/success`;`observation` 是 `custom/unknown`。持续故障只确认一次,恢复后再次空白可以生成新故障 ID;持续复检和上报不续期 Session。
649
+
650
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
651
+ | ----------------------------------------------------------- | -------------------------------------------------------------- | ------ | --------------------- | ------------------------------------------------- |
652
+ | `attributes.blank_screen.reason` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 白屏判定原因 | |
653
+ | `attributes.blank_screen.empty_ratio` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 空白点占比 | 回退根节点检测时仍为实际比例,不是固定 `1`。 |
654
+ | `attributes.blank_screen.empty_sample_count` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | int | 空白点数量 | |
655
+ | `attributes.blank_screen.phase` | ![Development](https://img.shields.io/badge/-development-blue) | str | 事件阶段 | detected / recovered / observation |
656
+ | `attributes.blank_screen.state` | ![Development](https://img.shields.io/badge/-development-blue) | str | 观测状态 | blank / content / loading / unknown |
657
+ | `attributes.blank_screen.strategy_version` | ![Development](https://img.shields.io/badge/-development-blue) | int | 检测策略版本 | 当前为 2 |
658
+ | `attributes.blank_screen.trigger` | ![Development](https://img.shields.io/badge/-development-blue) | str | 本次检查来源 | view、document_ready、visible 或活动类型 |
659
+ | `attributes.blank_screen.id` | ![Development](https://img.shields.io/badge/-development-blue) | str | 故障 ID | detected 与对应 recovered 共用 |
660
+ | `attributes.blank_screen.valid_sample_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | 有效点数 | 空白点与内容点之和 |
661
+ | `attributes.blank_screen.ignored_sample_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | 忽略点数 | 暴露的 loading 点 |
662
+ | `attributes.blank_screen.unknown_sample_count` | ![Development](https://img.shields.io/badge/-development-blue) | int | 无法判断点数 | 未计入有效分母 |
663
+ | `attributes.blank_screen.first_detected_at` / `detected_at` | ![Development](https://img.shields.io/badge/-development-blue) | number | 首次候选/二次确认时间 | epoch ms |
664
+ | `attributes.blank_screen.recovered_at` / `duration` | ![Development](https://img.shields.io/badge/-development-blue) | number | 恢复时刻/观测故障时长 | epoch ms / ms;仅 recovered,时长包含中间后台时间 |
566
665
 
567
666
  **[1] `attributes.blank_screen.reason`**:
568
667
 
569
- | 值 | 描述 |
570
- | ---------------- | --------------------------------------------------------------------------------------- |
571
- | `empty_viewport` | 配置的采样根元素存在,有效采样点的空白比例达到白屏阈值。 |
572
- | `missing_root` | 未找到 `root_selector` 指定的根元素,SDK 回退到 `body`(不可用时使用 `documentElement`)检测,且回退检测仍达到白屏阈值。 |
668
+ | 值 | 描述 |
669
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------ |
670
+ | `empty_viewport` | 配置的采样根元素存在,有效采样点的空白比例达到白屏阈值。 |
671
+ | `missing_root` | 未找到 `root_selector` 指定的根元素,SDK 回退到 `body`(不可用时使用 `documentElement`)检测,且回退检测仍达到白屏阈值。 |
672
+ | `loading_visible` | 采样区域大部分仍处于 loading/skeleton。 |
673
+ | `insufficient_evidence` | 采样证据不足,包含无法判断的 Canvas/iframe 等内容。 |
674
+ | `activity_timeout` | 请求或相关活动超过 maxWait 仍未稳定。 |
675
+ | `document_not_ready` | 文档超过 maxWait 仍处于 loading,不能把未返回正文认定为白屏。 |
676
+ | `detection_unavailable` | 采样不可用或 root selector 无法执行。 |
677
+
678
+ 后五种 reason 用于 observation,不计入 Error。没有实际采样时不伪造 sample count 或 empty ratio。算法边界与配置见[白屏检测](../features/blank-screen.md)。
573
679
 
574
680
  ### m. longtask
575
681
 
576
- | 字段 | 状态 | 类型 | 描述 |
577
- | ----------------------------------------------- | --------------------------------------------------------------- | ------ | -------------------- |
578
- | `attributes.long_task.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务或长动画帧 ID |
579
- | `attributes.long_task.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务名称 |
580
- | `attributes.long_task.entry_type` *[1]* | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务类型 |
581
- | `attributes.long_task.blocking_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 主线程阻塞耗时(ms) |
582
- | `attributes.long_task.first_ui_event_timestamp` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 首个交互事件时间(ms) |
583
- | `attributes.long_task.render_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 渲染阶段开始时间(ms) |
584
- | `attributes.long_task.style_and_layout_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 样式与布局阶段开始时间(ms) |
682
+ | 字段 | 状态 | 类型 | 描述 |
683
+ | ----------------------------------------------- | ---------------------------------------------------------- | ------ | ---------------------------- |
684
+ | `attributes.long_task.id` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务或长动画帧 ID |
685
+ | `attributes.long_task.name` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务名称 |
686
+ | `attributes.long_task.entry_type` _[1]_ | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | str | 长任务类型 |
687
+ | `attributes.long_task.blocking_duration` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 主线程阻塞耗时(ms) |
688
+ | `attributes.long_task.first_ui_event_timestamp` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 首个交互事件时间(ms) |
689
+ | `attributes.long_task.render_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 渲染阶段开始时间(ms) |
690
+ | `attributes.long_task.style_and_layout_start` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | number | 样式与布局阶段开始时间(ms) |
585
691
 
586
692
  **[1] `attributes.long_task.entry_type`**:
587
693
 
588
- | 值 | 描述 |
589
- | ------------------------ | ------------------------------------------------------------------- |
590
- | `long-animation-frame` | 通过 Long Animation Frame API 采集,包含主线程阻塞、渲染、样式与布局阶段以及脚本归因信息。 |
591
- | `long-task` | 通过 Long Tasks API 采集,用于不支持 Long Animation Frame API 的浏览器,只提供长任务基础信息。 |
694
+ | 值 | 描述 |
695
+ | ---------------------- | ---------------------------------------------------------------------------------------------- |
696
+ | `long-animation-frame` | 通过 Long Animation Frame API 采集,包含主线程阻塞、渲染、样式与布局阶段以及脚本归因信息。 |
697
+ | `long-task` | 通过 Long Tasks API 采集,用于不支持 Long Animation Frame API 的浏览器,只提供长任务基础信息。 |
592
698
 
593
699
  ### n. custom
594
700
 
595
701
  `reportCustomEvent()` 产生 `custom.<name>` Span。`reportAction({ name })` 产生以 `action.name` 命名的 Span,且 `action.type=custom`。
596
702
 
703
+ ### o. timing
704
+
705
+ `attributes.timing.*` 是采集浏览器 ResourceTiming 的原始字段。
706
+
707
+ | 字段 | 状态 | 类型 | 描述 | 备注 |
708
+ | --------------------------------------------------------- | -------------------------------------------------------------- | ------ | ----------------------------------- | ----------------------------------- |
709
+ | `attributes.timing.start_time` _[1]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 资源开始时间 | 导航起点为 `0`,属于有效值。 |
710
+ | `attributes.timing.redirect_start` _[2]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向开始时间 | |
711
+ | `attributes.timing.redirect_end` _[3]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 重定向结束时间 | |
712
+ | `attributes.timing.fetch_start` _[4]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 最终资源获取开始时间 | |
713
+ | `attributes.timing.worker_start` _[5]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 介入时间 | |
714
+ | `attributes.timing.worker_router_evaluation_start` _[6]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 静态路由评估开始时间 | |
715
+ | `attributes.timing.worker_cache_lookup_start` _[7]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | Service Worker 缓存查询开始时间 | |
716
+ | `attributes.timing.domain_lookup_start` _[8]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询开始时间 | |
717
+ | `attributes.timing.domain_lookup_end` _[9]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | DNS 查询结束时间 | |
718
+ | `attributes.timing.connect_start` _[10]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接开始时间 | |
719
+ | `attributes.timing.secure_connection_start` _[11]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | TLS 握手开始时间 | 非零值不代表本次一定发生 TLS 握手。 |
720
+ | `attributes.timing.connect_end` _[12]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 连接完成时间 | |
721
+ | `attributes.timing.request_start` _[13]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 请求开始时间 | |
722
+ | `attributes.timing.response_start` _[14]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 首个响应开始时间 | 可能指向 1xx 临时响应。 |
723
+ | `attributes.timing.final_response_headers_start` _[15]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 最终响应头开始时间 | |
724
+ | `attributes.timing.response_end` _[16]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 响应结束时间 | |
725
+ | `attributes.timing.unload_event_start` _[17]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 上一页面卸载开始时间 | |
726
+ | `attributes.timing.unload_event_end` _[18]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 上一页面卸载完成时间 | |
727
+ | `attributes.timing.dom_content_loaded_event_start` _[19]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | `DOMContentLoaded` 事件开始时间 | |
728
+ | `attributes.timing.dom_content_loaded_event_end` _[20]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | `DOMContentLoaded` 事件结束时间 | |
729
+ | `attributes.timing.load_event_start` _[21]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | `load` 事件开始时间 | |
730
+ | `attributes.timing.load_event_end` _[22]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | `load` 事件结束时间 | |
731
+ | `attributes.timing.activation_start` _[23]_ | ![Development](https://img.shields.io/badge/-development-blue) | number | 预渲染页面激活开始时间 | |
732
+
733
+ **[1] [`attributes.timing.start_time`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/startTime)**:资源获取开始时间。
734
+
735
+ **[2] [`attributes.timing.redirect_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/redirectStart)**:发起首次 HTTP 重定向的资源获取开始时间。
736
+
737
+ **[3] [`attributes.timing.redirect_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/redirectEnd)**:浏览器收到最后一次重定向响应的最后一个字节后的时间。
738
+
739
+ **[4] [`attributes.timing.fetch_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/fetchStart)**:浏览器开始获取资源前的时间。
740
+
741
+ **[5] [`attributes.timing.worker_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/workerStart)**:Service Worker 介入本次资源请求的时间。未拦截资源时为 0。
742
+
743
+ **[6] [`attributes.timing.worker_router_evaluation_start`](https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-workerrouterevaluationstart)**:Service Worker 静态路由规则评估开始时间。
744
+
745
+ **[7] [`attributes.timing.worker_cache_lookup_start`](https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-workercachelookupstart)**:Service Worker 静态路由开始查询 Cache Storage 的时间。
746
+
747
+ **[8] [`attributes.timing.domain_lookup_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/domainLookupStart)**:浏览器开始查询资源域名前的时间。
748
+
749
+ **[9] [`attributes.timing.domain_lookup_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/domainLookupEnd)**:浏览器完成资源域名查询后的时间。
750
+
751
+ **[10] [`attributes.timing.connect_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/connectStart)**:浏览器开始与服务器建立连接以获取资源前的时间。
752
+
753
+ **[11] [`attributes.timing.secure_connection_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/secureConnectionStart)**:浏览器开始握手以建立安全连接前的时间。
754
+
755
+ **[12] [`attributes.timing.connect_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/connectEnd)**:浏览器完成与服务器建立连接后的时间。
756
+
757
+ **[13] [`attributes.timing.request_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/requestStart)**:浏览器开始从服务器、缓存或本地资源请求数据前的时间。
758
+
759
+ **[14] [`attributes.timing.response_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStart)**:浏览器收到响应首字节后的时间,响应可能是临时响应。
760
+
761
+ **[15] [`attributes.timing.final_response_headers_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/finalResponseHeadersStart)**:浏览器收到最终响应首字节后的时间。
762
+
763
+ **[16] [`attributes.timing.response_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseEnd)**:浏览器收到资源最后一个字节后,或传输连接关闭前的时间,以先发生者为准。
764
+
765
+ **[17] [`attributes.timing.unload_event_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/unloadEventStart)**:上一页面的 unload 事件处理程序开始执行前的时间。
766
+
767
+ **[18] [`attributes.timing.unload_event_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/unloadEventEnd)**:上一页面的 unload 事件处理程序执行完成后的时间。
768
+
769
+ **[19] [`attributes.timing.dom_content_loaded_event_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/domContentLoadedEventStart)**:当前文档的 DOMContentLoaded 事件处理程序开始执行前的时间。
770
+
771
+ **[20] [`attributes.timing.dom_content_loaded_event_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/domContentLoadedEventEnd)**:当前文档的 DOMContentLoaded 事件处理程序执行完成后的时间。
772
+
773
+ **[21] [`attributes.timing.load_event_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/loadEventStart)**:当前文档的 load 事件处理程序开始执行前的时间。
774
+
775
+ **[22] [`attributes.timing.load_event_end`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/loadEventEnd)**:当前文档的 load 事件处理程序执行完成后的时间。
776
+
777
+ **[23] [`attributes.timing.activation_start`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/activationStart)**:文档开始预渲染到实际被激活之间的时间长度。
778
+
597
779
  ## 0x04 资源加载时序
598
780
 
599
781
  ### a. W3C Resource Timing
600
782
 
601
783
  字段定义见 [PerformanceResourceTiming](https://www.w3.org/TR/resource-timing/#the-performanceresourcetiming-interface)。下表按生命周期排序。
602
784
 
603
- | 字段 | 含义 | attribute |
604
- | --- | --- | --- |
605
- | `startTime` | 这次取资源开始 | `attributes.resource.timing.start_time` |
606
- | `redirectStart` | 第一次重定向开始 | `attributes.resource.timing.redirect_start` |
607
- | `redirectEnd` | 最后一次重定向的响应收完 | `attributes.resource.timing.redirect_end` |
608
- | `workerStart` | Service Worker 开始处理这次请求;未拦截时为 `0` | `attributes.resource.timing.worker_start` |
609
- | `workerRouterEvaluationStart` | Service Worker 静态路由开始评估 | `attributes.resource.timing.worker_router_evaluation_start` |
610
- | `workerCacheLookupStart` | Service Worker 静态路由开始查 Cache Storage,不代表命中 | `attributes.resource.timing.worker_cache_lookup_start` |
611
- | `fetchStart` | 重定向结束后,开始取最终资源 | `attributes.resource.timing.fetch_start` |
612
- | `domainLookupStart` | DNS 查询开始 | `attributes.resource.timing.domain_lookup_start` |
613
- | `domainLookupEnd` | DNS 查询结束 | `attributes.resource.timing.domain_lookup_end` |
614
- | `connectStart` | 开始建立到服务器的连接 | `attributes.resource.timing.connect_start` |
615
- | `secureConnectionStart` | 可见 TLS 握手开始时间;复用连接时也可能被钳到 `fetchStart`,不能单凭非零值判断本次发生握手 | `attributes.resource.timing.secure_connection_start` |
616
- | `connectEnd` | 连接建立完成,TLS 包含在内 | `attributes.resource.timing.connect_end` |
617
- | `requestStart` | 开始向服务器发请求 | `attributes.resource.timing.request_start` |
618
- | `firstInterimResponseStart` | 中间响应,例如 `103` | — |
619
- | `responseStart` | 首个响应开始;存在 1xx 时指向首个临时响应,否则指向最终响应头 | `attributes.resource.timing.response_start` |
620
- | `finalResponseHeadersStart` | 最终响应头开始;不保证浏览器均支持 | `attributes.resource.timing.final_response_headers_start` |
621
- | `responseEnd` | 最后一字节到达,或连接先关闭 | `attributes.resource.timing.response_end` |
622
- | `duration` | 总耗时,`responseEnd − startTime` | — |
623
- | `name` | 资源 URL | `attributes.url.full` |
624
- | `entryType` | 性能条目类型,固定为 `resource` | — |
625
- | `initiatorType` | 发起方式,如 `script`、`link`、`img`、`fetch` | `attributes.resource.type` |
626
- | `navigationId` | 所属页面导航的 ID | — |
627
- | `nextHopProtocol` | 网络协议,如 `h2`、`h3` | `attributes.resource.protocol` |
628
- | `deliveryType` | 资源获取方式,如 `cache`、`navigational-prefetch` | `attributes.resource.delivery_type` |
629
- | `responseStatus` | HTTP 状态码 | `attributes.http.response.status_code` |
630
- | `contentType` | 响应内容类型 | — |
631
- | `contentEncoding` | 响应内容编码,如 `gzip`、`br` | — |
632
- | `transferSize` | 规范化传输大小;本地缓存为 `0`,不是精确网络流量 | `attributes.resource.transfer_size` |
633
- | `encodedBodySize` | 压缩后正文大小 | `attributes.resource.encoded_body_size` |
634
- | `decodedBodySize` | 解码/解压后正文大小 | `attributes.resource.decoded_body_size` |
635
- | `renderBlockingStatus` | 渲染阻塞状态 | `attributes.resource.render_blocking_status` |
636
- | `serverTiming` | 服务端返回的 Server-Timing 指标 | — |
637
- | `workerMatchedSourceType` | Service Worker 静态路由命中的来源 | `attributes.resource.timing.worker_matched_router_source` |
638
- | `workerFinalSourceType` | Service Worker 最终使用的来源 | `attributes.resource.timing.worker_final_router_source` |
785
+ | 字段 | 含义 | attribute |
786
+ | ----------------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------- |
787
+ | `startTime` | 这次取资源开始 | `attributes.timing.start_time` |
788
+ | `redirectStart` | 第一次重定向开始 | `attributes.timing.redirect_start` |
789
+ | `redirectEnd` | 最后一次重定向的响应收完 | `attributes.timing.redirect_end` |
790
+ | `workerStart` | Service Worker 开始处理这次请求;未拦截时为 `0` | `attributes.timing.worker_start` |
791
+ | `workerRouterEvaluationStart` | Service Worker 静态路由开始评估 | `attributes.timing.worker_router_evaluation_start` |
792
+ | `workerCacheLookupStart` | Service Worker 静态路由开始查 Cache Storage,不代表命中 | `attributes.timing.worker_cache_lookup_start` |
793
+ | `fetchStart` | 重定向结束后,开始取最终资源 | `attributes.timing.fetch_start` |
794
+ | `domainLookupStart` | DNS 查询开始 | `attributes.timing.domain_lookup_start` |
795
+ | `domainLookupEnd` | DNS 查询结束 | `attributes.timing.domain_lookup_end` |
796
+ | `connectStart` | 开始建立到服务器的连接 | `attributes.timing.connect_start` |
797
+ | `secureConnectionStart` | 可见 TLS 握手开始时间;复用连接时也可能被钳到 `fetchStart`,不能单凭非零值判断本次发生握手 | `attributes.timing.secure_connection_start` |
798
+ | `connectEnd` | 连接建立完成,TLS 包含在内 | `attributes.timing.connect_end` |
799
+ | `requestStart` | 开始向服务器发请求 | `attributes.timing.request_start` |
800
+ | `firstInterimResponseStart` | 中间响应,例如 `103` | — |
801
+ | `responseStart` | 首个响应开始;存在 1xx 时指向首个临时响应,否则指向最终响应头 | `attributes.timing.response_start` |
802
+ | `finalResponseHeadersStart` | 最终响应头开始;不保证浏览器均支持 | `attributes.timing.final_response_headers_start` |
803
+ | `responseEnd` | 最后一字节到达,或连接先关闭 | `attributes.timing.response_end` |
804
+ | `duration` | 总耗时,`responseEnd − startTime` | — |
805
+ | `name` | 资源 URL | `attributes.url.full` |
806
+ | `entryType` | 性能条目类型,固定为 `resource` | — |
807
+ | `initiatorType` | 发起方式,如 `script`、`link`、`img`、`fetch` | `attributes.resource.initiator_type` |
808
+ | `navigationId` | 所属页面导航的 ID | — |
809
+ | `nextHopProtocol` | 网络协议,如 `h2`、`h3` | `attributes.resource.protocol` |
810
+ | `deliveryType` | 资源获取方式,如 `cache`、`navigational-prefetch` | `attributes.resource.delivery_type` |
811
+ | `responseStatus` | HTTP 状态码 | `attributes.http.response.status_code` |
812
+ | `contentType` | 响应内容类型 | — |
813
+ | `contentEncoding` | 响应内容编码,如 `gzip`、`br` | — |
814
+ | `transferSize` | 规范化传输大小;本地缓存为 `0`,不是精确网络流量 | `attributes.resource.transfer_size` |
815
+ | `encodedBodySize` | 压缩后正文大小 | `attributes.resource.encoded_body_size` |
816
+ | `decodedBodySize` | 解码/解压后正文大小 | `attributes.resource.decoded_body_size` |
817
+ | `renderBlockingStatus` | 渲染阻塞状态 | `attributes.resource.render_blocking_status` |
818
+ | `serverTiming` | 服务端返回的 Server-Timing 指标 | — |
819
+ | `workerMatchedSourceType` | Service Worker 静态路由命中的来源 | `attributes.resource.timing.worker_matched_router_source` |
820
+ | `workerFinalSourceType` | Service Worker 最终使用的来源 | `attributes.resource.timing.worker_final_router_source` |
639
821
 
640
822
  ### b. 阶段划分
641
823
 
642
- 下表使用 `attributes.resource.timing` 上报字段计算阶段。绘图时,阶段时间点无效、顺序异常或计算耗时小于等于 `0`,均不画阶段条。
643
-
644
- | 阶段 | 计算 | 术语介绍 | 用户感受 | 官方定义 |
645
- | --- | --- | --- | --- | --- |
646
- | 重定向 | `attributes.resource.timing.redirect_end − attributes.resource.timing.redirect_start` | 服务器返回 3xx 和新地址后,浏览器立即请求新地址,可能经过多次跳转,每次都多一次往返。 | 浏览器正在按服务器给出的新地址重新请求。 | W3C:[redirectStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-redirectstart)、[redirectEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-redirectend) |
647
- | 发起前等待 | C|D|E 类(无重定向):`attributes.resource.timing.fetch_start − attributes.resource.timing.start_time`<br />D|E 类(有重定向):`attributes.resource.timing.fetch_start − attributes.resource.timing.redirect_end` | 浏览器开始获取资源前的准备时间。 | 浏览器正在准备获取资源。 | W3C:[fetchStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-fetchstart) |
648
- | [资源调度] 正在排队 | B 类:`attributes.resource.timing.worker_start − attributes.resource.timing.start_time` | 请求在连接开始前被排入队列,原因可能是有更高优先级的请求,或者同一来源的连接数已满。 | 浏览器正在排队,等待处理这次请求。 | W3C:[workerStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-workerstart);DevTools:`[资源调度] 正在排队` |
649
- | [ServiceWorker] 启动 | `attributes.resource.timing.fetch_start − attributes.resource.timing.worker_start` | 浏览器启动 Service Worker,以便由它处理这次请求。 | 浏览器正在启动 Service Worker。 | W3C:[workerStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-workerstart);DevTools:[ServiceWorker] 启动 |
650
- | [ServiceWorker] 向 ServiceWorker 发送的请求 | `attributes.resource.timing.request_start − attributes.resource.timing.fetch_start` | 浏览器把请求发送给 Service Worker 处理。 | 浏览器正在把请求发送给 Service Worker。 | W3C:[requestStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-requeststart);DevTools:`[ServiceWorker] 向 ServiceWorker 发送的请求` |
651
- | [ServiceWorker] respondWith | 有首字节时间:`attributes.resource.timing.response_start − attributes.resource.timing.request_start`<br />无首字节时间:`attributes.resource.timing.response_end − attributes.resource.timing.request_start`<br />`attributes.resource.timing.request_start = 0` 时,起点改用 `attributes.resource.timing.fetch_start` | Service Worker 拦截请求后自行提供响应,例如读缓存或访问网络。 | Service Worker 正在处理请求,浏览器在等它交回响应。 | W3C:[Service Worker `respondWith`](https://w3c.github.io/ServiceWorker/#fetch-event-respondwith);DevTools:`[ServiceWorker] respondWith` |
652
- | DNS | `attributes.resource.timing.domain_lookup_end − attributes.resource.timing.domain_lookup_start` | 浏览器通过 DNS 把资源域名解析为 IP 地址。 | 浏览器正在解析请求的 IP 地址。 | W3C:[domainLookupStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-domainlookupstart)、[domainLookupEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-domainlookupend) |
653
- | 连接建立 | 有 TLS:`attributes.resource.timing.secure_connection_start − attributes.resource.timing.connect_start`<br />无 TLS:`attributes.resource.timing.connect_end − attributes.resource.timing.connect_start` | 浏览器通过 TCP 握手与服务器建立连接。 | 浏览器正在和服务器建立连接。 | W3C:[connectStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-connectstart)、[connectEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-connectend) |
654
- | TLS | `attributes.resource.timing.connect_end − attributes.resource.timing.secure_connection_start` | 浏览器与服务器协商加密方式并验证服务器身份,建立安全连接。 | 浏览器正在和服务器确认身份、协商加密。 | W3C:[secureConnectionStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-secureconnectionstart);Fetch:[复用连接的时间点钳制](https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info) |
655
- | 等待首字节 | D|E 类:`attributes.resource.timing.response_start − attributes.resource.timing.connect_end`<br />B 类:`attributes.resource.timing.response_start − attributes.resource.timing.request_start`(`attributes.resource.timing.request_start = 0` 时改用 `attributes.resource.timing.fetch_start`)<br />C 类:`attributes.resource.timing.response_start − attributes.resource.timing.fetch_start` | 浏览器发出请求后,等待服务器准备并返回响应第一个字节的时间。 | 浏览器正在发送请求并等待服务器回应。 | W3C:[requestStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-requeststart)、[responseStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responsestart) |
656
- | 内容下载 | 有首字节时间:`attributes.resource.timing.response_end − attributes.resource.timing.response_start`<br />B|C 类无首字节时间:`attributes.resource.timing.response_end − attributes.resource.timing.fetch_start` | 浏览器接收响应内容,从第一个字节到最后一个字节。 | 浏览器正在接收响应内容。 | W3C:[responseStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responsestart)、[responseEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responseend) |
657
- | 总耗时 | `attributes.resource.timing.response_end − attributes.resource.timing.start_time` | 从请求开始到收到响应最后一个字节的总时长。 | 从这次请求开始,到浏览器收完全部内容为止。 | W3C:[Timing-Allow-Origin](https://www.w3.org/TR/resource-timing/#sec-timing-allow-origin) |
824
+ 下表使用 `attributes.timing` 上报字段计算阶段。绘图时,阶段时间点无效、顺序异常或计算耗时小于等于 `0`,均不画阶段条。
825
+
826
+ | 阶段 | 计算 | 术语介绍 | 用户感受 | 官方定义 |
827
+ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
828
+ | 重定向 | `attributes.timing.redirect_end − attributes.timing.redirect_start` | 服务器返回 3xx 和新地址后,浏览器立即请求新地址,可能经过多次跳转,每次都多一次往返。 | 浏览器正在按服务器给出的新地址重新请求。 | W3C:[redirectStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-redirectstart)、[redirectEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-redirectend) |
829
+ | 发起前等待 | C 类(`attributes.timing.redirect_end` 非零):`attributes.timing.fetch_start − attributes.timing.redirect_end`<br />C 类(`attributes.timing.redirect_end` 缺失或为 `0`):`attributes.timing.fetch_start − attributes.timing.start_time`<br />D|E 类(无重定向):`attributes.timing.fetch_start − attributes.timing.start_time`<br />D|E 类(有重定向):`attributes.timing.fetch_start − attributes.timing.redirect_end` | 浏览器开始获取资源前的准备时间。 | 浏览器正在准备获取资源。 | W3C:[fetchStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-fetchstart) |
830
+ | [资源调度] 正在排队 | B 类(`attributes.timing.redirect_end` 非零):`attributes.timing.worker_start − attributes.timing.redirect_end`<br />B 类(`attributes.timing.redirect_end` 缺失或为 `0`):`attributes.timing.worker_start − attributes.timing.start_time` | 请求在连接开始前被排入队列,原因可能是有更高优先级的请求,或者同一来源的连接数已满。 | 浏览器正在排队,等待处理这次请求。 | W3C:[workerStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-workerstart);DevTools:`[资源调度] 正在排队` |
831
+ | [ServiceWorker] 启动 | `attributes.timing.fetch_start − attributes.timing.worker_start` | 浏览器启动 Service Worker,以便由它处理这次请求。 | 浏览器正在启动 Service Worker。 | W3C:[workerStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-workerstart);DevTools:[ServiceWorker] 启动 |
832
+ | [ServiceWorker] 向 ServiceWorker 发送的请求 | `attributes.timing.request_start − attributes.timing.fetch_start` | 浏览器把请求发送给 Service Worker 处理。 | 浏览器正在把请求发送给 Service Worker。 | W3C:[requestStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-requeststart);DevTools:`[ServiceWorker] 向 ServiceWorker 发送的请求` |
833
+ | [ServiceWorker] respondWith | 有首字节时间:`attributes.timing.response_start − attributes.timing.request_start`<br />无首字节时间:`attributes.timing.response_end − attributes.timing.request_start`<br />`attributes.timing.request_start = 0` 时,起点改用 `attributes.timing.fetch_start` | Service Worker 拦截请求后自行提供响应,例如读缓存或访问网络。 | Service Worker 正在处理请求,浏览器在等它交回响应。 | W3C:[Service Worker `respondWith`](https://w3c.github.io/ServiceWorker/#fetch-event-respondwith);DevTools:`[ServiceWorker] respondWith` |
834
+ | DNS | `attributes.timing.domain_lookup_end − attributes.timing.domain_lookup_start` | 浏览器通过 DNS 把资源域名解析为 IP 地址。 | 浏览器正在解析请求的 IP 地址。 | W3C:[domainLookupStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-domainlookupstart)、[domainLookupEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-domainlookupend) |
835
+ | 连接建立 | 有 TLS:`attributes.timing.secure_connection_start − attributes.timing.connect_start`<br />无 TLS:`attributes.timing.connect_end − attributes.timing.connect_start` | 浏览器通过 TCP 握手与服务器建立连接。 | 浏览器正在和服务器建立连接。 | W3C:[connectStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-connectstart)、[connectEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-connectend) |
836
+ | TLS | `attributes.timing.connect_end − attributes.timing.secure_connection_start` | 浏览器与服务器协商加密方式并验证服务器身份,建立安全连接。 | 浏览器正在和服务器确认身份、协商加密。 | W3C:[secureConnectionStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-secureconnectionstart);Fetch:[复用连接的时间点钳制](https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info) |
837
+ | 等待首字节 | D|E 类:`attributes.timing.response_start − attributes.timing.connect_end`<br />B 类:`attributes.timing.response_start − attributes.timing.request_start`(`attributes.timing.request_start = 0` 时改用 `attributes.timing.fetch_start`)<br />C 类:`attributes.timing.response_start − attributes.timing.fetch_start` | 浏览器发出请求后,等待服务器准备并返回响应第一个字节的时间。 | 浏览器正在发送请求并等待服务器回应。 | W3C:[requestStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-requeststart)、[responseStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responsestart) |
838
+ | 内容下载 | 有首字节时间:`attributes.timing.response_end − attributes.timing.response_start`<br />B|C 类无首字节时间:`attributes.timing.response_end − attributes.timing.fetch_start` | 浏览器接收响应内容,从第一个字节到最后一个字节。 | 浏览器正在接收响应内容。 | W3C:[responseStart](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responsestart)、[responseEnd](https://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-responseend) |
839
+ | 总耗时 | `attributes.timing.response_end − attributes.timing.start_time` | 从请求开始到收到响应最后一个字节的总时长。 | 从这次请求开始,到浏览器收完全部内容为止。 | W3C:[Timing-Allow-Origin](https://www.w3.org/TR/resource-timing/#sec-timing-allow-origin) |
658
840
 
659
841
  ### c. 瀑布图
660
842
 
661
- 按 A→E 顺序匹配;所有瀑布图在基础图上进一步修改,标为「可选」的阶段按图下表格的显示条件绘制。
843
+ `resource.timing.incomplete=true` 时只展示回退观测时长并注明数据不完整,不绘制猜测的网络阶段。其他条目按 A→E 顺序匹配,先检查时序可见性,再区分交付路径;大小字段缺失与 `0` 含义不同,不参与 A 类判断。所有瀑布图在基础图上进一步修改,标为「可选」的阶段按图下表格的显示条件绘制。
662
844
 
663
- | 瀑布图类型 | 说明 | 判断条件 | 备注 |
664
- | --- | --- | --- | --- |
665
- | A. 跨域明细不可见 | 只能展示总耗时 | 以下条件同时满足:<br />[1] `attributes.resource.timing.request_start = 0`;<br />[2] `attributes.resource.timing.response_start = 0`;<br />[3] `attributes.resource.decoded_body_size = 0` | -- |
666
- | B. Service Worker 响应 | 主请求由 SW 的 `fetch` 事件交回响应 | 以下条件同时满足:<br />[1] `attributes.resource.timing.worker_start > 0`;<br />[2] 以下条件满足任一:<br />[a] `attributes.resource.timing.connect_end = 0`<br />[b] `attributes.resource.timing.connect_end = attributes.resource.timing.fetch_start`<br />[3] 以下条件满足任一:<br />[a] `attributes.resource.timing.worker_matched_router_source = null`<br />[b] `attributes.resource.timing.worker_matched_router_source = fetch-event`<br />[4] `attributes.resource.timing.worker_final_router_source ≠ cache` | SW 转发网络时主请求也看不到 DNS、建连,真实网络耗时在 SW 内部请求上,所以不归 D / E。 |
667
- | C. 非网络响应 | 主请求没有可见的 DNS、建连和 TLS 阶段 | 以下条件同时满足:<br />[1] 以下条件满足任一:<br />[a] `attributes.resource.timing.connect_end = 0`<br />[b] `attributes.resource.timing.connect_end = attributes.resource.timing.fetch_start`<br />[2] 以下条件满足任一:<br />[a] `attributes.resource.delivery_type = cache && attributes.resource.transfer_size = 0`(浏览器缓存命中)<br />[b] `attributes.resource.delivery_type = null && attributes.resource.transfer_size = 0 && attributes.resource.decoded_body_size > 0`(推断缓存命中)<br />[c] `attributes.resource.timing.worker_final_router_source = cache`(Service Worker 静态路由命中缓存) | [2][b] 用于未上报 `delivery_type` 的浏览器:没有传输字节但有正文,按缓存命中处理。 |
668
- | D. 连接复用 | DNS、建连耗时为 `0` ms | 以下条件同时满足:<br />[1] `attributes.resource.timing.domain_lookup_start = attributes.resource.timing.domain_lookup_end = attributes.resource.timing.connect_start = attributes.resource.timing.connect_end`;<br />[2] `attributes.resource.timing.connect_end ≠ 0` | -- |
669
- | E. 网络请求 | 普通请求、缓存重新验证等 | 以下条件同时满足:<br />[1] 未匹配 A、B、C、D 类;<br />[2] `attributes.resource.timing.connect_start > 0 && attributes.resource.timing.connect_end > 0` | -- |
845
+ | 瀑布图类型 | 说明 | 判断条件 | 备注 |
846
+ | ---------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
847
+ | A. 明细不可见或缺失 | 只能展示已观测到的总耗时 | `attributes.timing.request_start` 为 `0` 或缺失,且 `attributes.timing.response_start` 为 `0` 或缺失 | TAO 限制、网络失败或缺少 Timing 都可能出现;不以正文大小推断原因。 |
848
+ | B. Service Worker 响应 | 主请求由 SW 的 `fetch` 事件交回响应 | 以下条件同时满足:<br />[1] `attributes.timing.worker_start > 0`;<br />[2] 以下条件满足任一:<br />[a] `attributes.timing.connect_end = 0`<br />[b] `attributes.timing.connect_end = attributes.timing.fetch_start`<br />[3] 以下条件满足任一:<br />[a] `attributes.resource.timing.worker_matched_router_source = null`<br />[b] `attributes.resource.timing.worker_matched_router_source = fetch-event`<br />[4] `attributes.resource.timing.worker_final_router_source ≠ cache` | SW 转发网络时主请求也看不到 DNS、建连,真实网络耗时在 SW 内部请求上,所以不归 D / E。 |
849
+ | C. 非网络响应 | 主请求没有可见的 DNS、建连和 TLS 阶段 | `attributes.timing.connect_end = 0` 或等于 `attributes.timing.fetch_start`,且满足任一:<br />[1] `attributes.resource.cache.hit = true && attributes.resource.transfer_size = 0`;<br />[2] `attributes.resource.timing.worker_final_router_source = cache`;<br />[3] `attributes.resource.delivery_type = cache-storage` | HTTP 缓存复用直接使用 SDK 的确认结果,不能仅凭 transfer 为 `0`、正文非零或 delivery_type 缺失推断。协商缓存仍可经过网络阶段。 |
850
+ | D. 连接复用 | DNS、建连耗时为 `0` ms | 以下条件同时满足:<br />[1] `attributes.timing.domain_lookup_start = attributes.timing.domain_lookup_end = attributes.timing.connect_start = attributes.timing.connect_end`;<br />[2] `attributes.timing.connect_end ≠ 0` | -- |
851
+ | E. 网络请求 | 普通请求、缓存重新验证等 | 以下条件同时满足:<br />[1] 未匹配 A、B、C、D 类;<br />[2] `attributes.timing.connect_start > 0 && attributes.timing.connect_end > 0` | -- |
670
852
 
671
853
  图例:`=` 阶段条,`-` 浅色条,`·` 分隔线。
672
854
 
@@ -684,19 +866,21 @@ startTime responseEnd
684
866
  **基础图**
685
867
 
686
868
  ```text
687
- startTime responseEnd
688
- ==== [资源调度] 正在排队
689
- ==== [ServiceWorker] 启动
690
- = [ServiceWorker] 向 ServiceWorker 发送的请求(可选)
691
- ================= [ServiceWorker] respondWith
692
- ================= 等待首字节(可选)
693
- ====================== 内容下载
869
+ startTime responseEnd
870
+ ====== 重定向(可选)
871
+ ==== [资源调度] 正在排队
872
+ ==== [ServiceWorker] 启动
873
+ = [ServiceWorker] 向 ServiceWorker 发送的请求(可选)
874
+ ================= [ServiceWorker] respondWith
875
+ ================= 等待首字节(可选)
876
+ ====================== 内容下载
694
877
  ```
695
878
 
696
- | 显示条件 | 阶段 | 说明 |
697
- | --- | --- | --- |
698
- | `requestStart > fetchStart` | [ServiceWorker] 向 ServiceWorker 发送的请求 | 通常为 `0` |
699
- | `responseStart > 0` | 等待首字节 | 与 [ServiceWorker] respondWith 同起止。 |
879
+ | 显示条件 | 阶段 | 说明 |
880
+ | ----------------------------------------- | ------------------------------------------- | ------------------------------------------------------------ |
881
+ | `startTime ≤ redirectStart < redirectEnd` | 重定向 | ServiceWorker 可以构造重定向请求,也可以拦截被重定向的请求。 |
882
+ | `requestStart > fetchStart` | [ServiceWorker] 向 ServiceWorker 发送的请求 | 通常为 `0` |
883
+ | `responseStart > 0` | 等待首字节 | 与 [ServiceWorker] respondWith 同起止。 |
700
884
 
701
885
  > `responseStart = 0` (部分浏览器在 ServiceWorker 场景下,不记录 responseStart):「内容下载」改用 fetchStart -> responseEnd。
702
886
 
@@ -705,12 +889,17 @@ startTime responseEnd
705
889
  **基础图**
706
890
 
707
891
  ```text
708
- startTime responseEnd
709
- ======== 发起前等待
710
- ============ 等待首字节
711
- ============================ 内容下载
892
+ startTime responseEnd
893
+ ====== 重定向(可选)
894
+ ======== 发起前等待
895
+ ============ 等待首字节
896
+ ============================ 内容下载
712
897
  ```
713
898
 
899
+ | 显示条件 | 阶段 | 说明 |
900
+ | ----------------------------------------- | ------ | -------------------------------------------------------- |
901
+ | `startTime ≤ redirectStart < redirectEnd` | 重定向 | 该请求未缓存时经历过重定向,最终缓存请求包含重定向阶段。 |
902
+
714
903
  #### D. 连接复用
715
904
 
716
905
  **基础图**
@@ -726,9 +915,9 @@ startTime responseEnd
726
915
 
727
916
  > 为区分缓存场景,连接复用场景需要展示 DNS、建立连接、TLS 阶段
728
917
 
729
- | 显示条件 | 阶段 | 说明 |
730
- | --- | --- | --- |
731
- | `redirectStart > 0` | 重定向 | 该请求经历重定向,最终一跳复用已有连接。 |
918
+ | 显示条件 | 阶段 | 说明 |
919
+ | ----------------------------------------- | ------ | ---------------------------------------- |
920
+ | `startTime ≤ redirectStart < redirectEnd` | 重定向 | 该请求经历重定向,最终一跳复用已有连接。 |
732
921
 
733
922
  #### E. 网络请求
734
923
 
@@ -745,18 +934,100 @@ startTime responseEnd
745
934
  ============== 内容下载
746
935
  ```
747
936
 
748
- | 显示条件 | 阶段 | 说明 |
749
- | --- | --- | --- |
750
- | `redirectStart > 0` | 重定向 | 最终请求前发生可见重定向时展示。 |
751
- | `domainLookupStart > 0` | DNS | DNS 使用缓存或复用现有解析结果时。 |
752
- | `connectStart > 0` | 连接建立 | 有 TLS 时计算到 `secureConnectionStart`;两者相等时没有独立的连接建立条。 |
753
- | `secureConnectionStart > 0` | TLS | 只有 `connectEnd − secureConnectionStart` 为正且时间点有效时才绘制;非零时间点本身不代表有握手阶段。 |
937
+ | 显示条件 | 阶段 | 说明 |
938
+ | ----------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
939
+ | `startTime ≤ redirectStart < redirectEnd` | 重定向 | 最终请求前发生可见重定向时展示。 |
940
+ | `domainLookupStart > 0` | DNS | DNS 使用缓存或复用现有解析结果时。 |
941
+ | `connectStart > 0` | 连接建立 | 有 TLS 时计算到 `secureConnectionStart`;两者相等时没有独立的连接建立条。 |
942
+ | `secureConnectionStart > 0` | TLS | 只有 `connectEnd − secureConnectionStart` 为正且时间点有效时才绘制;非零时间点本身不代表有握手阶段。 |
943
+
944
+ ### d. 后续扩展
945
+
946
+ 当前版本暂不展示,后续可按需补充:
947
+
948
+ | 扩展 | 计算 | 生效条件 | 说明 |
949
+ | ------------ | ------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
950
+ | 临时响应 | `finalResponseHeadersStart − responseStart` | `firstInterimResponseStart > 0 && finalResponseHeadersStart > 0` | 服务器先回 `103` 等临时响应时,`responseStart` 指向首个临时响应,所以内容下载可拆成「临时响应」和「最终内容下载」两段。 |
951
+ | 最终内容下载 | `responseEnd − finalResponseHeadersStart` | 同上 | 从最终响应头到收完最后一个字节。 |
952
+
953
+ ## 0x05 页面加载时序
954
+
955
+ ### a. W3C Navigation Timing
956
+
957
+ 字段定义见 [PerformanceNavigationTiming](https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming)。下表按生命周期排序,与 Resource 相同的字段在此不再赘述。
958
+
959
+ | 字段 | 含义 | attribute |
960
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
961
+ | `unloadEventStart` | 开始卸载上一页面 | `attributes.timing.unload_event_start` |
962
+ | `unloadEventEnd` | 上一页面卸载完成 | `attributes.timing.unload_event_end` |
963
+ | `domInteractive` | HTML 解析完成 | `attributes.view.dom_interactive` |
964
+ | `domContentLoadedEventStart` | 即将派发 DOMContentLoaded | `attributes.timing.dom_content_loaded_event_start` |
965
+ | `domContentLoadedEventEnd` | DOMContentLoaded 处理完成 | `attributes.timing.dom_content_loaded_event_end`、`attributes.view.dom_content_loaded` |
966
+ | `domComplete` | 文档进入 complete 状态 | `attributes.view.dom_complete` |
967
+ | `loadEventStart` | 即将派发 load | `attributes.timing.load_event_start` |
968
+ | `loadEventEnd` | load 处理完成 | `attributes.timing.load_event_end`、`attributes.view.load_event` |
969
+ | `activationStart` | 预渲染文档被激活,见 [Prerendering](https://wicg.github.io/nav-speculation/prerendering.html#dom-performancenavigationtiming-activationstart) | `attributes.timing.activation_start` |
970
+ | `type` | 导航类型,如 `navigate`、`reload`、`back_forward` | — |
971
+ | `redirectCount` | 同源重定向次数 | — |
972
+
973
+ **SDK View**
974
+
975
+ | 字段 | 含义 | attribute |
976
+ | ------------- | -------------------------------------------------------------------------------- | ------------------------------ |
977
+ | View 开始时间 | 本次页面访问的起点,即首次加载页面、进入新路由或从浏览器历史缓存恢复页面的时间。 | `attributes.view.started_at` |
978
+ | Loading Time | 从开始访问页面,到资源加载、接口请求和页面内容更新完成的耗时。 | `attributes.view.loading_time` |
979
+
980
+ ### b. 阶段划分
981
+
982
+ 以下导航阶段适用于 `attributes.view.loading_type = initial_load`时,按 c 节瀑布图展示即可。
983
+
984
+ **Navigation Timing 阶段**
985
+
986
+ | 阶段 | 计算 | 术语介绍 | 用户感受 | 官方定义 |
987
+ | ------------ | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
988
+ | 文档请求 | `attributes.timing.response_end − attributes.timing.start_time` | 获取主文档 HTML 的完整过程,该阶段后续可按 0x04 划分。 | 浏览器正在获取页面文档。 | W3C:[PerformanceNavigationTiming](https://www.w3.org/TR/navigation-timing-2/#sec-PerformanceNavigationTiming),继承 Resource Timing |
989
+ | 卸载上一页面 | `attributes.timing.unload_event_end − attributes.timing.unload_event_start` | 浏览器执行前一个页面的 unload 处理函数。 | 浏览器正在关闭上一个页面。 | W3C:[unloadEventStart](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-unloadeventstart)、[unloadEventEnd](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-unloadeventend) |
990
+ | 解析 HTML | `attributes.view.dom_interactive − attributes.timing.response_start` | 浏览器边接收边解析 HTML、构建 DOM,期间会执行同步脚本。 | 页面结构正在生成,内容开始陆续出现。 | W3C:[domInteractive](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-dominteractive);DevTools:`解析 HTML` |
991
+ | 脚本初始化 | `attributes.timing.dom_content_loaded_event_end − attributes.view.dom_interactive` | HTML 解析完成后,浏览器先等待并执行 defer 脚本和模块脚本,再派发 DOMContentLoaded 事件并执行处理函数。 | 页面结构已就绪,脚本正在初始化。 | HTML:[The end](https://html.spec.whatwg.org/multipage/parsing.html#the-end) |
992
+ | 剩余资源加载 | `attributes.timing.load_event_start − attributes.timing.dom_content_loaded_event_end` | 浏览器等待图片、iframe、async 脚本等子资源加载完成。 | 页面主体已出现,图片等内容仍在加载。 | W3C:[domComplete](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-domcomplete)、[loadEventStart](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-loadeventstart) |
993
+ | 页面趋于稳定 | `max(attributes.timing.load_event_end, attributes.view.loading_time) − attributes.timing.load_event_start` | 浏览器派发 load 事件并执行处理函数,之后接口请求、资源和 DOM 变化继续进行,直到页面活动结束。 | 页面内容加载完成,逐渐稳定下来。 | W3C:[loadEventStart](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-loadeventstart)、[loadEventEnd](https://www.w3.org/TR/navigation-timing-2/#dom-performancenavigationtiming-loadeventend);DevTools:`L` |
994
+ | 预渲染 | `attributes.timing.activation_start − attributes.timing.start_time` | 浏览器在后台提前加载并渲染页面。 | 用户还没进入页面,浏览器已经在后台准备。 | Prerender:[Performance Navigation Timing 扩展](https://wicg.github.io/nav-speculation/prerendering.html#performance-navigation-timing-extension) |
995
+
996
+ > 当前 SDK 尚未在 View 中上报文档请求分类所需字段,因此文档请求暂按总耗时展示,内部阶段暂不拆分。
997
+
998
+ ### c. 瀑布图
999
+
1000
+ ```text
1001
+ startTime loadEventEnd
1002
+ ============================================ 文档请求
1003
+ === 卸载上一页面(可选)
1004
+ ========== 解析 HTML
1005
+ ======= 脚本初始化
1006
+ ======== 剩余资源加载
1007
+ === 页面趋于稳定(可选)
1008
+ ========================================================== 预渲染(可选)
1009
+ ```
1010
+
1011
+ | 显示条件 | 阶段 | 说明 |
1012
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------- |
1013
+ | `0 ≤ startTime < responseEnd` | 文档请求 | 以 `startTime = 0` 为起点的有效请求也展示。 |
1014
+ | `unloadEventEnd > unloadEventStart > 0` | 卸载上一页面 | 前页跨域或重定向不全同源时,时间点为 `0`,不显示。 |
1015
+ | `domInteractive > responseStart > 0` | 解析 HTML | 仅使用实际上报的 `attributes.view.dom_interactive`;该字段缺失时省略此段。 |
1016
+ | `domInteractive > 0 && domContentLoadedEventStart ≥ domInteractive && domContentLoadedEventEnd ≥ domContentLoadedEventStart && domContentLoadedEventEnd > domInteractive` | 脚本初始化 | DOMContentLoaded 处理完成后,按 HTML 解析完成至事件处理结束的区间绘制。 |
1017
+ | `domContentLoadedEventStart > 0 && domContentLoadedEventEnd ≥ domContentLoadedEventStart && loadEventStart > domContentLoadedEventEnd` | 剩余资源加载 | DOMContentLoaded 已处理完成,且已到达 load 派发时间。 |
1018
+ | `activationStart > startTime ≥ 0` | 预渲染 | 页面在后台预渲染,条的终点就是用户激活的时刻。可能在加载完成之前或之后。 |
1019
+ | `loadEventStart > 0 && loadEventEnd ≥ loadEventStart && attributes.view.loading_time_source = auto && loading_time > 0 && max(loadEventEnd, loading_time) > loadEventStart` | 页面趋于稳定 | load 已处理完成,且自动 Loading Time 有效时绘制;终点取 `loadEventEnd` 与自动 `loading_time` 的较大值。 |
1020
+
1021
+ > 因为浏览器是边接收边解析,所以解析 HTML、卸载上一页面和文档请求的内容下载会有一部分重叠。
1022
+ >
1023
+ > 预渲染是在后台异步执行渲染的过程,所以预渲染页面没有前一个文档,卸载上一页面和预渲染不会同时出现。
754
1024
 
755
1025
  ### d. 后续扩展
756
1026
 
757
1027
  当前版本暂不展示,后续可按需补充:
758
1028
 
759
- | 扩展 | 计算 | 生效条件 | 说明 |
760
- | --- | --- | --- | --- |
761
- | 临时响应 | `finalResponseHeadersStart − responseStart` | `firstInterimResponseStart > 0 && finalResponseHeadersStart > 0` | 服务器先回 `103` 等临时响应时,`responseStart` 指向首个临时响应,所以内容下载可拆成「临时响应」和「最终内容下载」两段。 |
762
- | 最终内容下载 | `responseEnd − finalResponseHeadersStart` | 同上 | 从最终响应头到收完最后一个字节。|
1029
+ | 扩展 | 生效条件 | 说明 |
1030
+ | ---------------------- | --------------------------- | ---------------------------------------------------------------------- |
1031
+ | Critical-CH 重启时间点 | `criticalCHRestart > 0` | 服务器要求带上 Critical-CH 后重新请求的时间点。 |
1032
+ | 低置信度提示 | `confidence.value = low` | 在瀑布图顶部提示:这次导航数据的代表性较低。 |
1033
+ | BFCache 未命中原因 | `notRestoredReasons ≠ null` | 在 A 类、`type = back_forward` 时,展示页面没能从 BFCache 恢复的原因。 |