@blueking/open-telemetry 0.0.27 → 0.0.28

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