@blueking/open-telemetry 0.0.25 → 0.0.27

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.
@@ -14,7 +14,7 @@ export declare const getDeviceResourceAttributes: () => Attributes;
14
14
  * - `device.memory_gib`:硬件能力快照,写入 Resource。
15
15
  * - `user_agent.name` / `user_agent.version` / `user_agent.os.name`:User Agent 信息,写入 Resource。
16
16
  * - `browser.viewport.*` / `browser.screen.*`:视口与屏幕尺寸。
17
- * - `network.status` / `network.effective_type` / `network.connection_type`:网络信息。
17
+ * - `network.status` / `network.effective_type` / `network.connection.type`:网络信息。
18
18
  *
19
19
  * 实时更新:
20
20
  * - viewport 监听 `resize` / `orientationchange`,并经 250ms debounce 合并,避免拖窗口时高频触发;
@@ -48,10 +48,10 @@ export declare const RUM_ATTRIBUTES: {
48
48
  readonly viewId: "view.id";
49
49
  readonly viewLoadEvent: "view.load_event";
50
50
  readonly viewLoadingTime: "view.loading_time";
51
+ readonly viewLoadingTimeSource: "view.loading_time_source";
51
52
  readonly viewLoadingType: "view.loading_type";
52
53
  readonly viewName: "view.name";
53
54
  readonly viewPhase: "view.phase";
54
- readonly viewSource: "view.source";
55
55
  readonly viewStartedAt: "view.started_at";
56
56
  readonly viewUrl: "view.url";
57
57
  readonly viewUrlPathGroup: "view.url_path_group";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueking/open-telemetry",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "description": "OpenTelemetry browser SDK for BK RUM",
5
5
  "author": "TencentCloud Real User Monitoring",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "docs:preview": "vitepress preview wikis",
24
24
  "dev": "vite dev",
25
25
  "dts": "vue-tsc --project tsconfig.dts.json",
26
- "test:rum-context": "node --experimental-default-type=module --experimental-strip-types --test tests/action-plugin.test.mjs tests/consent.test.mjs tests/experience-plugins.test.mjs tests/request-model.test.mjs tests/runtime-context.test.mjs tests/sampling.test.mjs tests/session-state.test.ts tests/session-plugin.test.mjs tests/session-page-view.test.mjs tests/session-processors.test.mjs tests/web-vitals.test.mjs"
26
+ "test:rum-context": "node --experimental-default-type=module --experimental-strip-types --test tests/action-plugin.test.mjs tests/consent.test.mjs tests/experience-plugins.test.mjs tests/request-model.test.mjs tests/runtime-context.test.mjs tests/sampling.test.mjs tests/session-state.test.ts tests/session-plugin.test.mjs tests/session-page-view.test.mjs tests/session-processors.test.mjs tests/trace-context.test.mjs tests/web-vitals.test.mjs"
27
27
  },
28
28
  "dependencies": {
29
29
  "@opentelemetry/api": "^1.9.1",
@@ -24,7 +24,7 @@ SDK 只产生原始 RUM Span:
24
24
  | View / Router | `tracking.view` | auto | Navigation Timing、History、hash、BFCache | `browser.view` | [View 与路由](./views-routing.md) |
25
25
  | View Loading Time | `tracking.view.loadingTime` | 开 | 请求/资源/DOM/`window.open` 活动 | `browser.view` update | [View 与路由](./views-routing.md) |
26
26
  | Fetch/XHR | `tracking.request` | 开 | fetch、XMLHttpRequest、Resource Timing | `browser.resource` CLIENT | [网络](./network.md) |
27
- | Trace Header | `allowedTracingUrls` | 无白名单 | W3C Trace Context | 被观测请求的 `traceparent` | [网络](./network.md) |
27
+ | Trace Header | `allowedTracingUrls` | 无白名单 | W3C Trace Context | 被观测请求的 `traceparent` + `browser.resource` Span Link | [网络](./network.md) |
28
28
  | 静态资源 | `tracking.resource` | 开 | Resource PerformanceObserver | `browser.resource` CLIENT | [网络](./network.md) |
29
29
  | JS Error | `tracking.error` | 开 | window error | `browser.error` | [错误与安全](./errors-security.md) |
30
30
  | Promise rejection | `tracking.error` | 开 | unhandledrejection | `browser.unhandledrejection` | [错误与安全](./errors-security.md) |
@@ -101,7 +101,7 @@ Fetch/XHR 插件统一负责:
101
101
 
102
102
  - 建 `browser.resource` CLIENT Span;
103
103
  - 请求结果和 HTTP status;
104
- - 可选 W3C `traceparent`;
104
+ - 可选 W3C `traceparent`:为每个白名单请求生成独立 trace context,并用 Span Link 关联,Link Attributes 记录命中格式与原始 Header;业务已有 trace Header 时不注入;
105
105
  - 与 Resource Timing 在最多 200ms 内匹配;
106
106
  - 向 View/Action activity 通知开始与结束。
107
107
 
@@ -161,7 +161,7 @@ tracking: {
161
161
  | 配置 | 默认 | 说明 |
162
162
  | --- | --- | --- |
163
163
  | `excludedUrls` | 无 | 匹配后不建请求 Span、不注入 trace header,也不计入 View/Action 活动 |
164
- | `allowedTracingUrls` | 无 | 只有明确匹配的 URL 才注入 W3C `traceparent`,同源也不例外 |
164
+ | `allowedTracingUrls` | 无 | 只有明确匹配的 URL 才注入 W3C `traceparent`,同源也不例外;注入的是独立 trace context,并通过 Span Link 关联回 RUM Span。业务已自行设置 trace Header 时不注入 |
165
165
  | `beforeSend` | 无 | 只作用于 Fetch/XHR 请求事件;`event.resource.outcome` 区分 response/abort/timeout/network_error,返回 `false` 丢弃请求 Span |
166
166
 
167
167
  URL matcher 支持 string、RegExp 或函数:
@@ -20,12 +20,13 @@ SDK 不采集任何请求 Body、响应 Body、WebSocket 消息内容、消息
20
20
 
21
21
  1. 把 URL 转成绝对 URL。
22
22
  2. 排除 SDK 自身上报和 `excludedUrls`。
23
- 3. 创建 `browser.resource` CLIENT Span。
24
- 4. 按白名单决定是否注入 `traceparent`。
25
- 5. 把请求开始/结束通知给 View/Action 页面活动。
26
- 6. 根据 Response 或终止原因生成结构化 outcome,并补充结果、异常和 Resource Timing。
27
- 7. 执行请求级 `beforeSend`。
28
- 8. 结束 Span,并进入全局过滤链路。
23
+ 3. 按白名单探测既有 Trace Header,规划本次请求的 trace context。
24
+ 4. 创建 `browser.resource` CLIENT Span,并把关联后端 Trace 的 Span Link 一并写入。
25
+ 5. 需要时注入 `traceparent`。
26
+ 6. 把请求开始/结束通知给 View/Action 页面活动。
27
+ 7. 根据 Response 或终止原因生成结构化 outcome,并补充结果、异常和 Resource Timing。
28
+ 8. 执行请求级 `beforeSend`。
29
+ 9. 结束 Span,并进入全局过滤链路。
29
30
 
30
31
  Patch 在插件 shutdown 时仅在全局方法仍是 SDK 安装版本的情况下恢复,避免覆盖 SDK 之后由业务安装的其他 Patch。
31
32
 
@@ -82,7 +83,7 @@ Matcher 规则:
82
83
 
83
84
  ## W3C Trace Context
84
85
 
85
- 默认不向任何请求注入 Trace Header,包括同源请求。只有 `allowedTracingUrls` 显式命中时才使用 `W3CTraceContextPropagator` 注入 `traceparent`:
86
+ 默认不向任何请求注入 Trace Header,包括同源请求。只有 `allowedTracingUrls` 显式命中时才注入:
86
87
 
87
88
  ```ts
88
89
  tracking: {
@@ -94,9 +95,11 @@ tracking: {
94
95
  }
95
96
  ```
96
97
 
97
- Fetch 会合并 `init.headers` 或输入 Request 的 Headers;XHR 使用 `setRequestHeader()`。白名单应使用 URL-aware 函数或有边界的正则,不要用过宽字符串。
98
+ 白名单应使用 URL-aware 函数或有边界的正则,不要用过宽字符串。
98
99
 
99
- 当前请求 Span 命中 Session 采样后,注入值采用 W3C Trace Context v00:
100
+ ### 每个请求一条独立后端 Trace
101
+
102
+ 注入的 `traceparent` **不复用** RUM Span 自身的 trace context,而是为每个命中白名单的请求生成一对全新的 trace-id / span-id:
100
103
 
101
104
  ```text
102
105
  traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
@@ -104,22 +107,59 @@ traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
104
107
  └ version=00 parent-id:16 位 ─────┘ sampled=01
105
108
  ```
106
109
 
107
- 这里的 `parent-id` 是本次 Fetch/XHR CLIENT Span 的 `spanId`。请求 Patch 只在当前 Session 已采样时创建并注入记录型 Span,因此当前实现发出的 flags 为 `01`。如果活动父上下文带有 `traceState`,传播器还会写 `tracestate`;SDK 自身不创建 `tracestate`。
110
+ 这样后端按 trace-id 检索时,一条 Trace 只对应一个 API 请求,也不会把前端的 `browser.resource` Span 混进后端链路。前后端的关联改由 **Span Link** 承担,后端可按 `link.trace_id` 反查对应的 RUM Span。
111
+
112
+ 每个命中白名单的请求恒定产出**一条** Link,结构固定为 trace context 加上记录来源的 `attributes`:
113
+
114
+ ```json
115
+ {
116
+ "links": [
117
+ {
118
+ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
119
+ "span_id": "00f067aa0ba902b7",
120
+ "attributes": {
121
+ "format": "traceparent",
122
+ "traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
123
+ }
124
+ }
125
+ ]
126
+ }
127
+ ```
128
+
129
+ `attributes.format` 是命中的传播格式,其余键是该格式的**原始 Header 名与原始取值**(不做补零或进制转换),例如 Datadog 会带上 `x-datadog-trace-id`、`x-datadog-parent-id`、`x-datadog-sampling-priority` 等。这些 Link Attributes 不经过 `privacy.redactAttributes` 脱敏。
130
+
131
+ 请求 Patch 只在当前 Session 已采样时创建 Span 并注入,因此发出的 flags 恒为 `01`。注入的 span-id 在前端没有对应的已上报 Span,后端 Trace 的根 Span 会以它作为 `parent_span_id`。
132
+
133
+ ### 业务已有 Trace Header 时不注入
134
+
135
+ 注入前 SDK 会先读取本次请求最终会发出的 Header,按下列优先级探测业务是否已经自行传播链路:
136
+
137
+ | 优先级 | `format` | Header | 能否解析出合法 OTel id |
138
+ | --- | --- | --- | --- |
139
+ | 1 | `traceparent` | `traceparent`(连带记录 `tracestate`) | 能 |
140
+ | 2 | `sentry-trace` | `sentry-trace` | 能 |
141
+ | 3 | `b3` | `b3`(单头) | 能,64 位 trace-id 左侧补零到 128 位 |
142
+ | 4 | `b3-multi` | `x-b3-traceid` / `x-b3-spanid` / `x-b3-parentspanid` / `x-b3-sampled` / `x-b3-flags` | 同上 |
143
+ | 5 | `datadog` | `x-datadog-trace-id` / `x-datadog-parent-id` / `x-datadog-sampling-priority` / `x-datadog-origin` / `x-datadog-tags` | 能,十进制换算为 hex,128 位时从 `x-datadog-tags` 的 `_dd.p.tid` 拼接高位 |
144
+ | 6 | `sw8` | `sw8` | **不能**,SkyWalking 的 trace-id 不是 16 字节 hex |
145
+
146
+ 一旦探测到上表任一 Header,SDK **完全不注入**,只把命中格式的原始 Header 写进 Link Attributes。只记录命中格式自己的 Header——若 `traceparent` 与 `b3` 同时存在,按优先级只记录前者。
108
147
 
109
- 已有 Header 的处理取决于浏览器 API:
148
+ 几点需要注意:
110
149
 
111
- - Fetch 使用 `Headers.set()`,会覆盖 Headers 中已有的 `traceparent` / `tracestate`;
112
- - XHR 在 `send()` 前调用 `setRequestHeader()`,浏览器可能把业务先设置的同名值追加合并,形成无效 Trace Context;不要由业务再手工设置同名 Header;
113
- - SDK 不先解析入站 Header 再决定是否保留,`allowedTracingUrls` 命中即按当前活动 SpanContext 注入。
150
+ - `traceparent` 与 SDK 注入的是同一个 Header,因此**格式非法时视作没有既有链路并覆盖注入**——这种值后端同样无法接续。其余格式只要 Header 存在就一律尊重。
151
+ - 解析不出合法 id 时(`sw8`、或 `b3: 0` 这类只有采样标记的值),SDK 会补一对随机 id 让 Link 结构保持统一,但**不会注入**。这对占位 id 在后端不存在对应 Trace,只有 `attributes` 里的原始 Header 有排查价值。
152
+ - 后端只解析 W3C `traceparent`。如果业务发的是 `b3` / `sw8` / Datadog 这类格式,SDK 不注入意味着后端不会生成 Trace,Link 中的 trace-id 在后端查不到。
153
+ - Fetch 读取的是 `init.headers`,缺省时回退到输入 `Request` 的 Headers;XHR 因为浏览器不提供读取请求头的 API,SDK 会额外 Patch `setRequestHeader()` 做快照,这层 Patch 仅在配置了 `allowedTracingUrls` 时安装,`open()` 时快照同步失效。
114
154
 
115
155
  跨域注入会触发 CORS 预检,服务端至少需要允许:
116
156
 
117
157
  ```http
118
158
  Access-Control-Allow-Origin: https://your-web.example.com
119
- Access-Control-Allow-Headers: traceparent, tracestate
159
+ Access-Control-Allow-Headers: traceparent
120
160
  ```
121
161
 
122
- 若你的链路从不携带 `tracestate`,可以只允许 `traceparent`;如业务还有自定义 Header,应一并加入允许列表。
162
+ 如业务还有自定义 Header 或自有的 trace Header,应一并加入允许列表。
123
163
 
124
164
  ## 请求级 beforeSend
125
165
 
@@ -159,6 +159,8 @@ allowedTracingUrls: [
159
159
 
160
160
  不要使用宽泛 `/./` 或所有 URL,避免向第三方发送 Trace ID,也避免触发额外预检。API 端必须允许 `traceparent` header,并正确接续 W3C Trace Context。
161
161
 
162
+ 每个命中白名单的请求都会生成一条独立的后端 Trace,因此后端 Trace 数量约等于被注入的请求数。评估后端存储与采样容量时按这个量级估算,必要时在服务端做二次采样。
163
+
162
164
  ## 7. 排除长活动与噪声
163
165
 
164
166
  两类配置语义不同:
@@ -137,7 +137,7 @@ Device 插件还维护:
137
137
  | `browser.screen.width/height` | 启动、resize、orientationchange |
138
138
  | `network.status` | 启动、online、offline、connection change |
139
139
  | `network.effective_type` | 启动和 connection change |
140
- | `network.connection_type` | 同上 |
140
+ | `network.connection.type` | 同上 |
141
141
 
142
142
  视口变化使用 250ms trailing debounce。`network.status` 在浏览器环境中始终存在,其他网络字段只有浏览器实现 Network Information API 时才存在。这些变化不主动生成 Span,只影响后续 Span 的上下文。
143
143
 
@@ -50,9 +50,10 @@
50
50
 
51
51
  | OTLP 字段 | 类型/格式 | 条件 | 详细说明 |
52
52
  | ------------------- | ------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53
- | `traceId` | 32 位十六进制字符串 | 必有 | 16 字节 Trace ID。同一条调用链上的 Span 使用同一个值,可用于串联用户操作、前端请求和已传播 Trace Context 的后端链路。 |
53
+ | `traceId` | 32 位十六进制字符串 | 必有 | 16 字节 Trace ID。同一条调用链上的 Span 使用同一个值。注意注入到后端的 `traceparent` 使用的是另一个独立 trace-id,不等于本字段,两者通过 `links` 关联。 |
54
54
  | `spanId` | 16 位十六进制字符串 | 必有 | 当前 Span 的 8 字节唯一 ID,与 `traceId` 一起唯一定位本次 Span。 |
55
55
  | `parentSpanId` | 16 位十六进制字符串 | 有活动父 Span 时 | 父 Span ID。没有活动父上下文的 RUM 根 Span不包含该字段;缺失不代表数据异常。 |
56
+ | `links` | link[] | 注入或探测到 Trace Header 时 | 关联的其他 Trace。`browser.resource` Span 用它指向本次请求对应的后端 Trace,每项含 `traceId`、`spanId`、`traceFlags`。后端可按 `link.trace_id` 反查 RUM Span。 |
56
57
  | `name` | string | 必有 | Span 名称,例如 `browser.view`、`browser.resource`。稳定一级分类使用 `span_type`,具体类别使用各领域字段查询。 |
57
58
  | `kind` | enum number/string | 必有 | OpenTelemetry Span Kind。SDK 内置值为 `INTERNAL` 或 `CLIENT`;不同 OTLP JSON 实现可能编码为枚举数字或名称。 |
58
59
  | `startTimeUnixNano` | epoch ns 字符串 | 必有 | Span 开始时间。OTLP JSON 使用十进制字符串保存纳秒整数,避免 JavaScript Number 精度丢失。 |
@@ -106,7 +107,7 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
106
107
  | `browser.screen.height` | number | 浏览器提供 `window.screen` 时 | 当前屏幕高度,单位 CSS px;不是当前网页可用区域高度。 |
107
108
  | `network.status` | string | 浏览器环境 | 根据 `navigator.onLine` 取 `connected` 或 `not_connected`;表示浏览器判断的联网状态,不保证目标服务实际可达。 |
108
109
  | `network.effective_type` | string | Network Information API 支持 | 浏览器估算的有效网络类型,常见为 `slow-2g`、`2g`、`3g`、`4g`。它反映体验模型,不等同于真实无线制式。 |
109
- | `network.connection_type` | string | 浏览器提供 `connection.type` 时 | 浏览器返回的原始连接类型,例如 `wifi`、`cellular`、`ethernet`;多数 Safari/Firefox 环境可能缺失。 |
110
+ | `network.connection.type` | string | 浏览器提供 `connection.type` 时 | 浏览器返回的原始连接类型,例如 `wifi`、`cellular`、`ethernet`;多数 Safari/Firefox 环境可能缺失。 |
110
111
 
111
112
  默认 `context.attributes.page()` 返回空对象,不附加独立页面属性。页面地址使用 View 创建时冻结并经过 `redactUrl` 的 `view.url`,低基数路由聚合使用 `view.url_path_group`;业务需要额外页面维度时可自定义该 Hook。
112
113
 
@@ -125,7 +126,7 @@ Resource Attribute 描述产生 Span 的 SDK 实例和运行环境,同一实
125
126
  | Span 名 | Kind | `span_type` | 领域分类字段 | 默认状态/入口 | 表达的事件 |
126
127
  | ---------------------------- | -------- | ----------- | --------------------------------- | --------------------------------- | -------------------------------------------------- |
127
128
  | `browser.session` | INTERNAL | `session` | `session.phase` | 始终随 SDK 启动 | Session 创建、轮换和结束生命周期。 |
128
- | `browser.view` | INTERNAL | `view` | `view.phase`、`view.source` | 自动;可切为手动 View | 初始页面或 SPA View 的 start/update/end 快照。 |
129
+ | `browser.view` | INTERNAL | `view` | `view.phase` | 自动;可切为手动 View | 初始页面或 SPA View 的 start/update/end 快照。 |
129
130
  | `browser.resource` | CLIENT | `resource` | `resource.type` | 请求、静态资源默认开启 | Fetch、XHR 或静态资源加载。 |
130
131
  | `browser.error` | INTERNAL | `error` | `error.source=window.error` | 错误采集默认开启 | `window.error` 捕获的 JavaScript 运行时错误。 |
131
132
  | `browser.unhandledrejection` | INTERNAL | `error` | `error.source=unhandledrejection` | 错误采集默认开启 | 未处理的 Promise rejection。 |
@@ -162,7 +163,6 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
162
163
  | 字段 | 类型 | 条件/单位 | 来源与详细说明 |
163
164
  | -------------------------- | ------ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
164
165
  | `view.phase` | string | `start`、`update`、`end` | `start` 创建 View;`update` 写入自动/手动 Loading Time 或名称更新;`end` 关闭 View。 |
165
- | `view.source` | string | 所有阶段 | 创建来源会沿用到该 View 后续事件:`load`、`manual`、`pushState`、`replaceState`、`popstate`、`hashchange`、`bfCache`、`sessionRenewal`。 |
166
166
  | `view.id` | string | 所有阶段 | View 关联 ID。同一 View 的 start/update/end 使用相同值,可与该 View 内其他 Span 关联。 |
167
167
  | `view.version` | number | 从 1 递增 | 每次 `emitViewEvent` 递增;用于恢复同一 View 生命周期快照的先后顺序。 |
168
168
  | `view.started_at` | number | epoch ms | View 开始时间。初始 View 使用 `performance.timeOrigin`,路由/BFCache/续建 View 使用创建时刻。 |
@@ -171,7 +171,7 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
171
171
  | `view.url_path_group` | string | 所有阶段 | 低基数路由分组。数字 ID、UUID、长十六进制段默认折叠为 `:id`,用于稳定聚合动态路由。 |
172
172
  | `view.loading_type` | string | 所有阶段 | `initial_load`、`route_change`、`bf_cache` 或 `session_renewal`,含义见运行时公共属性。 |
173
173
  | `view.loading_time` | number | 计算完成后,ms | 从 `view.started_at` 到页面活动稳定的耗时。初始加载同时等待 load event 和页面活动,以较晚者为准;可由 `setViewLoadingTime()` 手动结束。 |
174
- | `view.loading_time.source` | string | 有 `view.loading_time` 时 | `auto` 表示 SDK 自动观察页面活动;`manual` 表示业务调用 `setViewLoadingTime()`。 |
174
+ | `view.loading_time_source` | string | 有 `view.loading_time` 时 | `auto` 表示 SDK 自动观察页面活动;`manual` 表示业务调用 `setViewLoadingTime()`。 |
175
175
  | `view.end_reason` | string | 仅 `end` | 结束原因:路由来源值、`manual`、`bfcache`、`pagehide`、`session_expired` 或 `shutdown`。它说明为何关闭旧 View,不是新 View 的加载类型。 |
176
176
  | `url.previous` | string | 所有阶段 | 创建 View 时记录的前序 URL,经 `redactUrl` 脱敏;初始 View 通常为空字符串。 |
177
177
  | `document.referrer` | string | 仅 `initial_load` | `document.referrer` 经 `redactUrl` 脱敏;没有来源页面时为空字符串。 |
@@ -204,6 +204,15 @@ Session Span 允许没有 `view.id`:SDK 先建立 Session,再创建初始 Vi
204
204
  | `resource.decoded_body_size` | number | 有 Resource Timing | 解码/解压后的响应体大小,单位 bytes,可与 encoded size 对比压缩收益。 |
205
205
  | `resource.transfer_size` | number | 有 Resource Timing | `transferSize`,本次网络实际传输字节数(含响应头);受缓存和 Timing-Allow-Origin 影响可能为 `0`,可与 body size 对比判断是否命中缓存。 |
206
206
 
207
+ 命中 `allowedTracingUrls` 的请求还会带一条 Span Link,用于关联后端 Trace。Trace 来源不记在 Span Attributes 上,而是记在 Link Attributes 上:
208
+
209
+ | 字段 | 类型 | 条件 | 说明 |
210
+ | ----------- | ------ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
211
+ | `format` | string | 恒有 | 命中的传播格式,取值为 `traceparent`、`sentry-trace`、`b3`、`b3-multi`、`datadog`、`sw8`。为 `traceparent` 且 Link 的 trace-id 由 SDK 生成时,表示是 SDK 注入的。 |
212
+ | Header 原名 | string | 该 Header 存在 | 命中格式的原始 Header 名与原始取值,未做补零或进制转换,例如 `traceparent`、`b3`、`x-datadog-trace-id`、`sw8`。仅记录命中格式自己的 Header。 |
213
+
214
+ Link 的 `trace_id` / `span_id` 优先取自解析结果;`sw8` 这类无法映射为合法 OTel id 的格式会补一对随机占位 id,此时后端不存在对应 Trace。Link Attributes 不经过 `privacy.redactAttributes` 脱敏。
215
+
207
216
  网络阶段字段均为 number、单位 ms。每个 `*.start` 相对该 Resource Entry 的 `startTime`,每个 `*.duration` 为对应阶段结束值减开始值:
208
217
 
209
218
  | 字段 | 条件 | 计算口径与使用方式 |
@@ -277,6 +277,16 @@ tracking: {
277
277
 
278
278
  跨域还需要服务端 CORS 允许请求头 `traceparent`。如果预检失败,缩小白名单并修复 API 服务的 CORS;不要把所有第三方 URL 加入白名单。
279
279
 
280
+ 命中白名单却依然没有注入时,看 Span Link 的 `attributes.format`。只要它不是 SDK 自己生成的 `traceparent`,就说明业务已经设置了 trace Header(`sentry-trace`、`b3`、Datadog、`sw8`,或业务自己的 `traceparent`),SDK 会尊重既有链路而不注入,只把原始 Header 记进 Link Attributes。
281
+
282
+ ## 后端按 `traceparent` 的 trace-id 查不到 RUM Span
283
+
284
+ 注入的 trace-id 与 RUM Span 自身的 `traceId` **不是同一个值**,两者通过 Span Link 关联。后端应按 `browser.resource` Span 的 `link.trace_id` 反查,而不是直接用 `traceId` 匹配。
285
+
286
+ 如果 Link 的 `attributes.format` 不是 `traceparent`,说明业务用的是 `b3` / `sw8` / Datadog 等格式。后端只解析 W3C `traceparent`,这种情况下后端不会生成 Trace,Link 里的 trace-id 自然查不到。
287
+
288
+ `sw8` 以及 `b3: 0` 这类只有采样标记的值,SDK 解析不出合法 OTel id,会补一对**随机占位 id** 让 Link 结构保持统一。这对 id 在后端一定查不到,判断依据仍是 `attributes.format` 与其中的原始 Header。
289
+
280
290
  ## 请求 Span 太多或 View loading 一直不结束
281
291
 
282
292
  使用两个不同的排除入口:
@@ -26,8 +26,6 @@ View 表示一次可独立分析的页面体验。初始文档加载、SPA 路
26
26
  - query-only 变化不创建 View;
27
27
  - 指向当前页面真实元素 ID 的 hash 视为页内锚点,不创建 View。
28
28
 
29
- 路由触发源写入 `view.source`,初始加载为 `load`,手动调用为 `manual`,其余使用对应 History/浏览器事件名。
30
-
31
29
  ## 手动 View 模式
32
30
 
33
31
  框架路由希望完全控制边界时:
@@ -144,7 +142,7 @@ Span 名固定为 `browser.view`:
144
142
  - SPA/BFCache/Session Renewal:只有观察到页面活动时才生成自动 Loading Time,取 View 开始到页面活动结束的耗时。
145
143
  - 页面在计算期间变为 hidden:取消自动计算,不上报不可靠结果。
146
144
 
147
- `view.loading_time.source=auto` 表示自动计算。
145
+ `view.loading_time_source=auto` 表示自动计算。
148
146
 
149
147
  ## 排除长轮询和无关活动
150
148
 
@@ -176,7 +174,7 @@ bkOT.setViewLoadingTime();
176
174
 
177
175
  SDK 计算“调用时刻 - View 开始时间”,取消仍在进行的自动计算,并发送 update:
178
176
 
179
- - `view.loading_time.source=manual`
177
+ - `view.loading_time_source=manual`
180
178
  - 多次调用以后一次为准;每次都会产生新版本 update。
181
179
  - 没有采样有效 View 时忽略。
182
180