@blueking/open-telemetry 0.0.31 → 0.0.33

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 (32) hide show
  1. package/README.md +71 -33
  2. package/dist/bk-rum.global.js +2 -2
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/plugin.d.ts +3 -0
  5. package/dist/index.js +461 -354
  6. package/dist/index.js.map +1 -1
  7. package/dist/plugins/web-vitals.d.ts +1 -1
  8. package/dist/schema/attributes.d.ts +1 -0
  9. package/dist/schema/span.d.ts +10 -0
  10. package/package.json +1 -1
  11. package/skills/bk-rum-otele/SKILL.md +1 -1
  12. package/skills/bk-rum-otele/evals/evals.json +1 -1
  13. package/skills/bk-rum-otele/references/actions.md +16 -10
  14. package/skills/bk-rum-otele/references/api.md +6 -3
  15. package/skills/bk-rum-otele/references/architecture.md +4 -4
  16. package/skills/bk-rum-otele/references/blank-screen.md +10 -19
  17. package/skills/bk-rum-otele/references/capabilities.md +18 -18
  18. package/skills/bk-rum-otele/references/configuration.md +5 -5
  19. package/skills/bk-rum-otele/references/data-model.md +14 -16
  20. package/skills/bk-rum-otele/references/errors-security.md +9 -8
  21. package/skills/bk-rum-otele/references/extensions.md +8 -0
  22. package/skills/bk-rum-otele/references/framework-integration.md +1 -1
  23. package/skills/bk-rum-otele/references/getting-started.md +21 -2
  24. package/skills/bk-rum-otele/references/network.md +21 -22
  25. package/skills/bk-rum-otele/references/performance.md +14 -25
  26. package/skills/bk-rum-otele/references/privacy.md +1 -1
  27. package/skills/bk-rum-otele/references/session-context.md +16 -12
  28. package/skills/bk-rum-otele/references/span-protocol.md +192 -282
  29. package/skills/bk-rum-otele/references/telemetry-reference.md +97 -99
  30. package/skills/bk-rum-otele/references/transport-sampling.md +19 -14
  31. package/skills/bk-rum-otele/references/troubleshooting.md +4 -4
  32. package/skills/bk-rum-otele/references/views-routing.md +5 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  # 遥测字段字典
4
4
 
5
- 本页是当前 SDK 实际产出的 RUM Span、Resource Attribute、Span Attribute 和 Span Event 字典。它面向 Collector 接入、后端建模、查询规则、告警配置和数据验收。SDK 当前只上报 Trace Span,不产出 OpenTelemetry Metric 或 Log。
5
+ 本页是对照 `src/` 手工维护的**当前实现事实**字典,记录 SDK 实际产出的 RUM Span、Resource Attribute、Span Attribute 和 Span Event。它面向 Collector 接入、后端建模、查询规则、告警配置和数据验收。SDK 当前只上报 Trace Span,不产出 OpenTelemetry Metric 或 Log。前后端长期兼容承诺见 [RUM 语义约定](./span-protocol.md)。
6
6
 
7
7
  ## 快速定位
8
8
 
@@ -12,7 +12,7 @@
12
12
  | ---------------------- | --------------------------------------------------------------- | ------------------------------------------------- |
13
13
  | SDK 与应用 Resource | `service.*`、`deployment.environment.name`、`telemetry.sdk.*` | 哪个应用、环境、版本和 SDK 产生了数据? |
14
14
  | RUM 运行时上下文 | `session.id`、`view.id`、`action.id`、`user.id`、设备和网络字段 | 事件属于哪个 Session、View、Action 和用户上下文? |
15
- | 公共分类 | `span_type`、`outcome.type`、`outcome.reason` | 这是什么信号,结果是否正常,失败属于哪类原因? |
15
+ | 公共分类 | `span_type`、`outcome.type` | 这是什么信号,结果是否正常? |
16
16
  | 领域属性 | `resource.*`、`error.*`、`vital.*`、`long_task.*` 等 | 具体发生了什么,耗时、来源和诊断细节是什么? |
17
17
  | OTLP Envelope 与 Event | `traceId`、`spanId`、时间戳、`status`、`events` | 如何定位单条记录、关联调用链和读取异常/脚本归因? |
18
18
 
@@ -32,7 +32,7 @@
32
32
  字段存在不等于 Span 一定会被导出。当前采集链路依次受以下条件约束:
33
33
 
34
34
  1. SDK 必须启用、获得采集授权,并且当前 Session 命中确定性采样。
35
- 2. 普通 Span 导出时必须同时具备有效的 `session.id` 和 `view.id`;`browser.session` 是唯一例外,它允许没有 View,但仍必须属于已采样 Session。
35
+ 2. 普通 Span 导出时必须同时具备有效的 `session.id` 和 `view.id`;`span_type=session` 是唯一例外,它允许没有 View,但仍必须属于已采样 Session。
36
36
  3. 指向 SDK Collector 自身的请求会被过滤;请求级 `tracking.request.beforeSend` 和全局 `tracking.beforeSend` 返回 `false` 时也会丢弃 Span。
37
37
 
38
38
  因此,插件已开启但没有数据时,应先检查授权、`session.sample_rate`、Session/View 是否已建立、浏览器能力和 beforeSend 过滤,而不是只检查字段解析。
@@ -53,8 +53,8 @@
53
53
  | `traceId` | 32 位十六进制字符串 | 必有 | 16 字节 Trace ID。同一条调用链上的 Span 使用同一个值。注意注入到后端的 `traceparent` 使用的是另一个独立 trace-id,不等于本字段,两者通过 `links` 关联。 |
54
54
  | `spanId` | 16 位十六进制字符串 | 必有 | 当前 Span 的 8 字节唯一 ID,与 `traceId` 一起唯一定位本次 Span。 |
55
55
  | `parentSpanId` | 16 位十六进制字符串 | 有活动父 Span 时 | 父 Span ID。没有活动父上下文的 RUM 根 Span不包含该字段;缺失不代表数据异常。 |
56
- | `links` | link[] | 注入或探测到 Trace Header 时 | 关联的其他 Trace。`browser.resource` Span 用它指向本次请求对应的后端 Trace,每项含 `traceId`、`spanId`、`traceFlags`。后端可按 `link.trace_id` 反查 RUM Span。 |
57
- | `name` | string | 必有 | Span 名称,例如 `browser.view`、`browser.resource`。稳定一级分类使用 `span_type`,具体类别使用各领域字段查询。 |
56
+ | `links` | link[] | 注入或探测到 Trace Header 时 | 关联的其他 Trace。Resource Span 用它指向本次请求对应的后端 Trace,每项含 `traceId`、`spanId`、`traceFlags`。后端可按 `link.trace_id` 反查 RUM Span。 |
57
+ | `name` | string | 必有 | 可读的低基数 Span 名称。SDK 根据 `span_type` 和领域字段生成,稳定一级分类仍使用 `span_type` 查询。 |
58
58
  | `kind` | enum number/string | 必有 | OpenTelemetry Span Kind。SDK 内置值为 `INTERNAL` 或 `CLIENT`;不同 OTLP JSON 实现可能编码为枚举数字或名称。 |
59
59
  | `startTimeUnixNano` | epoch ns 字符串 | 必有 | Span 开始时间。OTLP JSON 使用十进制字符串保存纳秒整数,避免 JavaScript Number 精度丢失。 |
60
60
  | `endTimeUnixNano` | epoch ns 字符串 | 必有 | Span 结束时间。瞬时生命周期事件通常与开始时间相同;Resource Span 的差值表示请求或资源加载耗时。 |
@@ -72,16 +72,14 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
72
72
  | `service.version` | string | 配置 `application.version` 时 | 来自应用版本配置,通常填写发布版本或构建号,用于比较发布前后性能和错误变化。 |
73
73
  | `deployment.environment.name` | string | 必有 | 来自 `application.environment`,未配置时为 `production`。用于区分生产、预发布、测试等环境。 |
74
74
  | `session.sample_rate` | number | 必有 | 解析后的 `session.sampleRate`,范围 `0..1`。表示配置的 Session 采样概率,不表示当前某条 Span 的采样结果。 |
75
- | `telemetry.sdk.name` | string | 必有 | 固定为 `@blueking/open-telemetry`,用于识别数据生产 SDK。 |
75
+ | `telemetry.sdk.name` | string | 必有 | 固定为 `blueking`,用于识别蓝鲸浏览器 RUM SDK。 |
76
76
  | `telemetry.sdk.language` | string | 必有 | 固定为 `webjs`,表示浏览器 JavaScript SDK。 |
77
77
  | `telemetry.sdk.version` | string | 必有 | 当前 npm 包版本,用于排查字段能力或采集行为是否受 SDK 版本影响。 |
78
78
  | `user_agent.name` | string | `tracking.device !== false` 且有浏览器环境 | 从 User-Agent 识别,取值 `Edge`、`Chrome`、`Firefox`、`Safari` 或 `Other`。识别不到时为 `Other`。 |
79
79
  | `user_agent.version` | string | 能识别浏览器版本时 | 从 User-Agent 提取的浏览器主版本号,不包含次版本和补丁版本;识别不到时缺失。 |
80
80
  | `user_agent.os.name` | string | `tracking.device !== false` 且有浏览器环境 | 从 User-Agent / User-Agent Client Hints 推断,取值 `iOS`、`Android`、`macOS`、`Windows`、`Linux` 或 `Other`。 |
81
81
  | `device.type` | string | `tracking.device !== false` 且有浏览器环境 | `mobile` 或 `desktop`。根据 `userAgentData.mobile` 或移动端 User-Agent 特征推断,不代表具体硬件型号。 |
82
- | `device.memory_gib` | number | 浏览器支持 `navigator.deviceMemory` 时 | 浏览器提供的近似设备内存容量,单位 GiB。该值通常已分档并可能受隐私策略限制,不应当作精确物理内存。 |
83
-
84
- `tracking.device=false` 时 SDK 构造的 Resource 不写入设备 Resource 字段。Resource 在 SDK 初始化时经过一次 `redactAttributes`,运行期间不会随窗口或网络状态变化。
82
+ `tracking.device=false` 时 SDK 构造的 Resource 不写入设备 Resource 字段。Resource 在 SDK 初始化时经过一次 `redactAttributes`,运行期间不会随窗口或网络状态变化。当前实现不读取 `navigator.deviceMemory` 或逻辑处理器数量,因此不会出现 `device.memory_gib` 一类硬件容量字段。
85
83
 
86
84
  ## 运行时公共属性
87
85
 
@@ -91,11 +89,10 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
91
89
  | ------------------------- | -------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
92
90
  | `user.id` | string | 调用 `setUser({ id })` 后 | 业务提供的用户 ID,SDK 原样写入并经过 `redactAttributes`。建议使用不可逆标识,避免直接上传手机号、邮箱等个人信息。 |
93
91
  | `session.id` | string | Session 有效 | SDK 生成的 Session 关联 ID。15 分钟无活动或 4 小时最大生命周期到期后会更换;同一 Session 的事件可用它聚合。 |
94
- | `session.start_time` | number | Session 有效 | Session 创建时间,单位 epoch ms。它不会因用户活动续期而变化,可用于计算 Session 相对时间。 |
95
92
  | `session.type` | string | Session 有效 | 当前固定为 `user`,为未来区分其他 Session 类型保留。 |
96
93
  | `session.has_replay` | boolean | Session 有效 | 当前固定为 `false`,表示 SDK 没有随该 Session 上报 Session Replay 数据。 |
97
94
  | `view.id` | string | View 有效 | 当前页面视图的关联 ID。首次加载、有效 SPA 路由变化、BFCache 恢复或 Session 续建都会创建新 View。 |
98
- | `view.name` | string | 显式命名后 | 业务给出的可读名称,仅在 `startView({ name })` 或 `setViewName()` 调用后存在。默认不上报,展示请用 `view.name ?? view.url_template`。 |
95
+ | `view.name` | string | View 有效期内 | 视图名称优先使用 `startView({ name })` 或 `setViewName()` 的显式值,未设置时取 `view.url_template`。 |
99
96
  | `view.url` | string | View 有效 | 创建 View 时的完整 URL,经 `redactUrl` 脱敏。与当前实时 `location.href` 不一定相同。 |
100
97
  | `view.url_template` | string | View 有效 | 低基数路由模板。默认把数字 ID、UUID 和长十六进制路径段归一为 `:id`,也可由 `getUrlTemplate` 自定义。 |
101
98
  | `view.loading_type` | string | View 有效 | View 创建类型:`initial_load` 首次文档加载、`route_change` SPA 路由、`bf_cache` BFCache 恢复、`session_renewal` Session 到期后续建。 |
@@ -115,50 +112,48 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
115
112
 
116
113
  | 字段 | 类型 | 条件 | 来源与详细说明 |
117
114
  | ---------------- | ------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
118
- | `span_type` | string | 所有 SDK 原生 RUM Span | 稳定的 RUM 一级分类:`session`、`view`、`resource`、`error`、`vital`、`long_task`、`action`、`websocket` 或 `custom`。 |
119
- | `outcome.type` | string | 所有 SDK 原生 RUM Span | 归一结果:`success`、`warning`、`error`、`timeout` 或 `abort`。Fetch/XHR 主动取消使用 `abort`。 |
120
- | `outcome.reason` | string | 需要解释非正常结果时 | 当前内置值包括 `network`、`network_timeout`、`http_4xx`、`http_5xx`、`blank_screen` 和 `csp`。正常结果以及可由领域字段完整表达的结果不写该字段。 |
115
+ | `span_type` | string | 所有 SDK 原生 RUM Span | 稳定的 RUM 一级分类:`session`、`view`、`resource`、`error`、`vital`、`long_task`、`action`、`websocket` 或 `custom`。 |
116
+ | `outcome.type` | string | 所有 SDK 原生 RUM Span | 归一结果:`success`、`warning`、`error`、`timeout` 或 `abort`。Fetch/XHR 主动取消使用 `abort`。 |
121
117
 
122
- `outcome.type` 是 RUM 查询维度,OTLP `status` 是 OpenTelemetry 状态,二者用途不同。例如 Web Vital 评级不佳时为 `outcome.type=warning`,但不会把 OTLP Status 设置为 `ERROR`。
118
+ `outcome.type` 是 RUM 查询维度,OTLP `status` 是 OpenTelemetry 状态,二者用途不同。例如 Web Vital 评级不佳时为 `outcome.type=warning`,但不会把 OTLP Status 设置为 `ERROR`。当前 `buildRumSpanAttributes()` **不会写入** `outcome.reason`;HTTP 失败用 `http.response.status_code`,错误入口用 `error.source`,白屏用 `blank_screen.reason`,CSP 用 `error.source=csp`。
123
119
 
124
120
  ## Span 清单
125
121
 
126
122
  | Span 名 | Kind | `span_type` | 领域分类字段 | 默认状态/入口 | 表达的事件 |
127
123
  | ---------------------------- | -------- | ----------- | --------------------------------- | --------------------------------- | -------------------------------------------------- |
128
- | `browser.session` | INTERNAL | `session` | `session.phase` | 始终随 SDK 启动 | Session 创建、轮换和结束生命周期。 |
129
- | `browser.view` | INTERNAL | `view` | `view.phase` | 自动;可切为手动 View | 初始页面或 SPA View 的 start/update/end 快照。 |
130
- | `browser.resource` | CLIENT | `resource` | `resource.type` | 请求、静态资源默认开启 | Fetch、XHR 或静态资源加载。 |
131
- | `browser.error` | INTERNAL | `error` | `error.source=window.error` | 错误采集默认开启 | `window.error` 捕获的 JavaScript 运行时错误。 |
132
- | `browser.unhandledrejection` | INTERNAL | `error` | `error.source=unhandledrejection` | 错误采集默认开启 | 未处理的 Promise rejection。 |
133
- | `browser.resource_error` | INTERNAL | `error` | `error.source=resource` | 错误采集默认开启 | script、img、link、media 等元素资源加载失败。 |
134
- | `browser.web_vital` | INTERNAL | `vital` | `vital.metric` | 默认开启 | 单项用户体验指标及归因。 |
135
- | `action.click` | INTERNAL | `action` | `action.type=click` | 自动 Action 默认开启 | 自动点击 Action 及其页面活动、错误和挫败归因。 |
136
- | `action.custom` | INTERNAL | `action` | `action.type=custom` | `reportAction` | 主动上报的业务 Action。 |
137
- | `browser.blank_screen` | INTERNAL | `error` | `blank_screen.reason` | 默认开启 | 视口九宫格连续检测确认的白屏。 |
138
- | `browser.long_task` | INTERNAL | `long_task` | `long_task.entry_type` | `tracking.longTask`,默认关闭 | Long Animation Frame,或不支持时回退的 Long Task。 |
139
- | `csp.violation` | INTERNAL | `error` | `error.source=csp` | `tracking.cspViolation`,默认关闭 | 浏览器 `securitypolicyviolation` 事件。 |
140
- | `browser.websocket` | CLIENT | `websocket` | `websocket.phase` | `tracking.websocket`,默认关闭 | 同一 WebSocket 连接的四类生命周期事件。 |
124
+ | `session.<phase>` | INTERNAL | `session` | `session.phase` | 始终随 SDK 启动 | Session 创建、轮换和结束生命周期。 |
125
+ | `<view.name>` | INTERNAL | `view` | `view.phase` | 自动;可切为手动 View | 初始页面或 SPA View 的 start/update/end 快照。 |
126
+ | `<method> <url.template>` | CLIENT | `resource` | `resource.type` | 请求、静态资源默认开启 | Fetch、XHR 或静态资源加载。 |
127
+ | `<exception.type>` | INTERNAL | `error` | `error.source=window.error` | 错误采集默认开启 | `window.error` 捕获的 JavaScript 运行时错误。 |
128
+ | `<exception.type>` | INTERNAL | `error` | `error.source=unhandledrejection` | 错误采集默认开启 | 未处理的 Promise rejection。 |
129
+ | `ResourceError` | INTERNAL | `error` | `error.source=resource` | 错误采集默认开启 | script、img、link、media 等元素资源加载失败。 |
130
+ | `<VITAL_METRIC>` | INTERNAL | `vital` | `vital.metric` | 默认开启 | 单项用户体验指标及归因。 |
131
+ | `click <target>` | INTERNAL | `action` | `action.type=click` | 自动 Action 默认开启 | 自动点击 Action 及其页面活动、错误和挫败归因。 |
132
+ | `<action.name>` | INTERNAL | `action` | `action.type=custom` | `reportAction({ name })` | 主动上报的业务 Action;Span 名使用业务提供的 `action.name`。 |
133
+ | `blank_screen.<reason>` | INTERNAL | `error` | `blank_screen.reason` | 默认开启 | 视口九宫格连续检测确认的白屏。 |
134
+ | `<long_task.entry_type>` | INTERNAL | `long_task` | `long_task.entry_type` | `tracking.longTask`,默认关闭 | Long Animation Frame,或不支持时回退的 Long Task。 |
135
+ | `csp.<effective_directive>` | INTERNAL | `error` | `error.source=csp` | `tracking.cspViolation`,默认关闭 | 浏览器 `securitypolicyviolation` 事件。 |
136
+ | `websocket.<phase>` | CLIENT | `websocket` | `websocket.phase` | `tracking.websocket`,默认关闭 | 同一 WebSocket 连接的四类生命周期事件。 |
141
137
  | `custom.<name>` | INTERNAL | `custom` | Span 名 | `reportCustomEvent` | 主动上报的业务事件。 |
142
138
 
139
+ Span 名只使用领域分类字段和业务提供的稳定名称。唯一 ID、完整 URL、错误消息、时间戳和数值不参与命名。
140
+
143
141
  ## Session 字段
144
142
 
145
- 适用于 `browser.session`。Session 默认在 15 分钟无活动后过期,并受 4 小时最大生命周期限制。
143
+ 适用于 `span_type=session`。Session 默认在 15 分钟无活动后过期,并受 4 小时最大生命周期限制。
146
144
 
147
- | 字段 | 类型 | 条件/取值 | 来源与详细说明 |
148
- | -------------------------- | ------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
149
- | `session.phase` | string | `start`、`rotate`、`end` | `start` 表示没有可复用记录时创建;`rotate` 表示旧 Session 到期后创建新 Session;`end` 表示当前 Session 失效。 |
150
- | `session.id` | string | 所有阶段 | 当前生命周期事件所描述的 Session ID。`end` 事件写旧 ID,`rotate` 事件写新 ID。 |
151
- | `session.start_time` | number | 所有阶段,epoch ms | 该 Session 最初创建时间。`end` 时仍保留原始开始时间,不是结束时间。 |
152
- | `session.type` | string | 所有阶段,固定 `user` | 表示按真实用户浏览活动划分的 Session。 |
153
- | `session.has_replay` | boolean | 所有阶段,固定 `false` | 明确当前 SDK 没有为该 Session 关联回放数据。 |
154
- | `session.lifecycle.reason` | string | 所有阶段 | `init`:初始化时创建;`inactivity`:15 分钟无活动;`maxLifetime`:达到 4 小时上限;`external`:共享存储被删除、替换或记录无效,导致本 Tab 当前 Session 失效。 |
155
- | `session.previous_id` | string | `rotate` 且能识别旧 Session 时 | 新 Session 的前一个 ID,用于串联因 `inactivity` 或 `maxLifetime` 发生的轮换。首次 `start` 通常缺失。 |
145
+ | 字段 | 类型 | 条件/取值 | 来源与详细说明 |
146
+ | -------------------- | ------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
147
+ | `session.phase` | string | `start`、`rotate`、`end` | `start` 表示没有可复用记录时创建;`rotate` 表示旧 Session 到期后创建新 Session;`end` 表示当前 Session 失效。 |
148
+ | `session.id` | string | 所有阶段 | 当前生命周期事件所描述的 Session ID。`end` 事件写旧 ID,`rotate` 事件写新 ID。 |
149
+ | `session.type` | string | 所有阶段,固定 `user` | 表示按真实用户浏览活动划分的 Session。 |
150
+ | `session.has_replay` | boolean | 所有阶段,固定 `false` | 明确当前 SDK 没有为该 Session 关联回放数据。 |
156
151
 
157
- Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 View;结束 Session 时也会先结束当前 View。
152
+ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 View;结束 Session 时也会先结束当前 View。过期原因(`init` / `inactivity` / `maxLifetime` / `external`)只出现在插件内部的 `notifySessionLifecycle` 事件上,**不会**写成 Span Attribute;`session.start_time`、`session.lifecycle.reason`、`session.previous_id` 当前均不上报。
158
153
 
159
154
  ## View 字段
160
155
 
161
- 适用于 `browser.view`。同一 View 会产生多条版本递增的生命周期快照,而不是一条持续到页面离开的长 Span。
156
+ 适用于 `span_type=view`。同一 View 会产生多条版本递增的生命周期快照,而不是一条持续到页面离开的长 Span。
162
157
 
163
158
  | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
164
159
  | -------------------------- | ------ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
@@ -166,7 +161,7 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
166
161
  | `view.id` | string | 所有阶段 | View 关联 ID。同一 View 的 start/update/end 使用相同值,可与该 View 内其他 Span 关联。 |
167
162
  | `view.version` | number | 从 1 递增 | 每次 `emitViewEvent` 递增;用于恢复同一 View 生命周期快照的先后顺序。 |
168
163
  | `view.started_at` | number | epoch ms | View 开始时间。初始 View 使用 `performance.timeOrigin`,路由/BFCache/续建 View 使用创建时刻。 |
169
- | `view.name` | string | 显式命名后 | 业务可读名称,仅 `startView({ name })` 或 `setViewName()` 后存在;未命名的 View 不带该字段。 |
164
+ | `view.name` | string | View 有效期内 | 优先使用 `startView({ name })` 或 `setViewName()` 的显式值,未设置时取 `view.url_template`。 |
170
165
  | `view.url` | string | 所有阶段 | 创建 View 时的 URL,经 `redactUrl` 脱敏;在该 View 生命周期内保持不变。 |
171
166
  | `view.url_template` | string | 所有阶段 | 当前 URL 的低基数路由模板。数字 ID、UUID、长十六进制段默认折叠为 `:id`,用于稳定聚合动态路由。 |
172
167
  | `view.previous_url_template` | string | 所有阶段 | 前序 URL 的低基数路由模板;使用 `tracking.view.getUrlTemplate` 生成,初始 View 为空字符串。 |
@@ -186,7 +181,7 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
186
181
 
187
182
  ## 请求与静态资源字段
188
183
 
189
- 适用于 `browser.resource`。Fetch/XHR 由请求插件建 Span,再合并匹配的 Resource Timing;静态资源由 Resource Observer 直接建 Span。
184
+ 适用于 `span_type=resource`。Fetch/XHR 由请求插件建 Span,再合并匹配的 Resource Timing;静态资源由 Resource Observer 直接建 Span。
190
185
 
191
186
  | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
192
187
  | --------------------------------- | ------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -195,7 +190,7 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
195
190
  | `server.address` | string | URL 可解析 | URL 的 `hostname`,不含端口。相对 URL 会基于当前页面地址解析。模板不含 host,跨域同路径会聚到一起,需要区分来源时配合该字段。 |
196
191
  | `server.port` | number | URL 显式包含端口 | URL 的显式端口号。使用协议默认端口且 URL 未写端口时缺失。 |
197
192
  | `resource.type` | string | 必有 | Fetch/XHR 为 `fetch`/`xhr`;静态资源使用 `PerformanceResourceTiming.initiatorType`,为空时为 `other`,常见还有 `script`、`link`、`img`、`css`。 |
198
- | `http.request.method` | string | Fetch/XHR | 归一为大写的 HTTP 方法,例如 `GET`、`POST`。静态资源通常没有可用的请求方法,因此缺失。 |
193
+ | `http.request.method` | string | 所有 Resource | Fetch/XHR 归一为实际的大写 HTTP 方法;其他 Resource 固定为 `GET`。 |
199
194
  | `http.response.status_code` | number | 获得真实 HTTP Response | HTTP 响应状态,只写大于 `0` 的有效状态码。abort、timeout、网络失败和 opaque Response 没有可用状态码时缺失,不使用 `0` 代替。 |
200
195
  | `resource.size` | number | 有 Resource Timing 详情 | `decodedBodySize`,解压后响应体大小,单位 bytes,不含响应头;缓存命中也能反映真实体积。Fetch/XHR 合并 Resource Timing 后同样会带上。 |
201
196
  | `resource.protocol` | string | 浏览器提供 `nextHopProtocol` | 实际传输协议,例如 `h2`、`h3`、`http/1.1`;浏览器无法判断时可能返回空字符串。 |
@@ -239,23 +234,25 @@ Link 的 `trace_id` / `span_id` 优先取自解析结果;`sw8` 这类无法映
239
234
 
240
235
  如果公共时间点缺失、不是有限数或顺序异常,SDK 会放弃整组阶段字段,避免产生负耗时。Resource Timing 的跨域详细信息还受 `Timing-Allow-Origin` 响应头限制。
241
236
 
242
- 请求结果映射:HTTP `408/504` 为 `outcome.type=timeout,outcome.reason=network_timeout`;其他 `4xx` 为 `error/http_4xx`;其他 `5xx` 为 `error/http_5xx`;Fetch AbortError 或 XHR `abort` 为 `abort` 且不写 reason;Fetch TimeoutError 或 XHR `timeout` 为 `timeout/network_timeout`;其他网络失败为 `error/network`;其余为 `success` 且不写 reason。
237
+ 请求结果映射(只写 `outcome.type`,不写 `outcome.reason`):HTTP `408/504` 为 `timeout`;其他 `4xx`/`5xx` 为 `error`;Fetch AbortError 或 XHR `abort` 为 `abort`;Fetch TimeoutError 或 XHR `timeout` 为 `timeout`;其他网络失败为 `error`;其余为 `success`。细分失败原因请用 `http.response.status_code` 或 Fetch/XHR 的 exception Event。
243
238
 
244
239
  ## 错误字段
245
240
 
246
- 三类自动浏览器错误都设置 `outcome.type=error`、OTLP Status `ERROR`,并记录 `exception` Span Event。错误来源由 `error.source` 表达,不重复写入 `outcome.reason`。
241
+ 三类自动浏览器错误都设置 `outcome.type=error`、OTLP Status `ERROR`,并记录 `exception` Span Event。错误来源由 `error.source` 表达。
247
242
 
248
243
  | 字段 | 类型 | 适用范围 | 来源与详细说明 |
249
244
  | -------------------- | ------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
250
245
  | `error.message` | string | 三类自动错误 | 归一后的错误消息。Error 使用 `message`,字符串直接使用,其他值优先 JSON 序列化,失败时转为字符串。资源加载错误消息会包含资源原始 URL,应使用 `redactAttributes` 做额外脱敏。 |
251
246
  | `error.handled` | boolean | 三类自动错误 | 当前自动采集固定为 `false`,表示该错误来自未处理的全局错误入口;不代表业务代码完全没有 try/catch。 |
252
247
  | `error.source` | string | 三类自动错误/CSP | `window.error`、`unhandledrejection`、`resource`;CSP Span 固定为 `csp`。用于区分采集入口。 |
253
- | `code.filepath` | string | `browser.error` | `ErrorEvent.filename`,即浏览器报告的脚本文件地址。浏览器未提供或跨域屏蔽时可能为空。 |
254
- | `code.lineno` | number | `browser.error` | `ErrorEvent.lineno`,错误在脚本中的 1-based 行号;浏览器无法定位时可能为 `0`。 |
255
- | `code.column` | number | `browser.error` | `ErrorEvent.colno`,错误列号;具体是否 0-based 由浏览器实现决定。 |
256
- | `error.cross_origin` | boolean | 跨域 `Script error.` | 仅当没有 Error 对象和 filename,且消息为 `Script error.` 时写 `true`,用于识别被同源策略屏蔽详情的脚本错误。 |
257
- | `url.full` | string | `browser.resource_error` | 加载失败元素的 `src`、`href` 或 `currentSrc`,经 `redactUrl` 脱敏。浏览器拿不到资源地址时可能为空字符串。 |
258
- | `html.tag` | string | `browser.resource_error` | 失败元素的 `tagName`,浏览器通常返回大写,例如 `SCRIPT`、`IMG`、`LINK`,可用于按资源载体分类。 |
248
+ | `code.filepath` | string | `error.source=window.error` | `ErrorEvent.filename`,即浏览器报告的脚本文件地址。浏览器未提供或跨域屏蔽时可能为空。 |
249
+ | `code.lineno` | number | `error.source=window.error` | `ErrorEvent.lineno`,错误在脚本中的 1-based 行号;浏览器无法定位时可能为 `0`。 |
250
+ | `code.column` | number | `error.source=window.error` | `ErrorEvent.colno`,错误列号;具体是否 0-based 由浏览器实现决定。 |
251
+ | `url.full` | string | `error.source=resource` | 加载失败元素的 `src`、`href` 或 `currentSrc`,经 `redactUrl` 脱敏。浏览器拿不到资源地址时可能为空字符串。 |
252
+
253
+ 当前 **不上报** `error.cross_origin` 或 `html.tag`。跨域脚本错误只能通过 `error.message` 为 `Script error.`、且 `code.filepath` 为空来识别。资源加载失败的元素标签只出现在 `error.message` 里(格式 `Resource load failed: <tag> <原始 URL>`),需要按标签聚合时应在服务端解析该文本。
254
+
255
+ 注意 `error.source=resource` 的 `error.message` 携带的是 **未脱敏** 的资源 URL(`url.full` 才是脱敏后的值)。有敏感 URL 风险时用 `redactAttributes` 重写 `error.message`。
259
256
 
260
257
  `context.attributes.error()` 返回的任意业务 Attribute 会合并到三类自动错误 Span,并统一经过 `redactAttributes`。字段命名和类型由接入方负责。
261
258
 
@@ -265,7 +262,7 @@ Link 的 `trace_id` / `span_id` 优先取自解析结果;`sw8` 这类无法映
265
262
 
266
263
  | Event 字段 | 类型 | 条件 | 来源与详细说明 |
267
264
  | ---------------------- | ------ | ----------------- | --------------------------------------------------------------------------------------------- |
268
- | `exception.type` | string | 能识别异常类型 | Error 的 `name`,或 SDK 为非 Error 值补充的类型,例如 `UnhandledRejection`、`ResourceError`。 |
265
+ | `exception.type` | string | 能识别异常类型 | Error 的 `name`;非 Error 值时由 SDK 补类型:Promise rejection 为 `UnhandledRejection`,资源错误为 `ResourceError`,`window.error` 抛非 Error 值时为 `window.error`。 |
269
266
  | `exception.message` | string | 能提取异常消息 | Error message 或归一后的异常文本,用于错误检索和展示。 |
270
267
  | `exception.stacktrace` | string | Error 带 stack 时 | 浏览器提供的调用栈。跨域、非 Error rejection 或浏览器安全策略可能导致缺失。 |
271
268
 
@@ -273,55 +270,52 @@ Link 的 `trace_id` / `span_id` 优先取自解析结果;`sw8` 这类无法映
273
270
 
274
271
  ## Web Vitals 字段
275
272
 
276
- `browser.web_vital` 上报 CLS、FCP、INP、LCP 和 TTFB。FCP/LCP/TTFB 由 `web-vitals/attribution` 采集导航级指标;CLS/INP 按 SDK View 边界汇总,View 结束时上报。
273
+ `span_type=vital` 上报 CLS、FCP、INP、LCP 和 TTFB。FCP/LCP/TTFB 由 `web-vitals/attribution` 采集导航级指标;CLS/INP 按 SDK View 边界汇总,View 结束时上报。
277
274
 
278
- | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
279
- | -------------- | ------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
280
- | `vital.metric` | string | 必有 | 指标名的小写值:`cls`、`fcp`、`inp`、`lcp`、`ttfb`。用于同一 Span 名下区分指标。 |
281
- | `vital.value` | number | 必有 | 指标值。CLS 是无量纲分数;FCP、INP、LCP、TTFB 单位均为 ms。非有限值不会上报。 |
282
- | `vital.rating` | string | 必有 | `good`、`needs-improvement` 或 `poor`。当前 good/needs-improvement/poor 分界:CLS `≤0.1/≤0.25/>0.25`;INP `≤200/≤500/>500ms`;FCP `≤1800/≤3000/>3000ms`;LCP `≤2500/≤4000/>4000ms`;TTFB `≤800/≤1800/>1800ms`。 |
283
- | `vital.id` | string | 必有 | 单条 Vital 的唯一 ID。FCP/LCP/TTFB 沿用 `web-vitals` ID;按 View 汇总的 CLS/INP 由 SDK 生成。 |
275
+ | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
276
+ | -------------- | ------ | --------- | ------------------------------------------------------------------------------------------------------- |
277
+ | `vital.metric` | string | 必有 | 指标名的小写值:`cls`、`fcp`、`inp`、`lcp`、`ttfb`。Span 名使用对应的大写值。 |
278
+ | `vital.value` | number | 必有 | 指标值。CLS 是无量纲分数;FCP、INP、LCP、TTFB 单位均为 ms。非有限值不会上报。 |
279
+ | `vital.id` | string | 必有 | 单条 Vital 的唯一 ID。FCP/LCP/TTFB 沿用 `web-vitals` ID;按 View 汇总的 CLS/INP 由 SDK 生成。 |
284
280
 
285
- `vital.rating=good` 映射为 `outcome.type=success`;其他评级映射为 `outcome.type=warning`。具体体验评级由 `vital.rating` 表达,不重复写入 `outcome.reason`。
281
+ `web-vitals` / SDK 内部仍会计算 rating,但 **不会** 写入 `vital.rating`。`rating=good` 映射为 `outcome.type=success`,其余映射为 `outcome.type=warning`。当前分界:CLS `≤0.1/≤0.25`;INP `≤200/≤500ms`;FCP/LCP/TTFB 沿用 `web-vitals` 默认阈值。也不写入 `navigationType`。
286
282
 
287
283
  ### LCP Attribution
288
284
 
285
+ `onLCP` 回调会抽取以下字段;缺失表示浏览器或 `web-vitals` 未提供,不代表 LCP 无效。
286
+
289
287
  | 字段 | 类型 | 单位/条件 | 来源与详细说明 |
290
288
  | ---------------------------------- | ------ | ----------------------- | ---------------------------------------------------------------------------------- |
291
289
  | `vital.lcp.url` | string | LCP 是图片等 URL 资源时 | LCP 资源 URL,经 `redactUrl` 脱敏。文本 LCP 没有资源 URL,因此缺失。 |
292
290
  | `vital.lcp.target` | string | 能定位 LCP 元素时 | `web-vitals` 生成的目标元素选择器/描述,用于定位拖慢最大内容绘制的 DOM 元素。 |
293
- | `vital.lcp.element_render_delay` | number | ms | LCP 资源加载完成到元素最终绘制之间的耗时;无独立资源时表示等待元素绘制的主要时间。 |
294
- | `vital.lcp.resource_load_duration` | number | ms | LCP 资源自身从请求开始到响应结束的下载耗时;文本 LCP 或无独立资源时通常为 `0`。 |
295
- | `vital.lcp.time_to_first_byte` | number | ms | 从导航开始到主文档响应首字节的时间,是 LCP 总耗时的服务端/网络前置部分。 |
291
+ | `vital.lcp.element_render_delay` | number | ms | LCP 资源加载完成到元素最终绘制之间的耗时。 |
292
+ | `vital.lcp.resource_load_duration` | number | ms | LCP 资源自身从请求开始到响应结束的下载耗时。 |
293
+
294
+ 当前 **不上报** `vital.lcp.time_to_first_byte`。
296
295
 
297
296
  ### CLS Attribution
298
297
 
299
- | 字段 | 类型 | 单位/条件 | 来源与详细说明 |
300
- | -------------------------------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
301
- | `vital.cls.largest_shift_target` | string | 能定位元素时 | 对 CLS 贡献最大的单次布局偏移中的首个目标元素描述。按 SDK View 汇总时取最大 Session Window 内最大的单次偏移目标。 |
302
- | `vital.cls.largest_shift_value` | number | 无量纲 | 上述单次布局偏移的分数,不是整个 `vital.value`;可用于判断 CLS 是否由一次大跳动还是多次小跳动组成。 |
303
- | `vital.cls.load_state` | string | 当前不产生 | 字段提取逻辑已预留,用于表达最大偏移发生时的文档加载阶段;当前 CLS 由 SDK 按 View 自行汇总,未向归因对象写入 load state,因此 Collector 数据中不会出现。 |
298
+ CLS 由 SDK 按 View 自行汇总,上报时 `attribution` 为空对象。因此 `vital.cls.load_state`、`vital.cls.largest_shift_target`、`vital.cls.largest_shift_value` **当前均不产生**。
304
299
 
305
300
  CLS 忽略 `hadRecentInput=true` 的偏移,并按“相邻偏移间隔小于 1 秒、窗口最长 5 秒”的 Session Window 规则取最大窗口累计值。View 结束时即使没有布局偏移也会上报 `vital.value=0`。
306
301
 
307
302
  ### INP Attribution
308
303
 
304
+ View 结束时,SDK 把选中的 p98 候选写入以下字段:
305
+
309
306
  | 字段 | 类型 | 单位/条件 | 来源与详细说明 |
310
307
  | ------------------------------- | ------ | ---------------- | -------------------------------------------------------------------------------------------------------- |
311
308
  | `vital.inp.interaction_target` | string | 能定位交互元素时 | 触发 INP 候选交互的元素描述。SDK 优先 `data-bk-action-name`、`aria-label`、`name`,否则使用小写 tag 名。 |
312
- | `vital.inp.interaction_type` | string | 必有 | SDK 按 View 汇总时为 Performance Event 名,例如 `click`、`keydown`;用于识别哪类输入产生延迟。 |
313
- | `vital.inp.input_delay` | number | ms | 从用户输入发生到浏览器开始执行事件处理器的延迟,主要反映主线程此前被其他任务占用。 |
314
- | `vital.inp.processing_duration` | number | ms | 从事件处理开始到处理结束的耗时,主要反映业务事件处理器本身及同步工作。 |
315
- | `vital.inp.presentation_delay` | number | ms | 事件处理完成到下一帧呈现的耗时,包含样式、布局、绘制、合成等后续工作。三段之和应近似 `vital.value`。 |
309
+ | `vital.inp.interaction_type` | string | 必有 | Performance Event 名,例如 `click`、`keydown`。 |
310
+ | `vital.inp.input_delay` | number | ms | 从用户输入发生到浏览器开始执行事件处理器的延迟。 |
311
+ | `vital.inp.processing_duration` | number | ms | 从事件处理开始到处理结束的耗时。 |
312
+ | `vital.inp.presentation_delay` | number | ms | 事件处理完成到下一帧呈现的耗时。三段之和应近似 `vital.value`。 |
316
313
 
317
314
  INP 只在 View 内至少观察到一次带 `interactionId` 的 Event Timing 时上报;Performance Observer 的 `durationThreshold` 为 40ms,值最大限制为 60,000ms。SDK 保留最慢的 10 个交互候选,并按交互数量选择近似 p98 候选。
318
315
 
319
316
  ### FCP Attribution
320
317
 
321
- | 字段 | 类型 | 单位/条件 | 来源与详细说明 |
322
- | ------------------------------ | ------ | --------- | --------------------------------------------------------------------------------------------------------------------- |
323
- | `vital.fcp.time_to_first_byte` | number | ms | 导航开始到主文档响应首字节的时间。`FCP - TTFB` 可近似观察首字节后到首次内容绘制的前端阶段。 |
324
- | `vital.fcp.load_state` | string | 必有 | FCP 发生时的文档加载阶段,例如 `loading`、`dom-interactive`、`dom-content-loaded`、`complete`;越早绘制通常体验越好。 |
318
+ `onFCP` 只上报公共 `vital.*` 字段。`pickAttribution()` 对 `FCP` 没有抽取分支,因此 **不上报** `vital.fcp.time_to_first_byte` 或 `vital.fcp.load_state`。
325
319
 
326
320
  ### TTFB Attribution
327
321
 
@@ -340,33 +334,30 @@ Attribution 字段受浏览器能力和指标实现影响,缺失不代表指
340
334
  | ------------------------- | -------- | ------------------------ | -------------- | --------------------------------------------------------------------------------------------------------- |
341
335
  | `action.id` | string | 必有 | 必有 | 当前 Action 的唯一 ID。自动 Action 活动期间,其他 Span 上的同名运行时字段也是单个 string。 |
342
336
  | `action.type` | string | 固定 `click` | 固定 `custom` | 区分自动点击和 `reportAction` 主动上报。 |
343
- | `action.name` | string | `Click on <target>` | payload `name` | 可读名称。自动点击目标名默认来自显式 `data-bk-action-name`,启用文本采集后才会回退到可访问名称/DOM 文本。 |
337
+ | `action.name` | string | `click <target>` | payload `name` | 可读的低基数名称,也是 Span 名。自动点击目标名默认来自显式 `data-bk-action-name`,启用文本采集后才会回退到可访问名称/DOM 文本。 |
344
338
  | `action.target.name` | string | 必有 | 不写 | 自动点击提取的目标名称,最多 100 字符;默认隐私模式下未显式命名时通常为小写 tag 名。 |
345
- | `action.target.tag` | string | 必有 | 不写 | 实际点击目标的原始 `tagName`,SDK 转为小写,用于按按钮、链接等元素类型聚合。 |
346
- | `action.loading_time` | number | 点击后有可观察页面活动时 | 不写 | 单位 ms,从点击发生到相关请求、资源、Long Task、DOM 活动安静的耗时;无页面副作用时不写,而不是 `0`。 |
339
+ | `action.target.tag` | string | 必有 | 不写 | 实际点击目标的原始 `tagName`,SDK 转为小写。 |
347
340
  | `action.frustration.type` | string[] | 检出挫败信号时 | 不写 | 可包含 `rage_click`、`dead_click`、`error_click`;一次 Action 可同时命中多个值。 |
348
341
 
342
+ 点击后若有可观察页面活动,SDK 用 Span 的 `startTimeUnixNano`/`endTimeUnixNano` 表达持续时间,**不上报** `action.loading_time` 属性。无页面副作用时 Span 起止时间相同。
343
+
349
344
  `rage_click` 表示 1 秒内、100px 范围内连续至少三次点击;`dead_click` 表示点击后没有页面活动、输入、滚动或选择等反馈(链接、表单输入等会排除);`error_click` 表示 Action 生命周期内出现错误。有错误或任一挫败信号时为 `outcome.type=warning`,具体类型只由 `action.frustration.type` 表达。
350
345
 
351
- `reportAction({ attributes })` 的业务 Attribute 会合并到 `action.custom`,但固定分类和事件字段由 SDK 写入。业务应避免复用本页保留字段名。
346
+ `reportAction({ attributes })` 的业务 Attribute 会合并到手动 Action Span,但固定分类和事件字段由 SDK 写入。业务应避免复用本页保留字段名。
352
347
 
353
348
  ## 白屏字段
354
349
 
355
350
  白屏插件在页面活动稳定后对视口九宫格采样,并在默认 200ms 间隔后再次确认;每个 View 最多上报一次。
356
351
 
357
- | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
358
- | ----------------------------------- | ------- | ------------------ | -------------------------------------------------------------------------------------------------- |
359
- | `blank_screen.reason` | string | 必有 | `missing_root`:配置的根节点不存在;`empty_viewport`:根节点存在,但有效采样点的空白比例达到阈值。 |
360
- | `blank_screen.empty_ratio` | number | `0..1` | `empty_sample_count / valid_sample_count`。默认阈值为 `0.8`;根节点缺失时固定为 `1`。 |
361
- | `blank_screen.sample_count` | number | 必有,当前固定 `9` | 视口 20%、50%、80% 横纵坐标组合形成的九宫格总采样点数。 |
362
- | `blank_screen.valid_sample_count` | number | 必有 | 参与空白比例计算的点数,等于总采样点减去 ignored 点。为 `0` 时不报告白屏。 |
363
- | `blank_screen.empty_sample_count` | number | 必有 | 有效采样点中,没有发现根节点内可见内容元素的点数。 |
364
- | `blank_screen.ignored_sample_count` | number | 必有 | 命中 loading、Skeleton 或业务 `ignoreSelectors` 的点数;这些点从比例分母中排除。 |
365
- | `blank_screen.root_selector` | string | 必有 | 实际检测使用的根节点 CSS selector,默认 `body`。用于判断是否因挂载点配置错误产生 `missing_root`。 |
366
- | `blank_screen.root_found` | boolean | 必有 | 是否找到根节点。`false` 与 `reason=missing_root` 对应。 |
367
- | `blank_screen.center_element` | string | 必有,可能为空 | 视口中心最上层元素的小写 tag,存在 ID 时为 `tag#id`;用于快速判断遮罩、容器或空 body。 |
352
+ | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
353
+ | ----------------------------- | ------ | ------------------ | -------------------------------------------------------------------------------------------------- |
354
+ | `blank_screen.reason` | string | 必有 | `missing_root`:配置的根节点不存在,检测回退到 `body`/`documentElement`;`empty_viewport`:配置根节点存在。 |
355
+ | `blank_screen.empty_ratio` | number | `0..1` | `emptyCount / validCount`。默认阈值为 `0.8`。根节点缺失时仍是回退后的实际比例,不是固定 `1`。 |
356
+ | `blank_screen.empty_sample_count` | number | 必有 | 有效采样点中,没有发现根节点内可见内容元素的点数。 |
368
357
 
369
- 该 Span 固定为 `outcome.type=error,outcome.reason=blank_screen`,但检测是基于采样点的启发式判断,应结合截图、错误和 View 数据进一步确认。
358
+ 当前 **不上报** `blank_screen.sample_count`、`valid_sample_count`、`ignored_sample_count`、`root_selector`、`root_found`、`center_element`。分母为 0 时不报告白屏。
359
+
360
+ 该 Span 固定为 `span_type=error`、`outcome.type=error`,不写 `outcome.reason`,也不设置 OTLP Status ERROR,不记录 exception Event。检测是基于采样点的启发式判断,应结合错误和 View 数据进一步确认。
370
361
 
371
362
  ## Long Task 字段
372
363
 
@@ -378,14 +369,14 @@ Attribution 字段受浏览器能力和指标实现影响,缺失不代表指
378
369
  | ------------------------------------ | ------ | ------------------------------- | -------------------------------------------------------------------------------------------------- |
379
370
  | `long_task.id` | string | 必有 | 当前 Long Task/LoAF 事件的随机唯一 ID,用于关联其 Span Event。 |
380
371
  | `long_task.entry_type` | string | 必有 | `long-animation-frame` 或 `long-task`,表示使用的浏览器 Performance Entry 类型。 |
381
- | `long_task.duration` | number | 必有,ms | 整个 LoAF/Long Task 持续时间,来源 `PerformanceEntry.duration`。 |
382
372
  | `long_task.name` | string | 必有 | 浏览器 Performance Entry 的 `name`;Legacy Long Task 常见为 `self` 或跨上下文归因名称。 |
383
- | `long_task.start_time` | number | 仅 LoAF,相对 timeOrigin ms | LoAF 的 `startTime`。Span 自身开始时间已转换为 epoch,这个字段保留原始 Performance Timeline 坐标。 |
384
- | `long_task.blocking_duration` | number | 仅 LoAF,ms | 浏览器计算的阻塞时间,表示超出可接受帧预算、真正阻塞交互响应的部分,不等于完整 `duration`。 |
373
+ | `long_task.blocking_duration` | number | 仅 LoAF,ms | 浏览器计算的阻塞时间,表示超出可接受帧预算、真正阻塞交互响应的部分,不等于完整持续时间。 |
385
374
  | `long_task.first_ui_event_timestamp` | number | LoAF 提供时,相对 timeOrigin ms | 该帧内首个 UI Event 的时间点;可判断长帧是否直接阻塞用户输入。 |
386
375
  | `long_task.render_start` | number | LoAF 提供时,相对 timeOrigin ms | 浏览器开始本帧渲染阶段的时间点。 |
387
376
  | `long_task.style_and_layout_start` | number | LoAF 提供时,相对 timeOrigin ms | 本帧开始样式计算和布局的时间点,可与 `render_start` 分析渲染阶段开销。 |
388
377
 
378
+ Span 持续时间就是 `PerformanceEntry.duration`(起止时间已转换为 epoch)。当前 **不上报** `long_task.duration` 或 `long_task.start_time` Attribute;需要原始 Performance Timeline 坐标时,用 `long_task.render_start` 等 LoAF 字段,或从 Span 起始时间减去 Resource 上的 SDK 时间基准。
379
+
389
380
  ### `long_task.script` Span Event
390
381
 
391
382
  每个 LoAF `scripts` 条目生成一个同名 Event;Event 自身时间戳为 `performance.timeOrigin + script.startTime`。
@@ -419,7 +410,7 @@ Legacy Long Task 的每个 attribution 条目生成一个 Event,Event 时间
419
410
 
420
411
  ## CSP 字段
421
412
 
422
- 适用于 `csp.violation`,来自浏览器 `SecurityPolicyViolationEvent`。该 Span 固定为 `outcome.type=error,outcome.reason=csp,error.source=csp`。
413
+ 适用于 `error.source=csp`,来自浏览器 `SecurityPolicyViolationEvent`。该 Span 固定为 `span_type=error`、`outcome.type=error`、`error.source=csp`,不写 `outcome.reason`,也不设置 OTLP Status ERROR。
423
414
 
424
415
  | 字段 | 类型 | 条件 | 来源与详细说明 |
425
416
  | ------------------------- | ------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
@@ -452,7 +443,7 @@ Legacy Long Task 的每个 attribution 条目生成一个 Event,Event 时间
452
443
  | `websocket.close.reason` | string | 仅 `close` | 对端/调用方提供的关闭原因文本,可能为空。该值不是 URL,不经过 `redactUrl`,敏感内容应由 `redactAttributes` 清理。 |
453
444
  | `websocket.close.was_clean` | boolean | 仅 `close` | 浏览器判断连接是否完成干净关闭握手;`false` 常见于网络中断或异常终止。 |
454
445
 
455
- `error` 阶段设置 `outcome.type=error,outcome.reason=network`;其他阶段为 `outcome.type=success` 且不写 reason。SDK 当前不采集 WebSocket 消息内容、数量或字节数。
446
+ `error` 阶段设置 `outcome.type=error`;其他阶段为 `outcome.type=success`。当前不写 `outcome.reason`。SDK 不采集 WebSocket 消息内容、数量或字节数。
456
447
 
457
448
  ## Custom Event 字段
458
449
 
@@ -485,8 +476,15 @@ Legacy Long Task 的每个 attribution 条目生成一个 Event,Event 时间
485
476
  当前源码不会产生:
486
477
 
487
478
  - `/v1/metrics`、`/v1/logs` 请求,以及 Counter、Histogram、Gauge、LogRecord。
488
- - `session.duration`、`view.duration`;持续时间应由服务端根据生命周期事件派生。
489
- - `vital.cls.load_state`;字段提取代码已预留,但当前按 View 汇总的 CLS 不提供该归因值。
479
+ - `session.duration`、`view.duration`、`session.start_time`、`session.lifecycle.reason`、`session.previous_id`。
480
+ - `outcome.reason`;失败细分由领域字段表达。
481
+ - `vital.rating`、`vital.cls.*` 归因、`vital.fcp.*` 归因、`vital.lcp.time_to_first_byte`。
482
+ - `action.loading_time`;持续时间由 Span 起止时间表达。
483
+ - `blank_screen.sample_count`、`valid_sample_count`、`ignored_sample_count`、`root_selector`、`root_found`、`center_element`。
484
+ - `long_task.duration`、`long_task.start_time`。
485
+ - `error.cross_origin`、`html.tag`。
486
+ - `device.memory_gib` 及逻辑处理器数字段;Device Resource 只读 UA/UA-CH,不读 `navigator.deviceMemory` 或 `hardwareConcurrency`。
487
+ - `tracestate`;SDK 既不注入也不记录。
490
488
  - Action、Resource、Error、Long Task count;计数和分布应从原始 Span 聚合。
491
489
  - 错误 fingerprint/group;错误分组由服务端根据 exception、message、stack 等字段计算。
492
490
  - HTTP request/response Body、Header;Trace Context 注入不代表采集请求内容。
@@ -38,8 +38,8 @@ https://rum.example.com/collector/v1/rum
38
38
  { "key": "service.name", "value": { "stringValue": "order-center" } },
39
39
  { "key": "session.sample_rate", "value": { "intValue": 1 } },
40
40
  { "key": "telemetry.sdk.language", "value": { "stringValue": "webjs" } },
41
- { "key": "telemetry.sdk.name", "value": { "stringValue": "@blueking/open-telemetry" } },
42
- { "key": "telemetry.sdk.version", "value": { "stringValue": "0.0.22" } }
41
+ { "key": "telemetry.sdk.name", "value": { "stringValue": "blueking" } },
42
+ { "key": "telemetry.sdk.version", "value": { "stringValue": "0.0.29" } }
43
43
  ],
44
44
  "droppedAttributesCount": 0
45
45
  },
@@ -50,13 +50,12 @@ https://rum.example.com/collector/v1/rum
50
50
  {
51
51
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
52
52
  "spanId": "00f067aa0ba902b7",
53
- "name": "browser.resource",
53
+ "name": "GET /api/orders/:id",
54
54
  "kind": 3,
55
55
  "startTimeUnixNano": "1784592000123000000",
56
56
  "endTimeUnixNano": "1784592000248000000",
57
57
  "attributes": [
58
58
  { "key": "session.id", "value": { "stringValue": "session-01" } },
59
- { "key": "session.start_time", "value": { "intValue": 1784592000000 } },
60
59
  { "key": "session.type", "value": { "stringValue": "user" } },
61
60
  { "key": "session.has_replay", "value": { "boolValue": false } },
62
61
  { "key": "view.id", "value": { "stringValue": "view-01" } },
@@ -94,6 +93,7 @@ Wire 编码注意点:
94
93
  - Status `code=0` 是 UNSET,ERROR 为 `2`;
95
94
  - `startTimeUnixNano`、`endTimeUnixNano` 和 Event `timeUnixNano` 编码为十进制字符串;
96
95
  - Attribute 不是普通扁平对象,而是 `{ key, value }` 数组;value 使用 `stringValue`、`intValue`、`doubleValue`、`boolValue` 或 `arrayValue`;
96
+ - `session.sample_rate` 在值为整数 `1`/`0` 时常见为 `intValue`,小数采样率(如 `0.2`)为 `doubleValue`;按 number 读取即可;
97
97
  - `traceId` 是 32 位十六进制字符串,`spanId` / `parentSpanId` 是 16 位;没有父 Span 时省略 `parentSpanId`;
98
98
  - `events` 中的 exception/Long Task Event 也使用同样的 Attribute Value 包装;
99
99
  - `flags=257` 是当前 transformer 写出的“本地 sampled Span 且携带 isRemote 有效位”组合值,不要把它当作业务字段;
@@ -239,8 +239,8 @@ transport: {
239
239
 
240
240
  | 项目 | 当前行为 |
241
241
  | --- | --- |
242
- | `timeoutMillis` | 默认 `10000ms`,且必须是大于 0 的有限数值 |
243
- | `concurrencyLimit` | 默认 `30` 个待处理 export Promise |
242
+ | `timeoutMillis` | 不配置时为 `10000ms`,且必须是大于 0 的有限数值 |
243
+ | `concurrencyLimit` | 不配置时为 `30` 个待处理 export Promise |
244
244
  | 可重试 HTTP 状态 | `429`、`502`、`503`、`504` |
245
245
  | 可重试网络错误 | 浏览器 Fetch 的部分 `TypeError` 网络错误 |
246
246
  | 最大重试次数 | 初次请求后最多再尝试 5 次,但不能超过总体超时期限 |
@@ -291,18 +291,23 @@ session: {
291
291
 
292
292
  排查“手动事件没有上报”时,先暂时设置 `sampleRate: 1`。
293
293
 
294
- ## 导出前过滤
294
+ ## 两层拦截:Sampler 与 Filtering Processor
295
295
 
296
- 一个已结束 Span 还需要通过 `FilteringSpanProcessor` 才会进入 simple/batch processor。以下数据会被丢弃:
296
+ 采样和过滤发生在两个不同阶段,排查时要分清:
297
297
 
298
- - 没有命中当前 Session 采样;
299
- - 没有关联有效 Session;
300
- - 除 `browser.session` 外,没有关联有效 View;
301
- - 命中 SDK 自身的 `/v1/rum` 上报地址;
302
- - 被内部插件标记为丢弃;
298
+ **第一层 · Provider Sampler(Span 创建时)。** `WebTracerProvider` 使用 `RumSessionSampler`:Session 未命中采样时返回 `NOT_RECORD`,Span 直接是 non-recording 的,不记录属性也不会触发 `onEnd`。这一层对**所有** Span 生效,包括通过 `useInstrumentation()` 注册的第三方 OpenTelemetry Instrumentation——它们不需要自己判断采样。
299
+
300
+ **第二层 · `FilteringSpanProcessor`(Span 结束时)。** 已结束的 recording Span 还要通过它才进入 simple/batch processor。以下会被丢弃:
301
+
302
+ - 没有关联有效 `session.id`;
303
+ - 除 `span_type=session` 外,没有关联有效 `view.id`;
304
+ - 属性里的 `url.full` 或 `http.url` 命中 SDK 自身的 `/v1/rum` 上报地址(后者用于识别第三方 HTTP Instrumentation 产生的自上报请求);
305
+ - 被请求插件的 `request.beforeSend` 标记为丢弃;
303
306
  - 被全局 `tracking.beforeSend` 返回 `false` 拒绝。
304
307
 
305
- 过滤层会在 Span 创建时补齐缺失的运行时和页面属性;Span 结束时执行上述过滤,并在交给 exporter 前移除仅供内部使用的采样标记。详细顺序见[架构与数据流](./architecture.md)。
308
+ 同一个 Processor 还负责在 `onStart` 阶段补齐 Span 尚未显式写入的运行时属性和 `context.attributes.page()`;已有同名属性不会被覆盖。
309
+
310
+ 因此“未采样”和“被过滤”的现象不同:未采样时浏览器里根本没有成形的 Span;被过滤时 Span 已创建但没有进入导出队列,`debug: true` 也不会打印它。详细顺序见[架构与数据流](./architecture.md)。
306
311
 
307
312
  ## CORS 基线
308
313
 
@@ -81,7 +81,7 @@ console.log({
81
81
  - 有 `session.id`;
82
82
  - 有 `view.id`。
83
83
 
84
- `browser.session` 是唯一可以没有 `view.id` 的内置 Span。
84
+ `span_type=session` 是唯一可以没有 `view.id` 的内置 Span。
85
85
 
86
86
  manual View 模式下,必须在 Session 建立后调用 `startView()`:
87
87
 
@@ -228,7 +228,7 @@ console.log({
228
228
  ### 3. Payload 和 Hook
229
229
 
230
230
  - `name` 类型必须是 string,并建议使用非空、低基数枚举;
231
- - 当前运行时不拒绝空字符串:`reportCustomEvent({ name: '' })` 会尝试生成名为 `custom.` 的 Span,`reportAction({ name: '' })` 会生成空的 `action.name`,都不会仅因空 name 抛错或丢弃,但数据不可用,不应依赖该行为;
231
+ - 当前运行时不拒绝空字符串:`reportCustomEvent({ name: '' })` 会尝试生成名为 `custom.` 的 Span,`reportAction({ name: '' })` 会生成名为 `action.` 的 Span,都不会仅因空 name 抛错或丢弃,但数据不可用,不应依赖该行为;
232
232
  - attributes 只能使用合法 OTel Attribute 类型;
233
233
  - `context.attributes.page/custom` 与 `privacy.redactAttributes` 不应抛错;
234
234
  - `tracking.beforeSend` 不能按 name 返回 false;Custom Event 不经过请求级 `request.beforeSend`。
@@ -281,7 +281,7 @@ tracking: {
281
281
 
282
282
  ## 后端按 `traceparent` 的 trace-id 查不到 RUM Span
283
283
 
284
- 注入的 trace-id 与 RUM Span 自身的 `traceId` **不是同一个值**,两者通过 Span Link 关联。后端应按 `browser.resource` Span 的 `link.trace_id` 反查,而不是直接用 `traceId` 匹配。
284
+ 注入的 trace-id 与 RUM Span 自身的 `traceId` **不是同一个值**,两者通过 Span Link 关联。后端应按 `span_type=resource` Span 的 `link.trace_id` 反查,而不是直接用 `traceId` 匹配。
285
285
 
286
286
  如果 Link 的 `attributes.injected` 为 `false` 且 `attributes.format` 不是 `traceparent`,说明业务用的是 `b3` / `sw8` / Datadog 等格式。后端只解析 W3C `traceparent`,这种情况下后端不会生成 Trace,Link 里的 trace-id 自然查不到。
287
287
 
@@ -317,7 +317,7 @@ tracking: {
317
317
  - Resource Timing buffer 已满;
318
318
  - 条目时间顺序异常,SDK 会省略无效阶段而不是上报负值。
319
319
 
320
- 先判断 `browser.resource` 是否存在,再判断单个可选字段,不要把“字段缺失”当成“插件未工作”。
320
+ 先判断 `span_type=resource` 的 Span 是否存在,再判断单个可选字段,不要把“字段缺失”当成“插件未工作”。
321
321
 
322
322
  ## Web Vitals 缺失或值不同
323
323