@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.
@@ -18,6 +18,8 @@
18
18
  3. `schema`:负责 RUM 字段、span 类型、结果、耗时分桶等归一化模型。
19
19
  4. `browser` / `index`:分别提供 CDN 全局入口(`https://unpkg.com/@blueking/open-telemetry/dist/bk-rum.global.js`)和 ESM 模块入口(`@blueking/open-telemetry`)。
20
20
 
21
+ 完整能力、默认开关与信号产出见[能力矩阵](./capabilities.md),初始化顺序、上下文和导出过滤见[架构与数据流](./architecture.md)。
22
+
21
23
  ## 最小示例
22
24
 
23
25
  ```ts
@@ -90,6 +92,20 @@ await bkOT.start();
90
92
 
91
93
  `use()`、`useInstrumentation()` 和 `extensions` 注册都必须发生在 `start()` 前。
92
94
 
95
+ 手动 View 也应在 `await start()` 建立 Session 后创建:
96
+
97
+ ```ts
98
+ const bkOT = new BkOpenTelemetry({
99
+ application: { name: 'manual-view-demo' },
100
+ autoStart: false,
101
+ transport: { endpoint: 'https://rum-collector.example.com' },
102
+ tracking: { view: { tracking: 'manual' } },
103
+ });
104
+
105
+ await bkOT.start();
106
+ bkOT.startView({ name: '订单详情', url: location.href });
107
+ ```
108
+
93
109
  ## CDN
94
110
 
95
111
  ```html
@@ -2,7 +2,7 @@
2
2
 
3
3
  # 插件总览
4
4
 
5
- 插件是 `@blueking/open-telemetry` 的能力边界。获得采集授权后,SDK 先建立 Device、Session、View 上下文,再启动请求采集和其他 RUM 插件。
5
+ 插件是 `@blueking/open-telemetry` 的能力边界。获得采集授权后,SDK 先建立 Session、Device、View 上下文,再启动请求采集和其他 RUM 插件。
6
6
 
7
7
  ## 默认插件组合
8
8
 
@@ -17,6 +17,7 @@ new BkOpenTelemetry({
17
17
  webVitals: true,
18
18
  blankScreen: true,
19
19
  device: true,
20
+ action: true,
20
21
  },
21
22
  });
22
23
  ```
@@ -29,8 +30,8 @@ new BkOpenTelemetry({
29
30
  | ---------- | ----------------------------------------------------------------- | ----------------------------- |
30
31
  | 基础上下文 | Session、View、`device` | log、span、runtime attributes |
31
32
  | 性能体验 | View Loading Time、`resource`、`webVitals`、`blankScreen`、`longTask` | span、metric、log |
32
- | 错误安全 | `error`、`cspViolation` | span、log |
33
- | 网络扩展 | request instrumentation、`websocket` | span、metric |
33
+ | 错误安全 | `error`、`cspViolation` | span |
34
+ | 网络扩展 | Fetch/XHR request patch、`websocket` | span、metric、log |
34
35
  | 用户行为 | `action`、`reportAction()` | span |
35
36
 
36
37
  ## 插件启用规则
@@ -68,7 +69,7 @@ new BkOpenTelemetry({
68
69
 
69
70
  ## session
70
71
 
71
- `session` 维护 `session.id`,并在会话开始和轮换时写入 log。它是所有 RUM 信号的关联边界,命中采样后始终开启,不能关闭。
72
+ `session` 维护 `session.id`,并在会话开始和轮换时写入 log。它是所有 RUM 信号的关联边界,获得 Consent 后始终开启,不能关闭;是否导出由 Session 采样决定。
72
73
 
73
74
  默认规则:
74
75
 
@@ -143,10 +144,12 @@ new BkOpenTelemetry({
143
144
  ```ts
144
145
  const bkOT = new BkOpenTelemetry({
145
146
  application: { name: 'order-web' },
147
+ autoStart: false,
146
148
  transport: { endpoint: 'https://rum-collector.example.com' },
147
149
  tracking: { view: { tracking: 'manual' } },
148
150
  });
149
151
 
152
+ await bkOT.start();
150
153
  bkOT.startView({
151
154
  name: '订单详情',
152
155
  url: window.location.href,
@@ -179,7 +182,7 @@ new BkOpenTelemetry({
179
182
  });
180
183
  ```
181
184
 
182
- 自动命名默认只读取 `data-bk-action-name`、`aria-label`、`title` 等显式或无障碍名称,不读取任意文本内容。如确实需要文本命名,可显式设置 `nameCollection: 'text'`,并自行评估隐私风险。
185
+ 自动命名在默认 `explicit` 模式只向上查找 `data-bk-action-name`;没有显式名称时退回目标元素标签名。设置 `nameCollection: 'text'` 后才会继续读取 label、按钮值、`aria-label`、`alt`、`name`、`title`、`placeholder` 和 DOM 文本,并自行评估隐私风险。
183
186
 
184
187
  对关键业务动作,推荐使用 `reportAction()` 显式上报,字段更稳定。
185
188
 
@@ -403,115 +406,140 @@ new BkOpenTelemetry({
403
406
 
404
407
  # 网络与扩展插件
405
408
 
406
- 以下片段聚焦 `tracking` 配置,实际初始化仍需提供必填的 `application.name` 和有效的 `transport` endpoint 配置。
409
+ 网络能力覆盖 Fetch/XHR 与 WebSocket。两者都会 patch 浏览器全局 API,同一页面只应运行一个 SDK 实例。
410
+
411
+ 以下片段聚焦 `tracking`,实际初始化仍需提供 `application.name` 和有效 Transport。
412
+
413
+ ## Fetch/XHR request
414
+
415
+ `tracking.request` 默认开启。当前实现由 SDK 自己统一 patch `window.fetch` 与 `XMLHttpRequest.prototype.open/send`,不使用官方 Fetch/XHR instrumentation,也不会为同一请求叠加两套生命周期。
407
416
 
408
- 网络类能力覆盖 Fetch/XHR Resource 和 WebSocket。由于这些能力会 patch 浏览器原生 API,微前端或多 SDK 实例场景需要特别注意避免重复初始化。
417
+ ### 请求生命周期
409
418
 
410
- ## request instrumentation
419
+ 一次请求按以下顺序处理:
411
420
 
412
- request 默认开启,使用 OpenTelemetry 官方 Fetch/XHR instrumentation 生成一个请求 Resource Span,并对 URL 做脱敏。静态资源观察器会跳过 Fetch/XHR timing,因此同一请求不会重复上报。
421
+ 1. 转成绝对 URL,检查 SDK 自身 OTLP Endpoint 与 `excludedUrls`。
422
+ 2. 创建名为 `browser.resource`、kind 为 `CLIENT` 的 Span。
423
+ 3. 记录 View/Action 页面活动;`view.excludedActivityUrls` 可只排除活动等待,不丢弃 Span。
424
+ 4. `allowedTracingUrls` 命中且 Trace 开启时进入传播 Header 注入分支;默认 W3C propagator 注入 `traceparent`,宿主已有全局 propagator 时以实际实现为准。
425
+ 5. 请求完成后写入状态、结果、错误和 `request.beforeSend` 属性。
426
+ 6. 等待最多 200ms 匹配 Resource Timing,把网络阶段补回同一 Span。
427
+ 7. 如已配置 Body 且 Log 开启,异步生成关联原 `trace.id` / `span.id` 的诊断 Log。
413
428
 
414
- **产出遥测**:Resource Span(如 `HTTP GET`,`span_type=resource`、`resource.type=fetch|xhr`),带 `resource.url`、`resource.method`、`resource.status_code`、网络阶段 span events 和请求/响应大小。
429
+ **产出遥测**:Span `browser.resource`,`span_type=resource`、`resource.type=fetch|xhr`,常用属性包括 `resource.url`、`resource.method`、`resource.status_code`、`http.*`、`url.full`、网络阶段与响应体积。
415
430
 
416
431
  ```ts
417
432
  new BkOpenTelemetry({
418
- privacy: {
419
- redactUrl: url => url.replace(/\/orders\/\d+/g, '/orders/:id'),
420
- },
433
+ application: { name: 'request-demo' },
434
+ transport: { endpoint: 'https://collector.example.com' },
421
435
  tracking: {
422
436
  request: {
423
437
  excludedUrls: [/\/health(?:\?|$)/],
424
- beforeSend: event => {
425
- event.attributes['business.module'] = 'order';
426
- return true;
438
+ beforeSend(event, context) {
439
+ event.attributes['request.transport'] = context.type;
440
+ return event.resource.statusCode !== 404;
427
441
  },
428
442
  },
429
443
  },
430
444
  });
431
445
  ```
432
446
 
433
- ### traceparent 透传(前后端 trace 串联)
447
+ `request.beforeSend` 在请求完成后执行,可修改 Span attributes;返回 `false` 会标记该 Span 在最终 processor 中丢弃,并立即跳过该请求的 Body Log。Hook 抛错不会中断业务请求,`debug: true` 时输出 warning。
448
+
449
+ ### excludedUrls 与 excludedActivityUrls
450
+
451
+ | 配置 | 是否创建 Span | 是否计入 View/Action 活动 | 适用场景 |
452
+ | --- | --- | --- | --- |
453
+ | `tracking.request.excludedUrls` | 否 | 否 | 探活、埋点、无需采集的请求 |
454
+ | `tracking.view.excludedActivityUrls` | 是 | 否 | 长轮询、SSE、流式接口,不应阻塞页面稳定 |
455
+
456
+ 两者都支持字符串包含、RegExp 和函数 matcher。
434
457
 
435
- 只有命中 `allowedTracingUrls` 的请求才会注入 W3C `traceparent`。同源请求也不会隐式注入:
458
+ ### traceparent 注入条件
459
+
460
+ 只有 `allowedTracingUrls` 命中且 Trace 信号开启时才进入传播 Header 注入分支;默认 W3C propagator 会注入 `traceparent`,同源请求也不隐式放行。
436
461
 
437
462
  ```ts
438
- new BkOpenTelemetry({
439
- tracking: {
440
- request: {
441
- allowedTracingUrls: ['api.example.com', /\.internal\.com\//],
442
- },
463
+ tracking: {
464
+ request: {
465
+ allowedTracingUrls: [
466
+ url => new URL(url).origin === 'https://api.example.com',
467
+ /^https:\/\/[^/]+\.internal\.example\.com\//,
468
+ ],
443
469
  },
444
- });
470
+ }
445
471
  ```
446
472
 
447
- 向跨域服务注入自定义头会触发 CORS 预检,目标服务需在 `Access-Control-Allow-Headers` 中放行 `traceparent`(以及按需的 `tracestate`)。
473
+ 字符串 matcher 使用包含匹配,例如 `'https://api.example.com'` 也会命中 `https://api.example.com.evil/`,不适合作为安全 origin 边界。需要精确控制时使用上面的 URL-aware 函数或带 `/` 边界的正则。
474
+
475
+ 跨域注入会触发 CORS 预检,目标服务必须在 `Access-Control-Allow-Headers` 放行实际使用的 Trace Header。SDK 成功注册自己的默认 W3C propagator 时通常注入 `traceparent`,并可能透传已有 `tracestate`;如果宿主已注册全局 propagator,实际 Header 由该 propagator 决定,可能还包含其他传播字段。
476
+
477
+ ### Resource Timing
448
478
 
449
- ### 错误请求 body
479
+ Fetch/XHR 与静态资源共用一个 Resource PerformanceObserver:
450
480
 
451
- body 默认不采集。显式配置 `request.body` 后,默认只采集 4xx/5xx、状态码 0 或网络异常请求的请求体和响应体,并生成关联原 Trace/Span 的 `browser.request.body` 诊断 Log:
481
+ - `initiatorType=fetch|xmlhttprequest` 的 entry 只用于匹配请求 Span,不再创建静态资源 Span。
482
+ - 通过 URL 与时间窗口匹配;找不到 entry 时请求 Span 仍正常结束。
483
+ - 跨域接口缺少 `Timing-Allow-Origin` 时,浏览器不会提供完整阶段字段。
484
+ - Trace 关闭时跳过 timing 等待,因为不存在可导出的请求 Span。
485
+
486
+ ### 请求/响应 Body
487
+
488
+ Body 默认关闭。开启时必须提供 `redact`,默认只采集状态未知、0 或 `>=400` 的请求:
452
489
 
453
490
  ```ts
454
- new BkOpenTelemetry({
455
- tracking: {
456
- request: {
457
- body: {
458
- capture: 'errors',
459
- maxSize: 10 * 1024,
460
- allowedContentTypes: ['application/json', /^text\//],
461
- redact: ({ body, kind }) =>
462
- kind === 'request' ? body.replace(/("(?:password|token)"\s*:\s*)"[^"]*"/g, '$1"***"') : body,
491
+ tracking: {
492
+ request: {
493
+ body: {
494
+ capture: 'errors',
495
+ maxSize: 10 * 1024,
496
+ allowedContentTypes: ['application/json', /^text\//],
497
+ redact({ body, kind }) {
498
+ if (kind === 'request') {
499
+ return body.replace(/("(?:password|token)"\s*:\s*)"[^"]*"/g, '$1"***"');
500
+ }
501
+ return body;
463
502
  },
464
503
  },
465
504
  },
466
- });
505
+ }
467
506
  ```
468
507
 
469
- Fetch Request 会在官方 request hook 中先 clone,Response 也通过 clone 限量读取,不消费业务侧原始流;XHR request body 复用官方 send patch 记录,不再增加一层原型 patch。不支持文本化的 FormData、ArrayBuffer 和二进制响应会跳过。
508
+ **产出遥测**:Log `browser.request.body`,错误请求为 ERROR,`capture: 'all'` 下成功请求为 INFO。
470
509
 
471
- ## websocket
510
+ - Fetch 的 Request/Response 通过 clone 限量读取,不消费业务原始流。
511
+ - XHR 支持文本与 JSON 响应。
512
+ - string、URLSearchParams、Blob 等可文本化请求可读取;FormData、ArrayBuffer 和二进制响应跳过。
513
+ - 默认 Content-Type:`text/*`、包含 `json`、`application/x-www-form-urlencoded`、`application/graphql`。
514
+ - `redact` 返回 `undefined` 时只跳过当前 request 或 response Body。
515
+ - Log 信号关闭时 Body 配置不生效。
472
516
 
473
- `websocket` 默认关闭。开启后会用 Proxy 包装 WebSocket,采集连接、消息大小、错误和关闭事件。
517
+ ## websocket
474
518
 
475
- **产出遥测**:span `websocket.connect`(`span_type=custom`,仅建连阶段);metric `browser.websocket.message.count` / `.message.bytes` / `.error.count` / `.connect.duration`;log `websocket.error` / `websocket.close`。
519
+ `tracking.websocket` 默认关闭。开启后用 Proxy 包装 `window.WebSocket`,保留静态常量、`instanceof` 与子类化行为。
476
520
 
477
521
  ```ts
478
522
  new BkOpenTelemetry({
479
- tracking: {
480
- websocket: true,
481
- },
523
+ application: { name: 'realtime-demo' },
524
+ transport: { endpoint: 'https://collector.example.com' },
525
+ tracking: { websocket: true },
482
526
  });
483
527
  ```
484
528
 
485
- 业务发送消息时无需改造。
529
+ **产出遥测**:
486
530
 
487
- ```ts
488
- const socket = new WebSocket('wss://message.example.com/ws');
531
+ - Span `websocket.connect`:只覆盖建连阶段,成功/失败后结束,不用长 Span 覆盖整个连接。
532
+ - Metric `browser.websocket.message.count`、`browser.websocket.message.bytes`:按 `in/out` 分组。
533
+ - Metric `browser.websocket.error.count`:按 `connect/runtime` 分组。
534
+ - Metric `browser.websocket.connect.duration`:只记录成功建连耗时。
535
+ - Log `websocket.error`、`websocket.close`:记录错误阶段和关闭详情。
489
536
 
490
- socket.addEventListener('open', () => {
491
- socket.send(JSON.stringify({ type: 'ping' }));
492
- });
493
- ```
537
+ 插件不读取消息内容,只计算数量和字节数。超过 64KB 的字符串使用 `string.length` 近似字节数,避免编码开销;CJK/emoji 会低估。相同 URL 的错误 Log 在 60 秒内最多 5 条,Error Counter 不受节流影响。
494
538
 
495
- ## 自定义网络事件
539
+ SDK shutdown 后新建连接不再采集;已存在连接上的包装会保留,但回调立即返回。若其他库后来替换了 `window.WebSocket`,shutdown 不会强行覆盖后来者。
496
540
 
497
- 如果业务已有请求封装,也可以在封装层补充更稳定的业务 span。
541
+ ## 与额外 instrumentation 的关系
498
542
 
499
- ```ts
500
- export const requestWithRum = async <T>(url: string, init?: RequestInit): Promise<T> => {
501
- const span = bkOT.startSpan('custom.biz_request', {
502
- 'biz.request.url': url.replace(/\/\d+/g, '/:id'),
503
- 'biz.request.method': init?.method || 'GET',
504
- });
543
+ `extensions.instrumentations` 适合已有标准 OpenTelemetry instrumentation。不要再注册覆盖 Fetch/XHR 或用户交互的 instrumentation,否则可能与内置 request/action 重复 patch、重复 Span。
505
544
 
506
- try {
507
- const response = await fetch(url, init);
508
- span.setAttribute('http.response.status_code', response.status);
509
- return response.json() as Promise<T>;
510
- } catch (error) {
511
- span.recordException(error as Error);
512
- throw error;
513
- } finally {
514
- span.end();
515
- }
516
- };
517
- ```
545
+ 需要 Session/View、`emitLog()`、页面活动或 RUM 归一字段时,优先写自定义插件,见[内置采集与扩展](./concepts.md)与[自定义插件](./custom-plugin.md)。
@@ -24,7 +24,7 @@ new BkOpenTelemetry({
24
24
 
25
25
  ## 属性脱敏
26
26
 
27
- `privacy.redactAttributes` 会在 SDK 自定义插件 emit 前过滤属性,适合删除 authorization、手机号、邮箱等字段。
27
+ `privacy.redactAttributes` 会处理通过 SDK `startSpan()`、`emitLog()` 以及内置插件显式应用的属性,适合删除 authorization、手机号、邮箱等字段。
28
28
 
29
29
  ```ts
30
30
  new BkOpenTelemetry({
@@ -40,6 +40,10 @@ new BkOpenTelemetry({
40
40
  });
41
41
  ```
42
42
 
43
+ 第三方 OpenTelemetry instrumentation 自己生成的 Span 属性不保证经过这一构造路径。需要统一清理第三方 Span 时,在 `tracking.beforeSend` 做最终兜底;该 Hook 作用于 Span/Log,不作用于 Metric。
44
+
45
+ `redactAttributes` 应返回完整可用的属性对象,不要只返回被修改的单个字段。
46
+
43
47
  ## 公共属性
44
48
 
45
49
  `context.attributes` 提供四类 hook:
@@ -42,7 +42,7 @@
42
42
  | span 名 | span_type | 来源 | 关键属性 | 备注 |
43
43
  | --- | --- | --- | --- | --- |
44
44
  | `browser.view` | `document` / `route` | View 管理器 | `view.name`、`view.loading_time`、`view.loading_time.source`、`url.previous`、`event.source`、`view.end_reason` | 有持续时间,下一次 View 或 pagehide 时结束 |
45
- | `HTTP <METHOD>` | `resource` | request 采集 | `resource.type=fetch\|xhr`、`resource.url`、`resource.method`、`resource.status_code`、网络阶段 events | span kind 为 CLIENT;Fetch/XHR 共用同一实现 |
45
+ | `browser.resource` | `resource` | Fetch/XHR request 采集 | `resource.type=fetch\|xhr`、`resource.url`、`resource.method`、`resource.status_code`、网络阶段属性 | span kind 为 CLIENT;Fetch/XHR 共用同一实现 |
46
46
  | `browser.resource` | `resource` | resource 插件 | `resource.type`、`resource.url`、`resource.duration`、网络阶段、`resource.render_blocking_status`、`resource.protocol`、`resource.cache.hit` | 仅静态资源,跳过 Fetch/XHR |
47
47
  | `browser.web_vital` | `vital` | webVitals 插件 | `vital.metric`、`vital.value`、`vital.rating`、`vital.id`、`rum.navigation.type`、`vital.<lcp\|cls\|inp\|fcp\|ttfb>.*` | 每个指标一条 |
48
48
  | `browser.blank_screen` | `error` | blankScreen 插件(二次确认白屏时) | `blank_screen.empty_ratio`、`blank_screen.reason`、`blank_screen.root_selector`、`blank_screen.root_found`、`blank_screen.*_sample_count`、`blank_screen.center_element` | 每个 View 最多一条 |
@@ -53,7 +53,7 @@
53
53
  | `csp.violation` | `error` | cspViolation 插件 | `csp.blocked_uri`、`csp.violated_directive`、`csp.effective_directive`、`csp.source_file`、`csp.line_number`、`csp.status_code`、`csp.fingerprint`、`csp.window_count`、`csp.original_policy`(窗口首条) | |
54
54
  | `websocket.connect` | `custom` | websocket 插件(仅建连阶段) | `url.full`、`url.scheme`、`server.address`、`network.protocol.name=websocket`、`target_domain` | 长连接生命周期不绑定 span |
55
55
  | `action.click` / `action.custom` | `action` | action 插件 / `reportAction()` | `action.id/name/type/target.*`、`action.loading_time`、`action.frustration.*`、`action.*.count` | 自动点击或手动动作;挫败信号仅自动点击 |
56
- | `custom.<name>` | `custom` | `reportCustomEvent()` / 自定义插件 | `rum.custom.name`、业务自定义属性 | 带 `error` 时附 `exception.*` |
56
+ | `custom.<name>` | `custom` | `reportCustomEvent()` / 自定义插件 | `rum.custom.name`、业务自定义属性 | 带 `error` 时记录 exception、设置错误 Status/Result,`span_type` 仍为 `custom` |
57
57
 
58
58
  ## Metric 清单
59
59
 
@@ -80,7 +80,7 @@
80
80
  | `session.start` | INFO | session 插件(首次新建) | `session.id`、`session.start_time`、`session.rotate.reason=init` |
81
81
  | `session.rotate` | INFO | session 插件(轮换) | + `session.previous_id`、`session.rotate.reason`(`inactivity` / `maxLifetime`) |
82
82
  | `browser.view` | INFO | View 管理器 | `view.snapshot.type=create\|update\|final`、`view.document_version`、`view.duration`、`view.is_active`、`view.loading_time` |
83
- | `browser.request.body` | ERROR(错误请求)/ INFO(`capture: 'all'` 的成功请求) | request instrumentation(仅显式配置 `request.body`) | `trace.id`、`span.id`、`request.body` / `response.body`、`*.body.content_type`、`*.body.truncated` |
83
+ | `browser.request.body` | ERROR(错误请求)/ INFO(`capture: 'all'` 的成功请求) | Fetch/XHR request patch(仅显式配置 `request.body`) | `trace.id`、`span.id`、`request.body` / `response.body`、`*.body.content_type`、`*.body.truncated` |
84
84
  | `websocket.error` | ERROR | websocket 插件 | `url.full`、`websocket.error.phase`、`websocket.error.window_count` |
85
85
  | `websocket.close` | INFO | websocket 插件 | `websocket.close.code`、`websocket.close.reason`、`websocket.close.was_clean` |
86
86
 
@@ -0,0 +1,79 @@
1
+ <!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
2
+
3
+ # 传输与采样
4
+
5
+ ## Endpoint
6
+
7
+ `transport.endpoint` 是可选根地址。未配置独立地址的已开启信号会基于它生成 `/v1/rum`、`/v1/metrics`、`/v1/logs`;单信号 `endpoint` 是完整 URL,不再拼接路径。
8
+
9
+ ```ts
10
+ new BkOpenTelemetry({
11
+ application: { name: 'demo' },
12
+ transport: {
13
+ endpoint: 'https://collector.example.com',
14
+ token: 'report-token',
15
+ signals: {
16
+ traces: {
17
+ endpoint: 'https://trace.example.com/v1/rum',
18
+ processor: 'batch',
19
+ batch: {
20
+ maxQueueSize: 2048,
21
+ maxExportBatchSize: 512,
22
+ scheduledDelayMillis: 5000,
23
+ exportTimeoutMillis: 30000,
24
+ },
25
+ },
26
+ metrics: { endpoint: 'https://metric.example.com/v1/metrics', intervalMillis: 60_000 },
27
+ logs: { endpoint: 'https://log.example.com/v1/logs' },
28
+ },
29
+ },
30
+ });
31
+ ```
32
+
33
+ ## 独立信号开关
34
+
35
+ 三类信号默认全部开启。设为 `false` 时,不创建对应 exporter、processor 或 metric reader:
36
+
37
+ ```ts
38
+ new BkOpenTelemetry({
39
+ application: { name: 'trace-only-demo' },
40
+ transport: {
41
+ signals: {
42
+ traces: { endpoint: 'https://trace.example.com/v1/rum' },
43
+ metrics: false,
44
+ logs: false,
45
+ },
46
+ },
47
+ });
48
+ ```
49
+
50
+ 校验规则:
51
+
52
+ - 至少开启一种信号,三类不能全部为 `false`。
53
+ - 每个开启信号必须有独立 endpoint,或能回退到根 `transport.endpoint`。
54
+ - 关闭 Trace 后不记录 Span,也不会向 `allowedTracingUrls` 注入 `traceparent`。
55
+ - 关闭 Metric 后不启动周期导出定时器。
56
+ - 关闭 Log 不影响 Session/View 上下文维护,但不会产生 Session、View Snapshot、HTTP body 等 Log。
57
+
58
+ 只开启 Metric 时没有精确 `view.id` 下钻链路;需要从指标定位具体 View 时,至少开启 Trace。
59
+
60
+ 请求头优先级:`token` 生成的 Authorization < `transport.headers` < 单 signal `headers`。
61
+
62
+ 浏览器 OTLP HTTP exporter 负责实际传输,SDK 在 `pagehide` 和页面进入 hidden 时触发 flush。`shutdown()` 会先结束 View 和插件,再 flush final Snapshot,最后关闭 provider。
63
+
64
+ ## Session 级确定性采样
65
+
66
+ ```ts
67
+ new BkOpenTelemetry({
68
+ application: { name: 'demo' },
69
+ transport: { endpoint: 'https://collector.example.com' },
70
+ session: { sampleRate: 0.05 },
71
+ });
72
+ ```
73
+
74
+ - `1` 表示全量,`0` 表示全部丢弃。
75
+ - 决定由 `application.name + session.id` 的稳定 hash 得出。
76
+ - 采样决定不写额外 storage;同一 Session 内 span/log/metric 决定一致。
77
+ - Session 续期后使用新 ID 重新计算。
78
+
79
+ Metric exporter 只接受带内部采样标记的数据点,并在传输前移除该标记。Metric 只保留低基数 `view.url_path_group`,精确 View 关联由 span/log/View Snapshot 的 `view.id` 提供。