@blueking/open-telemetry 0.0.14 → 0.0.16

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 (49) hide show
  1. package/README.md +96 -641
  2. package/dist/bk-rum.global.js +9 -9
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/action-activity.d.ts +28 -0
  5. package/dist/core/config.d.ts +113 -93
  6. package/dist/core/page-activity.d.ts +14 -0
  7. package/dist/core/plugin.d.ts +23 -6
  8. package/dist/core/processor.d.ts +25 -4
  9. package/dist/core/request-timing.d.ts +5 -0
  10. package/dist/core/runtime-context.d.ts +51 -3
  11. package/dist/core/sampling.d.ts +5 -1
  12. package/dist/core/sdk.d.ts +29 -10
  13. package/dist/core/url.d.ts +4 -1
  14. package/dist/index.d.ts +12 -14
  15. package/dist/index.js +2184 -1175
  16. package/dist/index.js.map +1 -1
  17. package/dist/plugins/action.d.ts +6 -2
  18. package/dist/plugins/activity.d.ts +6 -0
  19. package/dist/plugins/blank-screen.d.ts +17 -0
  20. package/dist/plugins/common.d.ts +11 -3
  21. package/dist/plugins/device.d.ts +2 -0
  22. package/dist/plugins/long-task.d.ts +3 -12
  23. package/dist/plugins/page-view.d.ts +1 -0
  24. package/dist/plugins/request-body.d.ts +14 -0
  25. package/dist/plugins/resource.d.ts +17 -1
  26. package/dist/plugins/session-state.d.ts +18 -0
  27. package/dist/plugins/session.d.ts +4 -4
  28. package/dist/plugins/web-vitals.d.ts +74 -0
  29. package/dist/schema/attributes.d.ts +31 -10
  30. package/dist/schema/span.d.ts +4 -12
  31. package/package.json +3 -7
  32. package/skills/bk-rum-otele/SKILL.md +39 -33
  33. package/skills/bk-rum-otele/evals/evals.json +3 -3
  34. package/skills/bk-rum-otele/references/api.md +247 -114
  35. package/skills/bk-rum-otele/references/architecture.md +141 -0
  36. package/skills/bk-rum-otele/references/capabilities.md +100 -0
  37. package/skills/bk-rum-otele/references/concepts.md +40 -111
  38. package/skills/bk-rum-otele/references/configuration.md +202 -254
  39. package/skills/bk-rum-otele/references/custom-plugin.md +22 -7
  40. package/skills/bk-rum-otele/references/data-model.md +17 -10
  41. package/skills/bk-rum-otele/references/framework-integration.md +25 -17
  42. package/skills/bk-rum-otele/references/getting-started.md +42 -86
  43. package/skills/bk-rum-otele/references/plugins.md +232 -138
  44. package/skills/bk-rum-otele/references/privacy.md +47 -34
  45. package/skills/bk-rum-otele/references/telemetry-reference.md +74 -45
  46. package/skills/bk-rum-otele/references/transport-sampling.md +79 -0
  47. package/skills/bk-rum-otele/references/troubleshooting.md +71 -37
  48. package/dist/plugins/http-body.d.ts +0 -3
  49. package/dist/plugins/route-timing.d.ts +0 -2
@@ -2,201 +2,278 @@
2
2
 
3
3
  # API 参考
4
4
 
5
- 本页按使用频率列出公开 API。完整类型以 `src/index.ts` 导出为准。
5
+ 本页只描述 `src/index.ts` 公开导出的 API。深层路径文件属于实现细节,接入方不应直接 import。
6
6
 
7
- ## BkOpenTelemetry
7
+ ## 创建实例
8
8
 
9
9
  ```ts
10
- import { BkOpenTelemetry } from '@blueking/open-telemetry';
10
+ import { BkOpenTelemetry, type BkOTOptions } from '@blueking/open-telemetry';
11
11
 
12
- const bkOT = new BkOpenTelemetry({
13
- app: { name: 'bk-rum-demo' },
12
+ const options: BkOTOptions = {
13
+ application: { name: 'bk-rum-demo' },
14
14
  transport: { endpoint: 'https://rum-collector.example.com' },
15
- });
16
- ```
17
-
18
- ### 实例成员总览
15
+ };
19
16
 
20
- `BkOpenTelemetry` 实例(`BkOTInstance`)提供以下成员,常用方法在下文展开:
21
-
22
- | 成员 | 类型 | 说明 |
23
- | --- | --- | --- |
24
- | `start()` | `() => Promise<void>` | 启动 SDK,注册 provider、instrumentation 和插件。 |
25
- | `shutdown()` | `() => Promise<void>` | 刷新数据、关闭 provider、清理插件;关闭后不可重启。 |
26
- | `flush()` | `() => Promise<void>` | 立即刷新插件、trace、metric、log。 |
27
- | `use(plugin)` | `(plugin) => this` | 注册自定义插件,须在 `start()` 前。 |
28
- | `useInstrumentation(instr)` | `(instr) => this` | 注册额外 OpenTelemetry instrumentation,须在 `start()` 前。 |
29
- | `setUser(user)` | `(user) => void` | 更新用户上下文(`user.id`)。 |
30
- | `setView(view)` | `(view) => void` | 更新当前 view 上下文。 |
31
- | `reportAction(payload)` | `(payload) => void` | 手动上报用户动作(受采样控制)。 |
32
- | `reportCustomEvent(payload)` | `(payload) => void` | 手动上报自定义事件(受采样控制)。 |
33
- | `startSpan(name, attributes?, options?)` | `(...) => Span` | 创建并返回一个 span,自动带上运行时属性与脱敏。 |
34
- | `emitLog(record)` | `(record) => void` | 发送一条 log,自动合并运行时属性与脱敏。 |
35
- | `getRuntimeAttributes()` | `() => Attributes` | 读取当前运行时公共属性快照。 |
36
- | `setRuntimeAttributes(attributes)` | `(attributes) => void` | 写入运行时公共属性。 |
37
- | `applyRedact(attributes)` | `(attributes) => Attributes` | 对属性执行一次 `privacy.redactAttributes`。 |
38
- | `config` | `ResolvedBkOTConfig` | 解析后的只读配置。 |
39
- | `tracer` / `meter` / `logger` | OpenTelemetry 原生对象 | 用于直接操作三类信号 provider。 |
17
+ const bkOT = new BkOpenTelemetry(options);
18
+ ```
40
19
 
41
- > `startSpan` / `emitLog` / `getRuntimeAttributes` 等既是实例方法,也是自定义插件 `init(context)` 中 `context` 的能力,见[自定义插件](./custom-plugin.md)。
20
+ 构造函数同步解析配置并创建三个 OpenTelemetry Provider;`autoStart: true` 时随后异步启动采集。完整配置见[配置参考](./configuration.md)。
42
21
 
43
- ### start
22
+ ## 生命周期方法
44
23
 
45
- 启动 SDK,注册 provider、instrumentation 和插件。
24
+ ### start()
46
25
 
47
26
  ```ts
48
27
  const bkOT = new BkOpenTelemetry({
28
+ application: { name: 'bk-rum-demo' },
49
29
  autoStart: false,
50
30
  transport: { endpoint: 'https://rum-collector.example.com' },
51
31
  });
52
32
 
33
+ bkOT.use(myPlugin);
53
34
  await bkOT.start();
54
35
  ```
55
36
 
56
- ### shutdown
37
+ 启动 Session、View、内置插件、接入方插件和 instrumentations,并安装页面隐藏时的 flush 监听。重复调用 `start()` 不会重复启动。
38
+
39
+ ### flush()
40
+
41
+ ```ts
42
+ await bkOT.flush();
43
+ ```
44
+
45
+ 先并行调用已启动插件的 `flush()`,再 force flush Trace、Metric、Log Provider。SDK 已在 `pagehide` 和页面变为 hidden 时触发 flush;业务只需在关键流程完成后按需主动调用。
57
46
 
58
- 刷新数据、关闭 provider,并执行插件清理。关闭后不应再重启同一个实例。
47
+ ### shutdown()
59
48
 
60
49
  ```ts
61
50
  await bkOT.shutdown();
62
51
  ```
63
52
 
64
- ### flush
53
+ 反向关闭插件、结束待处理事件、刷新 Provider 并清理浏览器 patch/监听。该方法幂等;关闭后不能重新启动同一实例,再调用 `start()` 会抛错。
65
54
 
66
- 立即刷新插件、trace、metric、log。
55
+ ## Consent
56
+
57
+ ### setTrackingConsent(consent)
67
58
 
68
59
  ```ts
69
- window.addEventListener('beforeunload', () => {
70
- void bkOT.flush();
60
+ const bkOT = new BkOpenTelemetry({
61
+ application: { name: 'consent-demo' },
62
+ privacy: { trackingConsent: 'not-granted' },
63
+ transport: { endpoint: 'https://rum-collector.example.com' },
71
64
  });
65
+
66
+ await bkOT.setTrackingConsent('granted');
67
+ await bkOT.setTrackingConsent('not-granted');
72
68
  ```
73
69
 
74
- ### use
70
+ - 未授权:不创建 Session/View,不启动插件,不 patch 浏览器 API。
71
+ - 授权:启动采集并建立新的 Session/View。
72
+ - 撤销:关闭采集副作用并 flush 已允许的数据。
73
+ - 再授权:插件会再次执行 `init()`。
74
+
75
+ 该方法在 `autoStart: false` 且尚未 `start()` 时只更新状态;随后 `start()` 使用最新 Consent。
75
76
 
76
- 注册自定义插件,必须在 `start()` 前调用。
77
+ ## User 与 View
78
+
79
+ ### setUser(user)
77
80
 
78
81
  ```ts
79
- bkOT.use(
80
- createPlugin({
81
- name: 'biz-plugin',
82
- init(context) {
83
- const span = context.startSpan('custom.biz_plugin_ready');
84
- span.end();
85
- },
86
- }),
87
- );
82
+ bkOT.setUser({ id: 'user-12345' });
83
+ bkOT.setUser({ id: undefined });
88
84
  ```
89
85
 
90
- ### useInstrumentation
86
+ 更新后续事件的 `user.id`。SDK 不 hash、不脱敏、不改写该值。
91
87
 
92
- 注册额外 OpenTelemetry instrumentation,必须在 `start()` 前调用。
88
+ ### startView(options?)
89
+
90
+ 结束当前 View 并创建新 View,`view.id` 始终由 SDK 生成。
93
91
 
94
92
  ```ts
95
- bkOT.useInstrumentation(new SomeWebInstrumentation());
93
+ const bkOT = new BkOpenTelemetry({
94
+ application: { name: 'manual-view-demo' },
95
+ autoStart: false,
96
+ tracking: { view: { tracking: 'manual' } },
97
+ transport: { endpoint: 'https://rum-collector.example.com' },
98
+ });
99
+
100
+ await bkOT.start();
101
+ bkOT.startView({
102
+ name: '订单详情',
103
+ url: location.href,
104
+ attributes: { 'biz.owner': 'order-team' },
105
+ });
96
106
  ```
97
107
 
98
- ### setUser
108
+ `BkOTStartViewOptions` 包含 `name?`、`url?`、`attributes?`。调用时必须已有采样有效的 Session;例如 `autoStart: false` 且尚未 `await start()`、未授权或未采样时,调用会被忽略。自动启动过程中、Page View 插件尚未初始化时发出的有效命令会由运行时队列交给插件消费,但接入代码仍推荐显式等待 `start()`。`attributes` 不能覆盖 SDK 的 Session/View 保留字段。
99
109
 
100
- 更新用户上下文。
110
+ ### setViewName(name)
101
111
 
102
112
  ```ts
103
- bkOT.setUser({
104
- id: 'user-12345',
105
- });
113
+ bkOT.setViewName('订单详情-只读');
106
114
  ```
107
115
 
108
- ### setView
116
+ 更新当前 View 名称,不创建新 View。后续子事件使用新名称,View Snapshot 产生 update。
109
117
 
110
- 更新当前 view 上下文。
118
+ ### setViewLoadingTime()
111
119
 
112
120
  ```ts
113
- bkOT.setView({
114
- id: 'view-home',
115
- url: window.location.href,
116
- urlPathGroup: '/home',
117
- loadingType: 'initial_load',
118
- });
121
+ await renderAsyncPage();
122
+ bkOT.setViewLoadingTime();
119
123
  ```
120
124
 
121
- ### reportAction
125
+ 用“当前时刻 - View 开始时刻”覆盖自动 `view.loading_time`。每次调用替换前一次值;没有有效 View 时忽略。
126
+
127
+ ## 手动事件
122
128
 
123
- 手动上报用户动作。
129
+ ### reportAction(payload)
124
130
 
125
131
  ```ts
126
132
  bkOT.reportAction({
127
- type: 'click',
128
- targetTag: 'button',
129
- targetText: '保存',
130
- attributes: {
131
- 'biz.form': 'alarm-strategy',
132
- },
133
+ name: '保存',
134
+ attributes: { 'biz.form': 'alarm-strategy' },
133
135
  });
134
136
  ```
135
137
 
136
- ### reportCustomEvent
138
+ 创建并立即结束 `action.custom` Span,写入新的 `action.id`、`action.name` 和 `action.type=custom`。它不会触发自动点击的活动耗时、关联计数或挫败信号计算。
137
139
 
138
- 手动上报自定义事件。
140
+ ### reportCustomEvent(payload)
139
141
 
140
142
  ```ts
141
143
  bkOT.reportCustomEvent({
142
144
  name: 'strategy_saved',
143
- attributes: {
144
- 'biz.strategy_id': '10001',
145
- },
145
+ attributes: { 'biz.strategy_id': '10001' },
146
146
  });
147
- ```
148
-
149
- 带错误的自定义事件:
150
147
 
151
- ```ts
152
148
  bkOT.reportCustomEvent({
153
149
  name: 'strategy_save_failed',
154
150
  error: new Error('validation failed'),
155
- attributes: {
156
- 'biz.strategy_id': '10001',
157
- },
158
151
  });
159
152
  ```
160
153
 
161
- ## createPlugin
154
+ 创建 `custom.<name>` Span,并合并 `context.attributes.page`、`context.attributes.custom` 与 payload attributes。传入 `error` 时记录 exception、设置 Span Status/`result=error`,但 `span_type` 仍为 `custom`。
155
+
156
+ 两类方法均受 Session 采样控制;未采样时直接返回。`debug: true` 仅对被丢弃的 Custom Event 输出 warning。
157
+
158
+ ## 自定义信号
159
+
160
+ ### startSpan(name, attributes?, options?)
161
+
162
+ ```ts
163
+ const startedAt = Date.now();
164
+ const span = bkOT.startSpan(
165
+ 'custom.cache_warmup',
166
+ { 'biz.cache': 'homepage' },
167
+ { startTime: startedAt, contextTime: startedAt },
168
+ );
169
+
170
+ span.end();
171
+ ```
172
+
173
+ 自动合并事件发生时的运行时上下文,并应用 `privacy.redactAttributes`。第三个参数的内部形状名为 `BkOTStartSpanOptions`,但该类型没有从包根导出,接入方直接按下表传对象即可,不要生成对它的 import:
174
+
175
+ | 字段 | 说明 |
176
+ | --- | --- |
177
+ | `startTime` | OpenTelemetry `TimeInput`;常用 epoch ms |
178
+ | `contextTime` | 用该 epoch ms 从历史快照解析 Session/View/Action;数字型 `startTime` 默认同时作为该值 |
179
+ | `kind` | OpenTelemetry `SpanKind`,默认 `INTERNAL` |
180
+
181
+ 只有已采样且同时带有效 `session.id`、`view.id` 的 Span 会导出。
182
+
183
+ ### emitLog(record)
184
+
185
+ ```ts
186
+ bkOT.emitLog({
187
+ severityText: 'INFO',
188
+ body: 'biz.cache_ready',
189
+ attributes: { 'biz.cache': 'homepage' },
190
+ });
191
+ ```
192
+
193
+ 自动合并运行时上下文与脱敏。自定义插件应使用 `emitLog()`,不要直接调用 `logger.emit()`。
194
+
195
+ ### tracer / meter / logger
196
+
197
+ 实例公开 SDK 私有 Provider 对应的原生 OpenTelemetry `Tracer`、`Meter`、`Logger`。优先使用 `startSpan()` 与 `emitLog()`。当前没有公开稳定的自定义 Metric 采样 helper,直接通过 `meter` 创建的数据点默认无法通过过滤器,不应作为接入方稳定能力;详见[架构与数据流](./architecture.md#扩展边界)。
198
+
199
+ ## 扩展注册
200
+
201
+ ### use(plugin)
202
+
203
+ ```ts
204
+ bkOT.use(
205
+ createPlugin({
206
+ name: 'biz-plugin',
207
+ init(context) {
208
+ context.startSpan('custom.biz_plugin_ready').end();
209
+ },
210
+ }),
211
+ );
212
+ ```
213
+
214
+ ### useInstrumentation(instrumentation)
215
+
216
+ ```ts
217
+ bkOT.useInstrumentation(new SomeWebInstrumentation());
218
+ ```
219
+
220
+ 两者都必须在 `start()` 前调用;使用默认自动启动时没有可靠的动态注册窗口,推荐配置 `autoStart: false`。完整插件契约见[自定义插件](./custom-plugin.md)。
221
+
222
+ 额外 instrumentation 的稳定扩展边界是 Trace。第三方 Metric 不会自动获得 SDK 内部采样标记,默认无法通过 Metric 过滤器。
223
+
224
+ ## 运行时与诊断成员
225
+
226
+ | 成员 | 返回/作用 |
227
+ | --- | --- |
228
+ | `config` | `resolveConfig()` 解析后的 `ResolvedBkOTConfig` |
229
+ | `applyRedact(attributes)` | 执行 `privacy.redactAttributes` |
230
+ | `getRuntimeAttributes()` | 当前公共属性快照 |
231
+ | `getRuntimeAttributesAt(timestamp)` | 指定 epoch ms 的历史公共属性快照 |
232
+ | `setRuntimeAttributes(attributes, changedAt?)` | 写入公共属性;高级扩展 API,谨慎避免覆盖 SDK 字段 |
233
+ | `isSampled()` | 当前 Session 是否命中采样 |
234
+ | `isSessionActive()` | 是否存在有效 Session |
235
+ | `isViewActive()` | 是否存在有效 View |
236
+ | `onSessionLifecycle(listener)` | 订阅 Session renewed/expired,返回取消函数 |
237
+ | `notifySessionLifecycle(event)` | 向运行时分发生命周期事件;主要供高级插件使用 |
238
+
239
+ ## createPlugin(plugin)
240
+
241
+ `createPlugin()` 是保留完整类型推导的恒等构造器。
162
242
 
163
243
  ```ts
164
244
  import { createPlugin } from '@blueking/open-telemetry';
165
245
 
166
- export const plugin = createPlugin({
246
+ const plugin = createPlugin({
167
247
  name: 'page-visible',
168
- init(context) {
169
- context.emitLog({
170
- severityText: 'INFO',
171
- body: 'plugin init',
172
- attributes: {
173
- 'document.visibility_state': document.visibilityState,
174
- },
175
- });
176
- },
248
+ enabled: config => config.enabled,
249
+ init(context) {},
250
+ flush() {},
251
+ shutdown() {},
177
252
  });
178
253
  ```
179
254
 
180
- ## RUM_ATTRIBUTES
255
+ `BkOTPlugin` 的 `enabled` 可为布尔值或接收 `ResolvedBkOTConfig` 的函数。Plugin Manager 顺序启动、并行 flush、反向 shutdown,并隔离单个插件的初始化错误。
181
256
 
182
- `RUM_ATTRIBUTES` 提供字段 key 常量,避免手写字符串。
257
+ ## Schema 辅助 API
183
258
 
184
- ```ts
185
- import { RUM_ATTRIBUTES } from '@blueking/open-telemetry';
259
+ ### RUM_ATTRIBUTES
186
260
 
261
+ 归一字段 key 常量。
262
+
263
+ ```ts
187
264
  bkOT.reportCustomEvent({
188
265
  name: 'biz_event',
189
- attributes: {
190
- [RUM_ATTRIBUTES.targetLabel]: 'submit-order',
191
- },
266
+ attributes: { [RUM_ATTRIBUTES.targetLabel]: 'submit-order' },
192
267
  });
193
268
  ```
194
269
 
195
- ## RUM_SPAN_TYPE 与 buildRumSpanAttributes
270
+ ### RUM_SPAN_TYPE / RUM_SPAN_RESULT
196
271
 
197
- ```ts
198
- import { RUM_SPAN_TYPE, buildRumSpanAttributes } from '@blueking/open-telemetry';
272
+ 分别提供标准 `span_type` 与 `result` 值。
273
+
274
+ ### buildRumSpanAttributes(classification)
199
275
 
276
+ ```ts
200
277
  const span = bkOT.startSpan('custom.cache_hit', {
201
278
  ...buildRumSpanAttributes({
202
279
  spanType: RUM_SPAN_TYPE.custom,
@@ -206,23 +283,79 @@ const span = bkOT.startSpan('custom.cache_hit', {
206
283
  targetValue: true,
207
284
  }),
208
285
  });
209
-
210
286
  span.end();
211
287
  ```
212
288
 
213
- ## resolveConfig
289
+ ### getDurationBucket(duration)
290
+
291
+ 返回 `<100ms`、`100~500ms`、`500ms~2s`、`>2s` 之一。
292
+
293
+ ### buildRumSpanAttributes 相关类型
214
294
 
215
- `resolveConfig()` 可用于预览 SDK 核心配置解析结果。插件配置不会在这里展开默认值;内置插件会在各自创建时处理开关、默认值和参数兜底。
295
+ 公开 `RumSpanClassification`、`RumSpanType`、`RumSpanResult`,用于扩展插件保持同一归一模型。
296
+
297
+ ## resolveConfig(options)
216
298
 
217
299
  ```ts
218
300
  import { resolveConfig } from '@blueking/open-telemetry';
219
301
 
220
302
  const config = resolveConfig({
221
- app: {
222
- name: 'bk-rum-demo',
223
- },
303
+ application: { name: 'bk-rum-demo' },
304
+ transport: { endpoint: 'https://rum-collector.example.com' },
224
305
  });
225
306
 
226
- console.log(config.app.name);
227
- console.log(config.transport.traces.endpoint);
307
+ console.log(config.transport.traces && config.transport.traces.endpoint);
228
308
  ```
309
+
310
+ 用于预览核心解析结果和测试配置。插件自己的参数默认值在插件工厂执行时解析,不会全部展开到 `ResolvedBkOTConfig`。
311
+
312
+ ## 内置插件工厂
313
+
314
+ 公共入口导出以下工厂,便于自定义组合或测试:
315
+
316
+ | 工厂 | 选项类型 |
317
+ | --- | --- |
318
+ | `createSessionPlugin` | `BkOTSessionConfig` |
319
+ | `createDevicePlugin` | `BkOTDevicePluginOptions` |
320
+ | `createCommonInstrumentationsPlugin` | `BkOTRequestConfig \| boolean` |
321
+ | `createResourcePlugin` | 直接传 `boolean`,控制是否为静态资源创建 Span;默认 `true` |
322
+ | `createErrorPlugin` | `BkOTErrorPluginOptions` |
323
+ | `createWebVitalsPlugin` | 无 |
324
+ | `createBlankScreenPlugin` | `BkOTBlankScreenPluginOptions` |
325
+ | `createActionPlugin` | `BkOTActionPluginOptions` |
326
+ | `createLongTaskPlugin` | `BkOTLongTaskPluginOptions` |
327
+ | `createWebSocketPlugin` | 无 |
328
+ | `createCspViolationPlugin` | 无 |
329
+
330
+ `createCommonInstrumentationsPlugin` 名称保留,但当前实现是 SDK 自有 Fetch/XHR patch,不注册官方 Fetch/XHR instrumentation。
331
+
332
+ ## 其他公共导出
333
+
334
+ `src/index.ts` 还导出以下高级能力:
335
+
336
+ - `RumRuntimeContext` 及 Session/View/User 相关类型。
337
+ - `PluginManager`。
338
+ - `FilteringSpanProcessor`、`FilteringMetricExporter`、`FilteringLogRecordProcessor`。
339
+ - `EXCLUDED_ACTIVITY_MUTATIONS_ATTRIBUTE`,用于标记不应延长 View Loading/Action 的 DOM 子树。
340
+ - 配置输入、解析结果、Transport、Hook、请求上下文等 TypeScript 类型。
341
+
342
+ 这些主要服务 SDK 维护和高级扩展;常规接入只需 `BkOpenTelemetry`、`BkOTOptions` 和手动事件类型。
343
+
344
+ `BkOpenTelemetry` 具体类上还能看到 `registerInstrumentations()`,它用于 SDK 向插件运行时提供批量注册能力,但被刻意排除在 `BkOTInstance` 契约之外,也会绕过 `useInstrumentation()` 的启动阶段检查。接入方不要直接调用;使用 `extensions.instrumentations` 或 `useInstrumentation()`。
345
+
346
+ ## 公共类型索引
347
+
348
+ 以下名称都可以从包根路径执行 `import type`:
349
+
350
+ | 分类 | 类型 |
351
+ | --- | --- |
352
+ | 顶层配置 | `BkOTOptions`、`BkOTApplicationConfig`、`BkOTTransportConfig`、`BkOTTrackingConfig`、`BkOTTrackingConsent`、`BkOTContextConfig`、`BkOTPrivacyConfig`、`BkOTExtensionsConfig` |
353
+ | Transport | `BkOTBatchConfig`、`SignalExporterConfig`、`SignalExporterInputConfig`、`SignalExportersInputConfig`、`TraceExporterInputConfig`、`MetricExporterInputConfig` |
354
+ | View/Session/User | `BkOTViewConfig`、`BkOTSessionConfig`、`BkOTStartViewOptions`、`BkOTViewContext`、`BkOTSessionLifecycleEvent`、`BkOTUserContext` |
355
+ | Request | `BkOTRequestConfig`、`BkOTRequestEvent`、`BkOTRequestContext`、`BkOTRequestBodyConfig`、`BkOTRequestBodyRedactPayload`、`BkOTUrlMatcher` |
356
+ | 事件与 Hook | `BkOTActionEventPayload`、`BkOTCustomEventPayload`、`BkOTBeforeSendEvent`、`BkOTAttributesConfig`、`BkOTAttributeValue` |
357
+ | 插件 | `BkOTPlugin`、`BkOTRuntimeContext`、`BkOTActionPluginOptions`、`BkOTBlankScreenPluginOptions`、`BkOTDevicePluginOptions`、`BkOTErrorPluginOptions`、`BkOTLongTaskPluginOptions` |
358
+ | 实例与解析结果 | `BkOTInstance`、`PluginManager`、`ResolvedBkOTConfig`、`ResolvedApplicationConfig`、`ResolvedTransportConfig`、`ResolvedViewConfig`、`ResolvedConfigHooks` |
359
+ | Schema | `RumAttributeKey`、`RumSpanClassification`、`RumSpanType`、`RumSpanResult` |
360
+
361
+ 如某个源码类型没有出现在本表,也没有从 `src/index.ts` 导出,则它不是包的公共契约。
@@ -0,0 +1,141 @@
1
+ <!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
2
+
3
+ # 架构与数据流
4
+
5
+ 本页描述当前 `src/` 的实现边界,适合 SDK 维护者、扩展插件作者和需要解释“为什么数据没有被导出”的接入方。
6
+
7
+ ## 源码模块
8
+
9
+ | 目录/文件 | 职责 | 稳定入口 |
10
+ | --- | --- | --- |
11
+ | `src/index.ts` | ESM 公共导出边界 | npm import 只能依赖这里导出的符号 |
12
+ | `src/browser.ts` | CDN/IIFE 入口 | 暴露 `window.BkOpenTelemetry` |
13
+ | `src/core/config.ts` | 输入类型、校验、默认值、Endpoint 与 Hook 解析 | `BkOTOptions`、`resolveConfig()` |
14
+ | `src/core/sdk.ts` | Provider、Exporter、生命周期、内置插件组合、公开实例 API | `BkOpenTelemetry` |
15
+ | `src/core/runtime-context.ts` | User/Session/View/Action 属性快照与历史归属 | `RumRuntimeContext` |
16
+ | `src/core/processor.ts` | Span/Metric/Log 的采样、上下文、自上报和 beforeSend 过滤 | 三个 Filtering 类 |
17
+ | `src/core/plugin.ts` | 插件契约、启动、并行 flush、反向 shutdown、错误隔离 | `createPlugin()` |
18
+ | `src/plugins/` | 浏览器采集与 RUM 语义 | 各 `create*Plugin()` |
19
+ | `src/schema/` | 归一字段、Span 类型、结果和耗时分桶 | `RUM_ATTRIBUTES`、`buildRumSpanAttributes()` |
20
+
21
+ 文档描述与源码冲突时,以 `src/index.ts` 的公开导出和对应实现为准。`dist/` 是构建产物,不作为文档事实源。
22
+
23
+ ## 构造、启动与关闭
24
+
25
+ ### 构造阶段
26
+
27
+ `new BkOpenTelemetry(options)` 同步完成:
28
+
29
+ 1. `resolveConfig()` 校验 `application.name`、Transport 和已启用信号的 Endpoint。
30
+ 2. 创建 Resource、TracerProvider、MeterProvider、LoggerProvider。
31
+ 3. 根据三类信号开关决定是否创建 exporter、processor 或 metric reader。
32
+ 4. 创建运行时上下文;初始状态尚无 Session/View,也未命中采样。
33
+ 5. `autoStart !== false` 时异步调用 `start()`。
34
+
35
+ 因此,需要在启动前注册扩展或立即创建手动 View 时,应显式设置 `autoStart: false`。
36
+
37
+ ### 启动阶段
38
+
39
+ `start()` 幂等。获得 Consent 且 `enabled=true` 时,插件按以下顺序初始化:
40
+
41
+ 1. 上下文:Session → Device → Activity → View → Resource Observer。
42
+ 2. 请求:统一 Fetch/XHR patch。
43
+ 3. RUM:Error → Web Vitals → Blank Screen → Action → 按需 WebSocket / Long Task / CSP。
44
+ 4. 接入方 `extensions.plugins`。
45
+ 5. 接入方 OpenTelemetry instrumentations。
46
+
47
+ 单个插件 `init()` 抛错不会阻断其他插件;仅在 `debug: true` 时输出 warning。Consent 撤销后再授权会重新执行插件 `init()`,插件必须在 `shutdown()` 中完整释放监听和 patch。
48
+
49
+ ### flush 与 shutdown
50
+
51
+ - `flush()`:并行刷新插件,再 force flush Trace、Metric、Log provider。
52
+ - `shutdown()`:反向关闭插件,结束/刷新最终数据,移除页面生命周期监听,关闭三个 provider。
53
+ - `shutdown()` 后同一实例不能重新启动;需要重新创建实例。
54
+ - SDK 在 `pagehide` 和页面变为 hidden 时主动调用 `flush()`。
55
+
56
+ ## 从浏览器事件到 OTLP
57
+
58
+ 一次事件的公共路径是:
59
+
60
+ 1. 插件或公开 API 观察浏览器事件。
61
+ 2. 从 `RumRuntimeContext` 读取事件发生时对应的 User、Session、View、Action 属性。
62
+ 3. 构造原生 OpenTelemetry Span、Metric datapoint 或 LogRecord。
63
+ 4. 应用 URL/属性脱敏和事件级 Hook。
64
+ 5. Filtering processor/exporter 校验采样与上下文。
65
+ 6. 通过对应 OTLP HTTP exporter 上报。
66
+
67
+ 不同信号的最终过滤规则不同:
68
+
69
+ | 信号 | 接受条件 | 最终 Hook |
70
+ | --- | --- | --- |
71
+ | Span | 已采样,且同时有有效 `session.id`、`view.id`;排除 SDK 上报请求和请求级丢弃标记 | `tracking.beforeSend` |
72
+ | Log | 同 Span;`session.start/rotate` 允许只有有效 Session | `tracking.beforeSend` |
73
+ | Metric | datapoint 带内部已采样标记;导出前移除该标记 | 无全局 beforeSend |
74
+
75
+ 这意味着手动模式首次 `startView()` 之前,普通 Span/Log 不会导出;只创建原生 meter 数据但没有使用 SDK 采样属性的自定义 Metric 也不会导出。
76
+
77
+ ## 运行时上下文与历史归属
78
+
79
+ 运行时上下文维护当前属性,也保留有限的变更时间线。PerformanceObserver 经常在事件结束后才回调,因此 `startSpan(..., { startTime, contextTime })` 可以按事件真实发生时间解析其所属 Session/View/Action,避免把旧页面资源归到新 View。
80
+
81
+ ### Span 与 Log
82
+
83
+ Span/Log 可携带唯一关联字段:
84
+
85
+ - `user.id`
86
+ - `session.id`
87
+ - `view.id`、`view.name`、`view.url`、`view.url_path_group`
88
+ - 活动期间的 `action.id`
89
+
90
+ ### Metric
91
+
92
+ Metric 只保留 `view.url_path_group` 等低基数属性,不携带 `session.id`、`view.id`、`action.id`。需要从聚合指标下钻到具体访问时,查询同名语义 Span 或 View Snapshot Log,或由后端使用 exemplar/派生数据建立关联。
93
+
94
+ ## Session、采样与 Consent
95
+
96
+ 三者是不同控制层:
97
+
98
+ | 控制层 | 决定什么 | 运行期变化 |
99
+ | --- | --- | --- |
100
+ | `enabled` | 实例是否启动采集 | 构造后不提供 Setter |
101
+ | Consent | 是否安装采集副作用、创建 Session/View | `setTrackingConsent()` 可授权/撤销 |
102
+ | `session.sampleRate` | 有效 Session 的数据是否进入导出链路 | Session 轮换后用新 ID 重新计算 |
103
+ | Signal 开关 | 是否存在对应 exporter/processor/reader | 构造时固定 |
104
+
105
+ Session 采样由 `application.name + session.id` 稳定 hash 决定,同一 Session 的三类信号保持一致。插件仍可维护页面生命周期,但未采样数据会在创建或导出路径被丢弃。
106
+
107
+ ## 请求采集设计
108
+
109
+ Fetch/XHR 由 `createCommonInstrumentationsPlugin()` 的单一生命周期直接 patch,不叠加官方 Fetch/XHR instrumentation:
110
+
111
+ - `excludedUrls` 在最前面完全排除请求。
112
+ - 开始请求时创建 `browser.resource` CLIENT Span,并登记 View/Action 活动。
113
+ - 只有 `allowedTracingUrls` 命中且 Trace 开启时才调用全局 propagator 注入。SDK 成功注册默认 W3C propagator 时注入 `traceparent`/已有 `tracestate`;宿主已有全局 propagator 时,实际 Header 由宿主决定。
114
+ - Resource Observer 把同一 URL/时间窗的 PerformanceResourceTiming 匹配回请求 Span。
115
+ - `request.beforeSend` 可修改请求事件属性或标记丢弃该 Span。
116
+ - 配置 Body 且 Log 开启时,异步生成关联 `trace.id` / `span.id` 的 `browser.request.body` Log。
117
+ - SDK 自身所有已启用 OTLP Endpoint 始终排除,防止递归上报。
118
+
119
+ 静态资源复用同一个 Resource Observer,但 Fetch/XHR entry 只用于 timing 匹配,不再创建第二条资源 Span。
120
+
121
+ ## 脱敏与 Hook 顺序
122
+
123
+ | 入口 | 作用范围 | 适合用途 |
124
+ | --- | --- | --- |
125
+ | `privacy.redactUrl` | SDK 写入的 URL 类属性 | 删除 query/hash、模板化路径 |
126
+ | `privacy.redactAttributes` | 通过 SDK `startSpan()`、`emitLog()` 和内置插件显式应用的属性 | 删除敏感业务字段 |
127
+ | `tracking.request.beforeSend` | 单个 Fetch/XHR,带原始 Request/Response/XHR 上下文 | 请求专属补充或丢弃 |
128
+ | Request Body `redact` | 单个请求/响应 Body,必填 | 内容级脱敏;返回 `undefined` 跳过该 Body |
129
+ | `tracking.beforeSend` | Span/Log 进入底层 processor 前 | 最终兜底修改或丢弃;不作用于 Metric |
130
+
131
+ 第三方 instrumentation 自己生成的属性不经过 SDK 的 `redactAttributes` 构造路径。若要统一约束第三方 Span,应在 `tracking.beforeSend` 中做最终清理。
132
+
133
+ ## 扩展边界
134
+
135
+ - RUM 语义、Session/View 关联、Log 或活动总线:使用 `createPlugin()`。
136
+ - 已有标准 OpenTelemetry instrumentation:通过 `extensions.instrumentations` 或 `useInstrumentation()` 注册。
137
+ - 自定义 Log 使用 `context.emitLog()`,不要直接 `context.logger.emit()`,否则不会自动合并运行时上下文。
138
+ - 自定义 Span 优先使用 `context.startSpan()`,它会应用运行时属性与脱敏。
139
+ - 当前包没有导出稳定的自定义 Metric 采样属性/helper。直接使用 `context.meter` 创建的数据点默认无法通过 `FilteringMetricExporter`;不要依赖内部 `bk.rum.sampled` 字段,也不要把 `getRuntimeAttributes()` 中的唯一 Session/View/Action ID 整体复制到 labels。需要稳定扩展时优先使用 Span/Log,或先在 SDK 内补充公共 Metric API。
140
+
141
+ 完整契约与示例见[自定义插件](./custom-plugin.md)。