@blueking/open-telemetry 0.0.22 → 0.0.24

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 (44) hide show
  1. package/README.md +256 -70
  2. package/dist/bk-rum.global.js +2 -2
  3. package/dist/bk-rum.global.js.map +1 -1
  4. package/dist/core/config.d.ts +4 -2
  5. package/dist/core/processor.d.ts +2 -2
  6. package/dist/core/runtime-context.d.ts +4 -0
  7. package/dist/core/sampling.d.ts +0 -1
  8. package/dist/index.d.ts +2 -2
  9. package/dist/index.js +395 -477
  10. package/dist/index.js.map +1 -1
  11. package/dist/plugins/blank-screen.d.ts +1 -1
  12. package/dist/plugins/common.d.ts +3 -4
  13. package/dist/plugins/web-vitals.d.ts +0 -5
  14. package/dist/schema/attributes.d.ts +6 -8
  15. package/dist/schema/span.d.ts +24 -15
  16. package/package.json +1 -1
  17. package/skills/bk-rum-otele/SKILL.md +26 -23
  18. package/skills/bk-rum-otele/references/actions.md +166 -0
  19. package/skills/bk-rum-otele/references/api.md +248 -215
  20. package/skills/bk-rum-otele/references/architecture.md +139 -37
  21. package/skills/bk-rum-otele/references/blank-screen.md +190 -0
  22. package/skills/bk-rum-otele/references/capabilities.md +175 -83
  23. package/skills/bk-rum-otele/references/configuration.md +226 -151
  24. package/skills/bk-rum-otele/references/data-model.md +156 -24
  25. package/skills/bk-rum-otele/references/errors-security.md +168 -0
  26. package/skills/bk-rum-otele/references/extensions.md +236 -0
  27. package/skills/bk-rum-otele/references/framework-integration.md +318 -75
  28. package/skills/bk-rum-otele/references/getting-started.md +186 -70
  29. package/skills/bk-rum-otele/references/network.md +258 -0
  30. package/skills/bk-rum-otele/references/performance.md +197 -0
  31. package/skills/bk-rum-otele/references/privacy.md +236 -67
  32. package/skills/bk-rum-otele/references/production.md +264 -0
  33. package/skills/bk-rum-otele/references/session-context.md +185 -0
  34. package/skills/bk-rum-otele/references/telemetry-reference.md +479 -51
  35. package/skills/bk-rum-otele/references/transport-sampling.md +318 -32
  36. package/skills/bk-rum-otele/references/troubleshooting.md +341 -151
  37. package/skills/bk-rum-otele/references/views-routing.md +211 -0
  38. package/skills/bk-rum-otele/references/concepts.md +0 -60
  39. package/skills/bk-rum-otele/references/custom-plugin.md +0 -170
  40. package/skills/bk-rum-otele/references/plugins-basic.md +0 -135
  41. package/skills/bk-rum-otele/references/plugins-error-security.md +0 -83
  42. package/skills/bk-rum-otele/references/plugins-experience.md +0 -124
  43. package/skills/bk-rum-otele/references/plugins-network.md +0 -32
  44. package/skills/bk-rum-otele/references/plugins.md +0 -62
@@ -10,7 +10,7 @@ export interface BkOTBlankScreenPluginOptions {
10
10
  confirmationDelay?: number;
11
11
  /** loading、骨架屏等不参与空白比例计算的元素。 */
12
12
  ignoreSelectors?: string[];
13
- /** 应用挂载根节点,默认 body。根节点不存在本身会被判为候选白屏。 */
13
+ /** 应用挂载根节点,默认 body。根节点不存在时回退到 body 检测。 */
14
14
  rootSelector?: string;
15
15
  /** 空白采样点比例阈值,默认 0.8。 */
16
16
  threshold?: number;
@@ -1,5 +1,4 @@
1
- import { REQUEST_DISCARD_ATTRIBUTE } from '../core/processor';
2
- import type { BkOTRequestConfig, BkOTRequestContext } from '../core/config';
1
+ import type { BkOTRequestConfig, BkOTRequestContext, BkOTRequestOutcome } from '../core/config';
3
2
  import type { BkOTPlugin, BkOTRuntimeContext } from '../core/plugin';
4
3
  import type { Span } from '@opentelemetry/api';
5
4
  interface RequestDetails {
@@ -7,6 +6,6 @@ interface RequestDetails {
7
6
  startedAt?: number;
8
7
  url?: string;
9
8
  }
10
- export { REQUEST_DISCARD_ATTRIBUTE };
11
- export declare const decorateRequestSpan: (context: BkOTRuntimeContext, span: Span, subtype: "fetch" | "xhr", domainContext: BkOTRequestContext, details?: RequestDetails) => void;
9
+ export declare const decorateRequestSpan: (context: BkOTRuntimeContext, span: Span, subtype: "fetch" | "xhr", domainContext: BkOTRequestContext, outcome: BkOTRequestOutcome, details?: RequestDetails) => void;
12
10
  export declare const createCommonInstrumentationsPlugin: (option: BkOTRequestConfig | boolean | undefined) => BkOTPlugin;
11
+ export {};
@@ -10,11 +10,6 @@
10
10
  *
11
11
  * 数值语义:CLS 是无量纲分数,FCP/INP/LCP/TTFB 的 vital.value 单位为 ms。
12
12
  *
13
- * Navigation Type:
14
- * 优先使用 metric.navigationType(web-vitals 内部计算,含 'back-forward-cache' 等准确值),
15
- * fallback 到 PerformanceNavigationTiming.type(注意 web-vitals 用连字符 'back-forward',
16
- * PerformanceNavigationTiming 用下划线 'back_forward',统一成连字符)。
17
- *
18
13
  * View 边界:FCP/LCP/TTFB 使用 web-vitals 的条目时间回查历史 View;CLS/INP 按 SDK View 重置,
19
14
  * CLS 使用 session window,INP 使用当前 View 的 p98 交互候选。
20
15
  *
@@ -18,11 +18,6 @@ export declare const RUM_ATTRIBUTES: {
18
18
  readonly deviceLogicalProcessorCount: "device.logical_processor_count";
19
19
  readonly deviceMemoryGib: "device.memory_gib";
20
20
  readonly deviceType: "device.type";
21
- readonly eventId: "event.id";
22
- readonly eventPhase: "event.phase";
23
- readonly eventTimestamp: "event.timestamp";
24
- readonly eventType: "event.type";
25
- readonly errorType: "error_type";
26
21
  readonly longTaskBlockingDuration: "long_task.blocking_duration";
27
22
  readonly longTaskDuration: "long_task.duration";
28
23
  readonly longTaskEntryType: "long_task.entry_type";
@@ -30,17 +25,17 @@ export declare const RUM_ATTRIBUTES: {
30
25
  readonly longTaskStartTime: "long_task.start_time";
31
26
  readonly networkEffectiveType: "network.effective_type";
32
27
  readonly nextHopProtocol: "resource.protocol";
33
- readonly result: "result";
34
- readonly rumSchemaVersion: "rum.schema.version";
28
+ readonly outcomeReason: "outcome.reason";
29
+ readonly outcomeType: "outcome.type";
35
30
  readonly serviceName: "service.name";
36
31
  readonly serviceVersion: "service.version";
37
32
  readonly osName: "os.name";
38
33
  readonly sessionHasReplay: "session.has_replay";
39
34
  readonly sessionId: "session.id";
40
35
  readonly sessionSampleRate: "session.sample_rate";
36
+ readonly sessionPhase: "session.phase";
41
37
  readonly sessionStartTime: "session.start_time";
42
38
  readonly sessionType: "session.type";
43
- readonly spanSubtype: "span_subtype";
44
39
  readonly spanType: "span_type";
45
40
  readonly userId: "user.id";
46
41
  readonly vitalMetric: "vital.metric";
@@ -55,9 +50,12 @@ export declare const RUM_ATTRIBUTES: {
55
50
  readonly viewLoadingTime: "view.loading_time";
56
51
  readonly viewLoadingType: "view.loading_type";
57
52
  readonly viewName: "view.name";
53
+ readonly viewPhase: "view.phase";
54
+ readonly viewSource: "view.source";
58
55
  readonly viewStartedAt: "view.started_at";
59
56
  readonly viewUrl: "view.url";
60
57
  readonly viewUrlPathGroup: "view.url_path_group";
61
58
  readonly viewVersion: "view.version";
59
+ readonly websocketPhase: "websocket.phase";
62
60
  };
63
61
  export type RumAttributeKey = (typeof RUM_ATTRIBUTES)[keyof typeof RUM_ATTRIBUTES];
@@ -1,5 +1,5 @@
1
1
  import type { Attributes } from '@opentelemetry/api';
2
- export declare const RUM_SPAN_RESULT: {
2
+ export declare const RUM_SPAN_OUTCOME: {
3
3
  readonly abort: "abort";
4
4
  readonly error: "error";
5
5
  readonly success: "success";
@@ -9,38 +9,47 @@ export declare const RUM_SPAN_RESULT: {
9
9
  export declare const RUM_SPAN_TYPE: {
10
10
  readonly action: "action";
11
11
  readonly custom: "custom";
12
- readonly document: "document";
13
12
  readonly error: "error";
14
- readonly longtask: "longtask";
13
+ readonly longTask: "long_task";
15
14
  readonly resource: "resource";
16
- readonly route: "route";
17
15
  readonly session: "session";
18
16
  readonly vital: "vital";
17
+ readonly view: "view";
19
18
  readonly websocket: "websocket";
20
19
  };
20
+ export type RumRequestOutcome = {
21
+ error?: unknown;
22
+ type: 'network_error';
23
+ } | {
24
+ error?: unknown;
25
+ type: 'timeout';
26
+ } | {
27
+ statusCode?: number;
28
+ type: 'response';
29
+ } | {
30
+ type: 'abort';
31
+ };
21
32
  export interface RumResourceSpanInput {
22
33
  initiatorType?: string;
23
34
  method?: string;
24
- networkError?: boolean;
25
- responseStatus?: number;
35
+ outcome?: RumRequestOutcome;
26
36
  transferSize?: number;
27
37
  url: string;
28
38
  }
29
39
  export interface RumSpanClassification {
30
- errorType?: string;
31
- result?: RumSpanResult;
32
- spanSubtype: string;
40
+ outcome?: RumSpanOutcome;
41
+ outcomeReason?: string;
33
42
  spanType: RumSpanType;
34
43
  }
35
- export type RumSpanResult = (typeof RUM_SPAN_RESULT)[keyof typeof RUM_SPAN_RESULT];
44
+ export type RumSpanOutcome = (typeof RUM_SPAN_OUTCOME)[keyof typeof RUM_SPAN_OUTCOME];
36
45
  export type RumSpanType = (typeof RUM_SPAN_TYPE)[keyof typeof RUM_SPAN_TYPE];
37
46
  export interface RumUrlTarget {
38
47
  serverAddress?: string;
39
48
  serverPort?: number;
40
49
  }
41
- export declare const getHttpResult: (statusCode: number | undefined) => RumSpanResult;
42
- export declare const getHttpErrorType: (statusCode: number | undefined) => "none" | "network_timeout" | "http_5xx" | "http_4xx";
43
- export declare const getVitalResult: (rating: string | undefined) => RumSpanResult;
50
+ export declare const getHttpOutcome: (statusCode: number | undefined) => RumSpanOutcome;
51
+ export declare const getHttpOutcomeReason: (statusCode: number | undefined) => "network_timeout" | "http_5xx" | "http_4xx" | undefined;
52
+ export declare const getVitalOutcome: (rating: string | undefined) => RumSpanOutcome;
44
53
  export declare const getUrlTarget: (url: string | undefined) => RumUrlTarget;
45
- export declare const buildRumSpanAttributes: ({ errorType, result, spanSubtype, spanType, }: RumSpanClassification) => Attributes;
46
- export declare const buildRumResourceSpanAttributes: ({ initiatorType, method, networkError, responseStatus, transferSize, url, }: RumResourceSpanInput) => Attributes;
54
+ export declare const buildRumSpanAttributes: ({ outcome, outcomeReason, spanType, }: RumSpanClassification) => Attributes;
55
+ export declare const buildRumResourceSpanAttributes: ({ initiatorType, method, outcome, transferSize, url, }: RumResourceSpanInput) => Attributes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueking/open-telemetry",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "OpenTelemetry browser SDK for BK RUM",
5
5
  "author": "TencentCloud Real User Monitoring",
6
6
  "main": "dist/index.js",
@@ -21,24 +21,26 @@ description: 帮助业务方在前端应用里接入、使用和配置蓝鲸 RUM
21
21
 
22
22
  | 用户想做的事 | 读取 |
23
23
  | ------------------------------------------------------------------------------------------- | ------------------------------------- |
24
- | 第一次接入、安装、最小示例、CDN、生产推荐配置 | `references/getting-started.md` |
25
- | 评估 SDK 能力边界、默认开关、浏览器 API、信号产出和降级行为 | `references/capabilities.md` |
26
- | 理解源码模块、初始化顺序、运行时上下文、过滤链路和 Hook 时机 | `references/architecture.md` |
27
- | 搞懂单一 Trace 信号、Instrumentation vs Plugin、采样、数据归一、运行时上下文 | `references/concepts.md` |
28
- | 查配置项、默认值、Endpoint、插件参数和 Hook | `references/configuration.md` |
29
- | 查 Transport、批量上报、Session 采样和 traceparent 透传 | `references/transport-sampling.md` |
30
- | 了解插件默认组合、启用规则和能力分类 | `references/plugins.md` |
31
- | 配置 Session、Device、View、Action | `references/plugins-basic.md` |
32
- | 配置 Resource、Web Vitals、Blank Screen、Long Task、View Loading Time | `references/plugins-experience.md` |
33
- | 配置 Error、CSP Violation 和错误上报 | `references/plugins-error-security.md` |
34
- | 配置 Fetch/XHR Request、Trace Header、WebSocket | `references/plugins-network.md` |
35
- | 写自定义插件、接入第三方 OpenTelemetry instrumentation | `references/custom-plugin.md` |
36
- | 查公开 API(start/flush/shutdown/setUser/setView/reportAction/reportCustomEvent 等) | `references/api.md` |
37
- | Vue / React / Vue Router / 微前端 集成 | `references/framework-integration.md` |
38
- | URL 脱敏、属性脱敏、公共属性、低基数路由、user.id 处理 | `references/privacy.md` |
39
- | 了解上报字段、span_type/result、哪些字段是后端派生 | `references/data-model.md` |
40
- | 查具体的 Span 名、事件字段和完整属性字典 | `references/telemetry-reference.md` |
41
- | 本地看不到数据、手动事件没上报、白屏误报、接口 span 太多等排障 | `references/troubleshooting.md` |
24
+ | 第一次接入、安装、最小示例、CDN、第一次数据验证 | `references/getting-started.md` |
25
+ | 生产上线、采样容量、Collector/CORS、灰度与验收 | `references/production.md` |
26
+ | 评估 SDK 能力边界、默认开关、浏览器 API、信号产出和降级行为 | `references/capabilities.md` |
27
+ | 理解源码模块、初始化顺序、运行时上下文、过滤链路和 Hook 时机 | `references/architecture.md` |
28
+ | 理解 OTLP 层级、Session/View/Action 关联、字段归属和服务端派生 | `references/data-model.md` |
29
+ | 配置 Session、用户、Device、持久化和跨 Tab | `references/session-context.md` |
30
+ | 配置自动/手动 View、Router、BFCache 和 View Loading Time | `references/views-routing.md` |
31
+ | 配置 Fetch/XHR、Resource Timing、Trace Header 和 WebSocket | `references/network.md` |
32
+ | 配置自动 Action、手动 Action、命名和 Rage/Dead/Error Click | `references/actions.md` |
33
+ | 配置 Web Vitals、Long Task 及其浏览器降级 | `references/performance.md` |
34
+ | 配置 JS/Promise/资源错误、exception 和 CSP Violation | `references/errors-security.md` |
35
+ | 配置白屏根节点、阈值、忽略元素和处理误报 | `references/blank-screen.md` |
36
+ | 写自定义 BkOTPlugin、接入第三方 OpenTelemetry Instrumentation | `references/extensions.md` |
37
+ | 查全部配置项、默认值、Endpoint、插件参数和 Hook | `references/configuration.md` |
38
+ | 查公开 API(start/flush/shutdown/setUser/startView/reportAction/reportCustomEvent 等) | `references/api.md` |
39
+ | Vue / React / Router / SSR / 微前端集成 | `references/framework-integration.md` |
40
+ | URL/属性脱敏、Consent、低基数路由、user.id 和服务端隐私责任 | `references/privacy.md` |
41
+ | 查 Transport、OTLP JSON、批量队列、重试、keepalive、Session 采样和 CORS | `references/transport-sampling.md` |
42
+ | 查具体 Span 名、OTLP Envelope、Resource/Span/Event 完整字段字典 | `references/telemetry-reference.md` |
43
+ | 没有数据、手动事件没上报、白屏误报、接口 Span 太多、字段缺失等排障 | `references/troubleshooting.md` |
42
44
 
43
45
  > `references/` 由 `packages/open-telemetry/scripts/gen-skill-references.mjs` 从 SDK 的 `wikis/` 自动生成,请勿手改。如内容过期,让维护者重新执行 `pnpm --filter @blueking/open-telemetry skill:refs`。
44
46
 
@@ -65,7 +67,7 @@ SDK 维护公共上下文并自动挂到后续 Span 上:`user.id`(业务方
65
67
 
66
68
  ### 数据归一
67
69
 
68
- SDK 为 span 补充归一字段便于统一检索:`span_type`(document/resource/vital/error/longtask/action/route/custom)、`span_subtype`、`result`(success/warning/error/timeout/abort)、`error_type`。Fetch/XHR 与静态资源统一为 resource,通过 `resource.type` 区分。
70
+ SDK 为 Span 补充归一字段便于统一检索:`span_type`(session/view/resource/vital/error/long_task/action/websocket/custom)、`outcome.type`(success/warning/error/timeout/abort)和可选 `outcome.reason`。具体子类由 `resource.type`、`vital.metric`、`error.source` 等领域字段表达;Fetch/XHR 与静态资源统一为 resource,通过 `resource.type` 区分。
69
71
 
70
72
  ## 最小接入速查
71
73
 
@@ -93,7 +95,7 @@ CDN:
93
95
  </script>
94
96
  ```
95
97
 
96
- `transport.endpoint` 是必填上报根地址(不含路径前缀),SDK 自动拼 `/v1/rum`。SDK 不创建 Metric/Log Provider,所有原始 RUM 事件统一走 Trace Span。`token` 作为 `Authorization: Bearer <token>` 默认头。构造后默认 `autoStart: true` 自动启动,无需手动 `start()`。
98
+ `transport.endpoint` 是必填上报根地址,可以包含网关前缀,但不要包含最终 `/v1/rum`;SDK 去除末尾斜杠后自动追加 `/v1/rum`。SDK 不创建 Metric/Log Provider,所有原始 RUM 事件统一走 Trace Span。`token` 作为 `Authorization: Bearer <token>` 默认头。构造后默认 `autoStart: true` 异步启动;如果要确保首个手动事件不丢,应改用 `autoStart: false` 并显式 `await start()`。
97
99
 
98
100
  ## 默认采集能力清单
99
101
 
@@ -101,15 +103,16 @@ CDN:
101
103
 
102
104
  - 基础能力:Session、View;内置采集:`request`、`action`、`resource`、`error`、`webVitals`、`blankScreen`、`device`
103
105
 
104
- View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`cspViolation`、`websocket`。关闭默认能力时显式设为 `false`。各插件参数按「任务路由」读取对应 `plugins-*.md`。
106
+ View Loading Time 默认开启;默认关闭、按需打开:`longTask`、`cspViolation`、`websocket`。关闭默认能力时显式设为 `false`。各能力参数按「任务路由」读取对应主题 reference。
105
107
 
106
108
  ## 关键易错点
107
109
 
108
110
  - **单实例**:`fetch`/`xhr`/`action`/`websocket` 会 patch 或监听全局 API,同页面只应初始化一个 SDK 实例,微前端只在主应用初始化一次。
109
111
  - **`use()` / `useInstrumentation()` 必须在 `start()` 之前**:要注册自定义插件或 instrumentation,请设 `autoStart: false` 再手动 `start()`。
110
112
  - **采样影响手动上报**:未命中采样时 `reportAction()` / `reportCustomEvent()` 静默丢弃,排查时先确认采样。
111
- - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;SDK 不采集 HTTP Body;`user.id` 需 hash 的话要在传入前处理。
112
- - **Consent**:未授权初始化时配置 `privacy.trackingConsent: 'not-granted'`,用户授权后调用 `setTrackingConsent('granted')`;撤销授权会停止采集并解除 patch。
113
+ - **手动事件不排队**:异步 autoStart 尚未建立 View 时立即调用的手动事件可能被过滤;确定性时序使用 `autoStart: false`、`await start()`,manual View 再先调用 `startView()`。
114
+ - **隐私要业务显式配置**:SDK 不猜哪些字段敏感,URL、属性需通过 `privacy` / `request.beforeSend` 显式处理;SDK 不采集 HTTP Body;`user.id` 需 hash 的话要在传入前处理。`tracking.beforeSend` 新写入的字段不会再次自动经过 `redactAttributes`。
115
+ - **Consent**:未授权初始化时配置 `privacy.trackingConsent: 'not-granted'`,用户授权后调用 `setTrackingConsent('granted')`;撤销授权会停止采集并解除 patch。该配置不会阻止构造阶段读取 Device Resource 快照;要求授权前零读取时必须延迟构造 SDK。
113
116
  - **单一信号**:只有 `/v1/rum` Trace 通道;计数、直方图、分位数、错误指纹和跨事件聚合由服务端完成。
114
117
  - **低基数路由**:用 `tracking.view.getPathGroup` 把 `/user/123` 归类成 `/user/:id`,避免高基数 URL 污染指标维度。
115
118
  - **手动 View 的时机**:使用 `autoStart: false`,先 `await start()` 建立 Session,再调用 `startView()`;启动前调用会因没有有效采样 Session 而被忽略。
@@ -0,0 +1,166 @@
1
+ <!-- 本文件由 packages/open-telemetry/scripts/gen-skill-references.mjs 从 wikis 自动生成,请勿手改。 -->
2
+
3
+ # 用户 Action 与挫败信号
4
+
5
+ Action 表示一次用户操作以及操作后引发的页面活动。SDK 默认自动监听 click,也提供 `reportAction()` 上报业务命名动作。自动 Action 才计算 Loading Time、页面活动和挫败信号。
6
+
7
+ ## 自动 Action 生命周期
8
+
9
+ 一次 click 的处理过程:
10
+
11
+ 1. 从 Event 取得真实发生时间和 composed target。
12
+ 2. 生成 `action.id`,保存当时的 Session/View 上下文。
13
+ 3. 把活动中的 Action ID 写入运行时上下文,后续请求、资源、错误和 Long Task 自动关联。
14
+ 4. 观察请求、DOM Mutation、Resource、Long Task、Error 和部分用户行为。
15
+ 5. 发生过页面活动后,等待所有请求完成并连续 100ms 无活动。
16
+ 6. 最长等待 `maxDuration`,默认 10 秒。
17
+ 7. 从运行时上下文移除 Action ID。
18
+ 8. 最多再等待到 click 后 1 秒完成 Rage Click 判断。
19
+ 9. 创建并结束 `action.click` Span。
20
+
21
+ 上报等待期不会延长 Action 关联窗口;后续无关事件不会因为等待 Rage Click 判断而关联旧 Action。
22
+
23
+ ## Action 活动
24
+
25
+ 会影响 Loading Time 的活动:
26
+
27
+ - Fetch/XHR 开始和结束;
28
+ - 静态资源完成;
29
+ - DOM Mutation;
30
+ - Long Task;
31
+ - Error;
32
+ - `window.open`。
33
+
34
+ Error 会把 Action 标记为发生过活动、更新结束时间并标记 `error_click`;Long Task 也只影响 Action Activity。View Loading Time 的稳定判断会忽略 Error 和 Long Task。`view.excludedActivityUrls` 命中的请求/资源不参与 Action 活动。
35
+
36
+ 点击后 100ms 内没有任何页面活动时,Action 以零持续时间结束且没有 `action.loading_time`;它仍可能被识别为 Dead Click。
37
+
38
+ ## 自动命名
39
+
40
+ 默认配置:
41
+
42
+ ```ts
43
+ tracking: {
44
+ action: {
45
+ actionNameAttribute: 'data-bk-action-name',
46
+ maxDuration: 10_000,
47
+ nameCollection: 'explicit',
48
+ },
49
+ }
50
+ ```
51
+
52
+ `explicit` 模式从目标元素向上查找指定属性;找不到时只使用目标标签名。推荐:
53
+
54
+ ```html
55
+ <button data-bk-action-name="提交订单">提交</button>
56
+ ```
57
+
58
+ 遥测中的名称为 `Click on 提交订单`,同时写入:
59
+
60
+ - `action.target.name=提交订单`
61
+ - `action.target.tag=button`
62
+
63
+ 名称会合并连续空白、截断到 100 字符。
64
+
65
+ ## 文本命名模式
66
+
67
+ `nameCollection='text'` 才会继续读取:
68
+
69
+ 1. 关联 label;
70
+ 2. button/reset/submit input value;
71
+ 3. button、label、`role=button` 文本;
72
+ 4. `aria-label`、`alt`、`name`、`title`、`placeholder`;
73
+ 5. DOM textContent;
74
+ 6. 从目标开始,最多继续检查 10 层父级;遇到 form/body/html/head 停止。
75
+
76
+ 该模式可能采集用户输入、订单内容或个人信息。生产环境优先使用 `explicit`,只有完成隐私评估后才启用文本模式。
77
+
78
+ ## Rage Click
79
+
80
+ 满足以下条件时标记 `rage_click`:
81
+
82
+ - 1 秒内至少三次 click;
83
+ - 点击目标是同一个 DOM Element;
84
+ - 相邻点击坐标距离不超过 100px;
85
+ - 期间没有 scroll 或 selectionchange 中断点击链。
86
+
87
+ 前三次点击仍各自保留独立 Action Span,并带 Rage Click 语义,不合并成一条事件。
88
+
89
+ ## Dead Click
90
+
91
+ 点击后没有页面活动,且没有 input、scroll 或文本选择时,候选为 `dead_click`。以下目标因行为难以可靠判断而排除:
92
+
93
+ - 带 href 的链接;
94
+ - `select`、`textarea`、`canvas`;
95
+ - `contenteditable`;
96
+ - 文本类 input;
97
+ - 指向以上控件的 label。
98
+
99
+ button、checkbox、radio、range、reset、submit input 仍可判断。
100
+
101
+ ## Error Click
102
+
103
+ Action 活动窗口内发生由 Activity Bus 通知的前端错误时,标记 `error_click`。Error 不要求是 Action Span 的子 Span,只要事件时间落在活动窗口并带同一 `action.id` 即可在服务端关联。
104
+
105
+ ## Outcome 与字段
106
+
107
+ 自动 Action Span:
108
+
109
+ | 条件 | `outcome.type` | 具体语义 |
110
+ | --- | --- | --- |
111
+ | 无错误、无挫败 | `success` | 无 |
112
+ | 有前端错误 | `warning` | `action.frustration.type=error_click` |
113
+ | 只有 Rage/Dead Click | `warning` | `action.frustration.type` 对应值 |
114
+
115
+ 关键字段:
116
+
117
+ - `action.id`
118
+ - `action.type=click`
119
+ - `action.name`
120
+ - `action.target.name`
121
+ - `action.target.tag`
122
+ - `action.loading_time`,只有观察到页面活动时存在,单位 ms
123
+ - `action.frustration.type`,按 `rage_click`、`dead_click`、`error_click` 固定顺序的数组
124
+
125
+ SDK 不在 Action Span 中写请求数、资源数、错误数或 Long Task 数;服务端通过 `action.id` 关联原始事件后派生。
126
+
127
+ ## 手动 Action
128
+
129
+ ```ts
130
+ bkOT.reportAction({
131
+ name: '立即支付',
132
+ attributes: {
133
+ 'biz.order_type': 'normal',
134
+ },
135
+ });
136
+ ```
137
+
138
+ 它立即创建并结束 `action.custom`:
139
+
140
+ - 新生成独立 `action.id`;
141
+ - `action.type=custom`;
142
+ - `action.name` 使用传入名称;
143
+ - `span_type=action`、`outcome.type=success`;
144
+ - 不建立活动窗口;
145
+ - 不计算 Loading Time 或挫败信号;
146
+ - 不把该 ID挂到后续请求/错误。
147
+
148
+ 未采样、未授权或没有有效 View 时不会导出。`reportAction()` 未采样时静默返回。
149
+
150
+ ## Flush 与页面退出
151
+
152
+ 页面隐藏、pagehide、Session 过期、插件 flush 或 shutdown 时,SDK会结束仍活动的 Action,并立即落数等待中的 Rage Click Action,避免正常生命周期中积压。
153
+
154
+ ## 常见问题
155
+
156
+ ### Action 名称只有标签名
157
+
158
+ 这是默认隐私行为。为元素或祖先添加 `data-bk-action-name`,或显式配置其他 `actionNameAttribute`。
159
+
160
+ ### 点击有请求但没有 Loading Time
161
+
162
+ 检查请求是否命中 `view.excludedActivityUrls`,click 是否在请求开始前被其他监听逻辑延迟,以及 Action 是否在未采样/无 View 状态发生。
163
+
164
+ ### Dead Click 过多
165
+
166
+ 确认自定义控件是否由普通 `div` 实现但实际承担输入/跳转行为;可让点击产生可观察活动、改用语义化元素,或关闭自动 Action 并使用手动上报。当前配置没有单独关闭某一种挫败信号的选项。