@blueking/open-telemetry 0.0.15 → 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.
@@ -2,50 +2,26 @@
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({
12
+ const options: BkOTOptions = {
13
13
  application: { name: 'bk-rum-demo' },
14
14
  transport: { endpoint: 'https://rum-collector.example.com' },
15
- });
15
+ };
16
+
17
+ const bkOT = new BkOpenTelemetry(options);
16
18
  ```
17
19
 
18
- ### 实例成员总览
19
-
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
- | `setTrackingConsent(consent)` | `(consent) => Promise<void>` | 授予或撤销采集授权,并启动或停止采集。 |
31
- | `startView(options?)` | `(options?) => void` | 结束当前 View 并创建新 View。可在 SDK 启动前调用。 |
32
- | `setViewName(name)` | `(name) => void` | 更新当前 View 名称,不创建新 View。 |
33
- | `setViewLoadingTime()` | `() => void` | 使用当前时刻覆盖当前 View 的自动页面稳定耗时。 |
34
- | `reportAction(payload)` | `(payload) => void` | 手动上报用户动作(受采样控制)。 |
35
- | `reportCustomEvent(payload)` | `(payload) => void` | 手动上报自定义事件(受采样控制)。 |
36
- | `startSpan(name, attributes?, options?)` | `(...) => Span` | 创建并返回一个 span,自动带上运行时属性与脱敏。 |
37
- | `emitLog(record)` | `(record) => void` | 发送一条 log,自动合并运行时属性与脱敏。 |
38
- | `getRuntimeAttributes()` | `() => Attributes` | 读取当前运行时公共属性快照。 |
39
- | `setRuntimeAttributes(attributes)` | `(attributes) => void` | 写入运行时公共属性。 |
40
- | `applyRedact(attributes)` | `(attributes) => Attributes` | 对属性执行一次 `privacy.redactAttributes`。 |
41
- | `config` | `ResolvedBkOTConfig` | 解析后的只读配置。 |
42
- | `tracer` / `meter` / `logger` | OpenTelemetry 原生对象 | 用于直接操作三类信号 provider。 |
43
-
44
- > `startSpan` / `emitLog` / `getRuntimeAttributes` 等既是实例方法,也是自定义插件 `init(context)` 中 `context` 的能力,见[自定义插件](./custom-plugin.md)。
45
-
46
- ### start
47
-
48
- 启动 SDK,注册 provider、instrumentation 和插件。
20
+ 构造函数同步解析配置并创建三个 OpenTelemetry Provider;`autoStart: true` 时随后异步启动采集。完整配置见[配置参考](./configuration.md)。
21
+
22
+ ## 生命周期方法
23
+
24
+ ### start()
49
25
 
50
26
  ```ts
51
27
  const bkOT = new BkOpenTelemetry({
@@ -54,178 +30,250 @@ const bkOT = new BkOpenTelemetry({
54
30
  transport: { endpoint: 'https://rum-collector.example.com' },
55
31
  });
56
32
 
33
+ bkOT.use(myPlugin);
57
34
  await bkOT.start();
58
35
  ```
59
36
 
60
- ### shutdown
37
+ 启动 Session、View、内置插件、接入方插件和 instrumentations,并安装页面隐藏时的 flush 监听。重复调用 `start()` 不会重复启动。
61
38
 
62
- 刷新数据、关闭 provider,并执行插件清理。关闭后不应再重启同一个实例。
39
+ ### flush()
63
40
 
64
41
  ```ts
65
- await bkOT.shutdown();
42
+ await bkOT.flush();
66
43
  ```
67
44
 
68
- ### flush
45
+ 先并行调用已启动插件的 `flush()`,再 force flush Trace、Metric、Log Provider。SDK 已在 `pagehide` 和页面变为 hidden 时触发 flush;业务只需在关键流程完成后按需主动调用。
69
46
 
70
- 立即刷新插件、trace、metric、log。
47
+ ### shutdown()
71
48
 
72
49
  ```ts
73
- window.addEventListener('beforeunload', () => {
74
- void bkOT.flush();
75
- });
50
+ await bkOT.shutdown();
76
51
  ```
77
52
 
78
- ### use
79
-
80
- 注册自定义插件,必须在 `start()` 前调用。
81
-
82
- ```ts
83
- bkOT.use(
84
- createPlugin({
85
- name: 'biz-plugin',
86
- init(context) {
87
- const span = context.startSpan('custom.biz_plugin_ready');
88
- span.end();
89
- },
90
- }),
91
- );
92
- ```
53
+ 反向关闭插件、结束待处理事件、刷新 Provider 并清理浏览器 patch/监听。该方法幂等;关闭后不能重新启动同一实例,再调用 `start()` 会抛错。
93
54
 
94
- ### useInstrumentation
55
+ ## Consent
95
56
 
96
- 注册额外 OpenTelemetry instrumentation,必须在 `start()` 前调用。
57
+ ### setTrackingConsent(consent)
97
58
 
98
59
  ```ts
99
- bkOT.useInstrumentation(new SomeWebInstrumentation());
100
- ```
60
+ const bkOT = new BkOpenTelemetry({
61
+ application: { name: 'consent-demo' },
62
+ privacy: { trackingConsent: 'not-granted' },
63
+ transport: { endpoint: 'https://rum-collector.example.com' },
64
+ });
101
65
 
102
- ### setUser
66
+ await bkOT.setTrackingConsent('granted');
67
+ await bkOT.setTrackingConsent('not-granted');
68
+ ```
103
69
 
104
- 更新用户上下文。
70
+ - 未授权:不创建 Session/View,不启动插件,不 patch 浏览器 API。
71
+ - 授权:启动采集并建立新的 Session/View。
72
+ - 撤销:关闭采集副作用并 flush 已允许的数据。
73
+ - 再授权:插件会再次执行 `init()`。
105
74
 
106
- ```ts
107
- bkOT.setUser({
108
- id: 'user-12345',
109
- });
110
- ```
75
+ 该方法在 `autoStart: false` 且尚未 `start()` 时只更新状态;随后 `start()` 使用最新 Consent。
111
76
 
112
- ### setTrackingConsent
77
+ ## User 与 View
113
78
 
114
- 运行期更新采集授权。撤销授权会停止插件与浏览器 API patch,并刷新已允许采集的数据;再次授权会重新建立 Session/View 和采集能力。
79
+ ### setUser(user)
115
80
 
116
81
  ```ts
117
- await bkOT.setTrackingConsent('granted');
118
- await bkOT.setTrackingConsent('not-granted');
82
+ bkOT.setUser({ id: 'user-12345' });
83
+ bkOT.setUser({ id: undefined });
119
84
  ```
120
85
 
121
- ### startView
86
+ 更新后续事件的 `user.id`。SDK 不 hash、不脱敏、不改写该值。
122
87
 
123
- 创建新的 View,并结束前一个 View。`view.id` 由 SDK 生成,业务侧不能覆盖。
88
+ ### startView(options?)
89
+
90
+ 结束当前 View 并创建新 View,`view.id` 始终由 SDK 生成。
124
91
 
125
92
  ```ts
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();
126
101
  bkOT.startView({
127
- name: '首页',
128
- url: window.location.href,
129
- attributes: {
130
- 'biz.owner': 'portal-team',
131
- },
102
+ name: '订单详情',
103
+ url: location.href,
104
+ attributes: { 'biz.owner': 'order-team' },
132
105
  });
133
106
  ```
134
107
 
135
- ### setViewName
108
+ `BkOTStartViewOptions` 包含 `name?`、`url?`、`attributes?`。调用时必须已有采样有效的 Session;例如 `autoStart: false` 且尚未 `await start()`、未授权或未采样时,调用会被忽略。自动启动过程中、Page View 插件尚未初始化时发出的有效命令会由运行时队列交给插件消费,但接入代码仍推荐显式等待 `start()`。`attributes` 不能覆盖 SDK 的 Session/View 保留字段。
136
109
 
137
- 只修改当前 View 的 `view.name`,后续子事件使用新名称。
110
+ ### setViewName(name)
138
111
 
139
112
  ```ts
140
- bkOT.setViewName('首页-新版');
113
+ bkOT.setViewName('订单详情-只读');
141
114
  ```
142
115
 
143
- ### setViewLoadingTime
116
+ 更新当前 View 名称,不创建新 View。后续子事件使用新名称,View Snapshot 产生 update。
144
117
 
145
- 当自动页面活动无法表达业务真正的渲染完成点时,手动覆盖当前 View 的 `view.loading_time`。每次调用都会替换前一次结果。
118
+ ### setViewLoadingTime()
146
119
 
147
120
  ```ts
148
121
  await renderAsyncPage();
149
122
  bkOT.setViewLoadingTime();
150
123
  ```
151
124
 
152
- ### reportAction
125
+ 用“当前时刻 - View 开始时刻”覆盖自动 `view.loading_time`。每次调用替换前一次值;没有有效 View 时忽略。
153
126
 
154
- 手动上报用户动作。
127
+ ## 手动事件
128
+
129
+ ### reportAction(payload)
155
130
 
156
131
  ```ts
157
132
  bkOT.reportAction({
158
133
  name: '保存',
159
- attributes: {
160
- 'biz.form': 'alarm-strategy',
161
- },
134
+ attributes: { 'biz.form': 'alarm-strategy' },
162
135
  });
163
136
  ```
164
137
 
165
- ### reportCustomEvent
138
+ 创建并立即结束 `action.custom` Span,写入新的 `action.id`、`action.name` 和 `action.type=custom`。它不会触发自动点击的活动耗时、关联计数或挫败信号计算。
166
139
 
167
- 手动上报自定义事件。
140
+ ### reportCustomEvent(payload)
168
141
 
169
142
  ```ts
170
143
  bkOT.reportCustomEvent({
171
144
  name: 'strategy_saved',
172
- attributes: {
173
- 'biz.strategy_id': '10001',
174
- },
145
+ attributes: { 'biz.strategy_id': '10001' },
175
146
  });
176
- ```
177
-
178
- 带错误的自定义事件:
179
147
 
180
- ```ts
181
148
  bkOT.reportCustomEvent({
182
149
  name: 'strategy_save_failed',
183
150
  error: new Error('validation failed'),
184
- attributes: {
185
- 'biz.strategy_id': '10001',
186
- },
187
151
  });
188
152
  ```
189
153
 
190
- ## 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()` 是保留完整类型推导的恒等构造器。
191
242
 
192
243
  ```ts
193
244
  import { createPlugin } from '@blueking/open-telemetry';
194
245
 
195
- export const plugin = createPlugin({
246
+ const plugin = createPlugin({
196
247
  name: 'page-visible',
197
- init(context) {
198
- context.emitLog({
199
- severityText: 'INFO',
200
- body: 'plugin init',
201
- attributes: {
202
- 'document.visibility_state': document.visibilityState,
203
- },
204
- });
205
- },
248
+ enabled: config => config.enabled,
249
+ init(context) {},
250
+ flush() {},
251
+ shutdown() {},
206
252
  });
207
253
  ```
208
254
 
209
- ## RUM_ATTRIBUTES
255
+ `BkOTPlugin` 的 `enabled` 可为布尔值或接收 `ResolvedBkOTConfig` 的函数。Plugin Manager 顺序启动、并行 flush、反向 shutdown,并隔离单个插件的初始化错误。
210
256
 
211
- `RUM_ATTRIBUTES` 提供字段 key 常量,避免手写字符串。
257
+ ## Schema 辅助 API
212
258
 
213
- ```ts
214
- import { RUM_ATTRIBUTES } from '@blueking/open-telemetry';
259
+ ### RUM_ATTRIBUTES
260
+
261
+ 归一字段 key 常量。
215
262
 
263
+ ```ts
216
264
  bkOT.reportCustomEvent({
217
265
  name: 'biz_event',
218
- attributes: {
219
- [RUM_ATTRIBUTES.targetLabel]: 'submit-order',
220
- },
266
+ attributes: { [RUM_ATTRIBUTES.targetLabel]: 'submit-order' },
221
267
  });
222
268
  ```
223
269
 
224
- ## RUM_SPAN_TYPE 与 buildRumSpanAttributes
270
+ ### RUM_SPAN_TYPE / RUM_SPAN_RESULT
225
271
 
226
- ```ts
227
- import { RUM_SPAN_TYPE, buildRumSpanAttributes } from '@blueking/open-telemetry';
272
+ 分别提供标准 `span_type` 与 `result` 值。
273
+
274
+ ### buildRumSpanAttributes(classification)
228
275
 
276
+ ```ts
229
277
  const span = bkOT.startSpan('custom.cache_hit', {
230
278
  ...buildRumSpanAttributes({
231
279
  spanType: RUM_SPAN_TYPE.custom,
@@ -235,26 +283,79 @@ const span = bkOT.startSpan('custom.cache_hit', {
235
283
  targetValue: true,
236
284
  }),
237
285
  });
238
-
239
286
  span.end();
240
287
  ```
241
288
 
242
- ## resolveConfig
289
+ ### getDurationBucket(duration)
290
+
291
+ 返回 `<100ms`、`100~500ms`、`500ms~2s`、`>2s` 之一。
292
+
293
+ ### buildRumSpanAttributes 相关类型
243
294
 
244
- `resolveConfig()` 可用于预览 SDK 核心配置解析结果。插件配置不会在这里展开默认值;内置插件会在各自创建时处理开关、默认值和参数兜底。
295
+ 公开 `RumSpanClassification`、`RumSpanType`、`RumSpanResult`,用于扩展插件保持同一归一模型。
296
+
297
+ ## resolveConfig(options)
245
298
 
246
299
  ```ts
247
300
  import { resolveConfig } from '@blueking/open-telemetry';
248
301
 
249
302
  const config = resolveConfig({
250
- application: {
251
- name: 'bk-rum-demo',
252
- },
253
- transport: {
254
- endpoint: 'https://rum-collector.example.com',
255
- },
303
+ application: { name: 'bk-rum-demo' },
304
+ transport: { endpoint: 'https://rum-collector.example.com' },
256
305
  });
257
306
 
258
- console.log(config.application.name);
259
- console.log(config.transport.traces.endpoint);
307
+ console.log(config.transport.traces && config.transport.traces.endpoint);
260
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)。