@arms/rum-reactnative 0.1.1 → 0.1.3-beta.0

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 (178) hide show
  1. package/README.md +399 -15
  2. package/RumSdkReactnative.podspec +28 -0
  3. package/android/build.gradle +83 -0
  4. package/android/gradle.properties +6 -0
  5. package/android/src/main/AndroidManifest.xml +13 -0
  6. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativeModule.kt +512 -0
  7. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativePackage.kt +33 -0
  8. package/android/src/main/java/com/rumsdkreactnative/crash/CrashContextManager.kt +157 -0
  9. package/android/src/main/java/com/rumsdkreactnative/crash/CrashHandler.kt +444 -0
  10. package/android/src/main/java/com/rumsdkreactnative/crash/CrashInitProvider.kt +50 -0
  11. package/android/src/main/java/com/rumsdkreactnative/crash/NdkCrashHandler.kt +66 -0
  12. package/android/src/main/jni/CMakeLists.txt +21 -0
  13. package/android/src/main/jni/rum_backtrace.c +144 -0
  14. package/android/src/main/jni/rum_crash_handler.c +200 -0
  15. package/android/src/main/jni/rum_crash_writer.c +442 -0
  16. package/android/src/main/jni/rum_module_info.c +316 -0
  17. package/android/src/main/jni/rum_module_info.h +54 -0
  18. package/android/src/main/jni/rum_test_crash.cpp +55 -0
  19. package/app.plugin.js +11 -0
  20. package/docs/ReactNative SDK/351/205/215/347/275/256/345/217/202/350/200/203.md" +671 -0
  21. package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +12 -0
  22. package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +238 -0
  23. package/ios/PrivacyInfo.xcprivacy +93 -0
  24. package/ios/RumCrashReporter.h +38 -0
  25. package/ios/RumCrashReporter.mm +861 -0
  26. package/ios/RumSdkReactnative.h +5 -0
  27. package/ios/RumSdkReactnative.mm +291 -0
  28. package/ios/fishhook/fishhook.c +264 -0
  29. package/ios/fishhook/fishhook.h +76 -0
  30. package/lib/commonjs/NativeRumSdkReactnative.js +50 -0
  31. package/lib/commonjs/collector/action/index.js +108 -0
  32. package/lib/commonjs/collector/exception/crash.js +148 -0
  33. package/lib/commonjs/collector/exception/index.js +238 -0
  34. package/lib/commonjs/collector/index.js +42 -0
  35. package/lib/commonjs/collector/resource/api.js +286 -0
  36. package/lib/commonjs/collector/view/perf.js +79 -0
  37. package/lib/commonjs/collector/view/pv.js +88 -0
  38. package/lib/commonjs/expoConfigPlugin.js +37 -0
  39. package/lib/commonjs/index.js +29 -0
  40. package/lib/commonjs/package.json +1 -0
  41. package/lib/commonjs/plugin.js +47 -0
  42. package/lib/commonjs/processor/default-processor.js +27 -0
  43. package/lib/commonjs/processor/session-processor.js +47 -0
  44. package/lib/commonjs/reporter/index.js +148 -0
  45. package/lib/commonjs/reporter/monitor-reporter.js +43 -0
  46. package/lib/commonjs/shell.js +91 -0
  47. package/lib/commonjs/types/client.js +6 -0
  48. package/lib/commonjs/types/crash.js +37 -0
  49. package/lib/commonjs/types/index.js +2 -0
  50. package/lib/commonjs/utils/action.js +305 -0
  51. package/lib/commonjs/utils/api.js +83 -0
  52. package/lib/commonjs/utils/base.js +95 -0
  53. package/lib/commonjs/utils/crash.js +146 -0
  54. package/lib/commonjs/utils/platform.js +162 -0
  55. package/lib/commonjs/utils/session.js +158 -0
  56. package/lib/commonjs/utils/url.js +59 -0
  57. package/lib/commonjs/utils/view.js +93 -0
  58. package/lib/module/NativeRumSdkReactnative.js +47 -0
  59. package/lib/module/collector/action/index.js +45 -10
  60. package/lib/module/collector/exception/crash.js +143 -0
  61. package/lib/module/collector/exception/index.js +144 -46
  62. package/lib/module/collector/index.js +8 -0
  63. package/lib/module/collector/resource/api.js +6 -6
  64. package/lib/module/collector/view/pv.js +13 -2
  65. package/lib/module/expoConfigPlugin.js +33 -0
  66. package/lib/module/index.js +1 -0
  67. package/lib/module/plugin.js +4 -1
  68. package/lib/module/processor/session-processor.js +22 -0
  69. package/lib/module/reporter/index.js +102 -16
  70. package/lib/module/reporter/monitor-reporter.js +38 -0
  71. package/lib/module/shell.js +32 -7
  72. package/lib/module/types/crash.js +33 -0
  73. package/lib/module/utils/action.js +299 -0
  74. package/lib/module/utils/api.js +10 -10
  75. package/lib/module/utils/base.js +9 -9
  76. package/lib/module/utils/crash.js +141 -0
  77. package/lib/module/utils/platform.js +127 -72
  78. package/lib/module/utils/session.js +23 -4
  79. package/lib/module/utils/view.js +2 -1
  80. package/lib/typescript/commonjs/package.json +1 -0
  81. package/lib/typescript/commonjs/src/NativeRumSdkReactnative.d.ts +49 -0
  82. package/lib/typescript/{src → commonjs/src}/collector/action/index.d.ts +7 -1
  83. package/lib/typescript/commonjs/src/collector/exception/crash.d.ts +28 -0
  84. package/lib/typescript/{src → commonjs/src}/collector/exception/index.d.ts +7 -0
  85. package/lib/typescript/commonjs/src/collector/index.d.ts +6 -0
  86. package/lib/typescript/{src → commonjs/src}/collector/view/pv.d.ts +2 -2
  87. package/lib/typescript/commonjs/src/expoConfigPlugin.d.ts +28 -0
  88. package/lib/typescript/commonjs/src/index.d.ts +6 -0
  89. package/lib/typescript/{src → commonjs/src}/processor/session-processor.d.ts +2 -0
  90. package/lib/typescript/{src → commonjs/src}/reporter/index.d.ts +3 -1
  91. package/lib/typescript/commonjs/src/reporter/monitor-reporter.d.ts +8 -0
  92. package/lib/typescript/commonjs/src/shell.d.ts +57 -0
  93. package/lib/typescript/{src → commonjs/src}/types/client.d.ts +2 -2
  94. package/lib/typescript/commonjs/src/types/crash.d.ts +95 -0
  95. package/lib/typescript/commonjs/src/utils/action.d.ts +63 -0
  96. package/lib/typescript/{src → commonjs/src}/utils/api.d.ts +1 -1
  97. package/lib/typescript/commonjs/src/utils/crash.d.ts +12 -0
  98. package/lib/typescript/commonjs/src/utils/platform.d.ts +22 -0
  99. package/lib/typescript/{src → commonjs/src}/utils/session.d.ts +4 -0
  100. package/lib/typescript/module/src/NativeRumSdkReactnative.d.ts +49 -0
  101. package/lib/typescript/module/src/collector/action/index.d.ts +21 -0
  102. package/lib/typescript/module/src/collector/exception/crash.d.ts +28 -0
  103. package/lib/typescript/module/src/collector/exception/index.d.ts +32 -0
  104. package/lib/typescript/module/src/collector/index.d.ts +6 -0
  105. package/lib/typescript/module/src/collector/resource/api.d.ts +21 -0
  106. package/lib/typescript/module/src/collector/view/perf.d.ts +1 -0
  107. package/lib/typescript/module/src/collector/view/pv.d.ts +16 -0
  108. package/lib/typescript/module/src/expoConfigPlugin.d.ts +28 -0
  109. package/lib/typescript/module/src/index.d.ts +6 -0
  110. package/lib/typescript/module/src/plugin.d.ts +3 -0
  111. package/lib/typescript/module/src/processor/default-processor.d.ts +6 -0
  112. package/lib/typescript/module/src/processor/session-processor.d.ts +11 -0
  113. package/lib/typescript/module/src/reporter/index.d.ts +18 -0
  114. package/lib/typescript/module/src/reporter/monitor-reporter.d.ts +8 -0
  115. package/lib/typescript/module/src/shell.d.ts +57 -0
  116. package/lib/typescript/module/src/types/client.d.ts +27 -0
  117. package/lib/typescript/module/src/types/crash.d.ts +95 -0
  118. package/lib/typescript/module/src/types/index.d.ts +118 -0
  119. package/lib/typescript/module/src/utils/action.d.ts +63 -0
  120. package/lib/typescript/module/src/utils/api.d.ts +59 -0
  121. package/lib/typescript/module/src/utils/base.d.ts +8 -0
  122. package/lib/typescript/module/src/utils/crash.d.ts +12 -0
  123. package/lib/typescript/module/src/utils/platform.d.ts +22 -0
  124. package/lib/typescript/module/src/utils/session.d.ts +41 -0
  125. package/lib/typescript/module/src/utils/url.d.ts +17 -0
  126. package/lib/typescript/module/src/utils/view.d.ts +13 -0
  127. package/package.json +61 -26
  128. package/LICENSE +0 -20
  129. package/lib/module/collector/action/index.js.map +0 -1
  130. package/lib/module/collector/exception/index.js.map +0 -1
  131. package/lib/module/collector/resource/api.js.map +0 -1
  132. package/lib/module/collector/view/perf.js.map +0 -1
  133. package/lib/module/collector/view/pv.js.map +0 -1
  134. package/lib/module/index.js.map +0 -1
  135. package/lib/module/plugin.js.map +0 -1
  136. package/lib/module/processor/default-processor.js.map +0 -1
  137. package/lib/module/processor/session-processor.js.map +0 -1
  138. package/lib/module/reporter/index.js.map +0 -1
  139. package/lib/module/shell.js.map +0 -1
  140. package/lib/module/types/client.js.map +0 -1
  141. package/lib/module/types/index.js.map +0 -1
  142. package/lib/module/utils/api.js.map +0 -1
  143. package/lib/module/utils/base.js.map +0 -1
  144. package/lib/module/utils/platform.js.map +0 -1
  145. package/lib/module/utils/session.js.map +0 -1
  146. package/lib/module/utils/url.js.map +0 -1
  147. package/lib/module/utils/view.js.map +0 -1
  148. package/lib/typescript/src/collector/action/index.d.ts.map +0 -1
  149. package/lib/typescript/src/collector/exception/index.d.ts.map +0 -1
  150. package/lib/typescript/src/collector/resource/api.d.ts.map +0 -1
  151. package/lib/typescript/src/collector/view/perf.d.ts.map +0 -1
  152. package/lib/typescript/src/collector/view/pv.d.ts.map +0 -1
  153. package/lib/typescript/src/index.d.ts +0 -4
  154. package/lib/typescript/src/index.d.ts.map +0 -1
  155. package/lib/typescript/src/plugin.d.ts.map +0 -1
  156. package/lib/typescript/src/processor/default-processor.d.ts.map +0 -1
  157. package/lib/typescript/src/processor/session-processor.d.ts.map +0 -1
  158. package/lib/typescript/src/reporter/index.d.ts.map +0 -1
  159. package/lib/typescript/src/shell.d.ts +0 -26
  160. package/lib/typescript/src/shell.d.ts.map +0 -1
  161. package/lib/typescript/src/types/client.d.ts.map +0 -1
  162. package/lib/typescript/src/types/index.d.ts.map +0 -1
  163. package/lib/typescript/src/utils/api.d.ts.map +0 -1
  164. package/lib/typescript/src/utils/base.d.ts.map +0 -1
  165. package/lib/typescript/src/utils/platform.d.ts +0 -15
  166. package/lib/typescript/src/utils/platform.d.ts.map +0 -1
  167. package/lib/typescript/src/utils/session.d.ts.map +0 -1
  168. package/lib/typescript/src/utils/url.d.ts.map +0 -1
  169. package/lib/typescript/src/utils/view.d.ts.map +0 -1
  170. /package/lib/typescript/{src → commonjs/src}/collector/resource/api.d.ts +0 -0
  171. /package/lib/typescript/{src → commonjs/src}/collector/view/perf.d.ts +0 -0
  172. /package/lib/typescript/{src → commonjs/src}/plugin.d.ts +0 -0
  173. /package/lib/typescript/{src → commonjs/src}/processor/default-processor.d.ts +0 -0
  174. /package/lib/typescript/{src → commonjs/src}/types/index.d.ts +0 -0
  175. /package/lib/typescript/{src → commonjs/src}/utils/base.d.ts +0 -0
  176. /package/lib/typescript/{src → commonjs/src}/utils/url.d.ts +0 -0
  177. /package/lib/typescript/{src → commonjs/src}/utils/view.d.ts +0 -0
  178. /package/lib/typescript/{package.json → module/package.json} +0 -0
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _rumCore = require("@arms/rum-core");
8
+ var _view = require("../../utils/view");
9
+ var _action = require("../../utils/action");
10
+ class ActionCollector {
11
+ name = 'action-collector';
12
+ DELAY_TIME = 300;
13
+ events = ['tap'];
14
+ setup(ctx, sendEvent) {
15
+ const {
16
+ collectors = {}
17
+ } = ctx.getConfig();
18
+ if (collectors.action === false) {
19
+ return;
20
+ }
21
+ this.ctx = ctx;
22
+ this.sendEvent = sendEvent;
23
+ // 开启 React Native 触摸自动采集,并监听标准化的 tap 事件
24
+ (0, _action.startTrackingActions)();
25
+ (0, _action.addActionListener)(this.onEvent);
26
+ }
27
+ onEvent = e => {
28
+ if (e && this.events.includes(e.type) && e.target) {
29
+ const {
30
+ target,
31
+ currentTarget,
32
+ type
33
+ } = e;
34
+ const {
35
+ dataset,
36
+ id
37
+ } = target;
38
+ if (!id) return;
39
+ if (currentTarget && id !== currentTarget.id) return;
40
+ let view;
41
+ if (this.ctx) {
42
+ view = (0, _view.getCurView)(this.ctx);
43
+ }
44
+ const event = {
45
+ event_type: _rumCore.RumEventType.ACTION,
46
+ type,
47
+ name: e.name || id,
48
+ target_name: e.targetName,
49
+ duration: e.duration,
50
+ position: e.position,
51
+ target: this.buildTarget(target),
52
+ snapshots: dataset && Object.keys(dataset).length ? JSON.stringify(dataset).slice(0, 1000) : undefined,
53
+ times: 1,
54
+ view
55
+ };
56
+ clearTimeout(this.timer);
57
+ if (this.lastEvent && this.lastActionId === id) {
58
+ // 同一元素的连续点击:仅累加次数
59
+ // @ts-ignore
60
+ this.lastEvent.times += 1;
61
+ } else {
62
+ // 切换到不同元素:立即上报上一个,再记录新事件
63
+ if (this.lastEvent) {
64
+ this.sendAction();
65
+ }
66
+ this.lastEvent = event;
67
+ this.lastActionId = id;
68
+ }
69
+ this.timer = setTimeout(this.sendAction, this.DELAY_TIME);
70
+ }
71
+ };
72
+
73
+ /**
74
+ * 组装热力图相关的 target 信息(selector/宽高/可交互性/可信度)。
75
+ * 当没有任何字段时返回 undefined,避免上报空对象。
76
+ */
77
+ buildTarget(target) {
78
+ const {
79
+ selector,
80
+ width,
81
+ height,
82
+ reaction,
83
+ trust
84
+ } = target;
85
+ if (selector === undefined && width === undefined && height === undefined && reaction === undefined && trust === undefined) {
86
+ return undefined;
87
+ }
88
+ return {
89
+ selector,
90
+ width,
91
+ height,
92
+ reaction,
93
+ trust
94
+ };
95
+ }
96
+ sendAction = () => {
97
+ // @ts-ignore
98
+ this.sendEvent(this.lastEvent);
99
+ this.lastEvent = undefined;
100
+ this.lastActionId = undefined;
101
+ };
102
+ destroy() {
103
+ (0, _action.removeActionListener)(this.onEvent);
104
+ (0, _action.stopTrackingActions)();
105
+ }
106
+ }
107
+ exports.default = ActionCollector;
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _rumCore = require("@arms/rum-core");
8
+ var _NativeRumSdkReactnative = _interopRequireDefault(require("../../NativeRumSdkReactnative"));
9
+ var _crash = require("../../types/crash");
10
+ var _crash2 = require("../../utils/crash");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ /**
13
+ * 崩溃采集器(Exception 的子类型):
14
+ * 1. 初始化时读取上次运行写入的原生崩溃文件,转换为 RumEvent 通过标准管线上报;
15
+ * 2. 通过 ctx.emitter 订阅上下文变更事件,同步到原生侧
16
+ * (用于下一次启动时崩溃报告携带正确上下文)。
17
+ */
18
+
19
+ class CrashCollector {
20
+ name = 'crash-collector';
21
+ initialized = false;
22
+ /** 已上报待确认(ack)的 crash_id,成功后才删文件 */
23
+ pendingAckIds = new Set();
24
+ setup(ctx, sendEvent) {
25
+ const {
26
+ collectors = {}
27
+ } = ctx.getConfig();
28
+ if (collectors.crash === false) {
29
+ return;
30
+ }
31
+ this.ctx = ctx;
32
+ this.sendEvent = sendEvent;
33
+
34
+ // 订阅上下文变更事件,同步到原生侧
35
+ ctx.emitter.on(_crash.CRASH_CONTEXT_EVENT, this.onCrashContextChange);
36
+ // 订阅上报确认事件:reporter 上报成功后回 ack,再删除对应崩溃文件
37
+ ctx.emitter.on(_crash.CRASH_REPORT_ACK_EVENT, this.onCrashReportAck);
38
+
39
+ // 顺序执行:先处理待上报崩溃,再清理旧文件(避免竞态)
40
+ this.processPendingCrashes().then(() => this.cleanupOldCrashes()).catch(e => {
41
+ _rumCore.logger.error('crash-collector', 'Failed to process crash reports', e);
42
+ });
43
+ }
44
+ async processPendingCrashes() {
45
+ if (this.initialized) return;
46
+ this.initialized = true;
47
+
48
+ // 不以 crashedLastRun 作为 gating:KSCrash 的 crashedLastLaunch 只在崩溃后的下一次
49
+ // 启动为 true,再下一次正常启动就清零,会导致遗留崩溃文件永远不被处理。
50
+ // 只要磁盘上有 pending 文件就读取并上报。
51
+ await (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.crashedLastRun(), 'crashedLastRun');
52
+ const crashesJson = await (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.getPendingCrashes(), 'getPendingCrashes');
53
+ if (!crashesJson) return;
54
+ let crashes = [];
55
+ try {
56
+ crashes = JSON.parse(crashesJson) || [];
57
+ } catch (e) {
58
+ _rumCore.logger.error('crash-collector', 'Failed to parse crashes JSON', e);
59
+ // 清理损坏的文件,避免每次启动重复尝试解析
60
+ await (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.clearAllCrashReports(), 'clearAllCrashReports');
61
+ return;
62
+ }
63
+ if (!Array.isArray(crashes) || crashes.length === 0) return;
64
+ const crashIds = [];
65
+ const hasFilesWithoutId = crashes.some(c => !c.crash_id);
66
+ for (let i = 0; i < crashes.length; i++) {
67
+ try {
68
+ const event = (0, _crash2.convertCrashToRumEvent)(crashes[i]);
69
+ const cid = crashes[i].crash_id;
70
+ // 将瞬态 crash_id 注入 snapshots(而非根级),reporter 上报前从中提取
71
+ // 用于 ack,并在序列化前从 snapshots 中剥离,不会发送到后端
72
+ if (cid) {
73
+ try {
74
+ const snapshotsObj = JSON.parse(event.snapshots);
75
+ snapshotsObj[_crash.CRASH_ID_FIELD] = cid;
76
+ event.snapshots = JSON.stringify(snapshotsObj);
77
+ } catch {
78
+ // snapshots 解析失败时降级:仍挂载到根级以保证 ack 机制可用
79
+ event[_crash.CRASH_ID_FIELD] = cid;
80
+ }
81
+ this.pendingAckIds.add(cid);
82
+ crashIds.push(cid);
83
+ }
84
+ // 最后一个崩溃事件使用 immediate 立即 flush 整个队列
85
+ const isLast = i === crashes.length - 1;
86
+ this.sendEvent?.(event, isLast ? {
87
+ immediate: true
88
+ } : undefined);
89
+ } catch (e) {
90
+ _rumCore.logger.warn('crash-collector', 'Failed to convert crash', e);
91
+ }
92
+ }
93
+
94
+ // 有 crash_id 的文件:不在此处删除,等 reporter 上报成功后由 onCrashReportAck
95
+ // 删除;上报失败则保留,下次启动重试(cleanupOldCrashes 兜底防止无限增长)。
96
+
97
+ // 无 crash_id 的旧版 NDK 崩溃文件无法 ack:仅当本次没有待 ack 的带 id 文件时
98
+ // 才安全清理(clearAllCrashReports 会删除全部文件,避免误删 ack-pending)。
99
+ if (hasFilesWithoutId && crashIds.length === 0) {
100
+ await (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.clearAllCrashReports(), 'clearAllCrashReports');
101
+ }
102
+ }
103
+
104
+ /** 兜底清理:删除过期和超限的崩溃文件,防止存储耗尽 */
105
+ async cleanupOldCrashes() {
106
+ // 最多保留 10 个崩溃文件,7 天过期
107
+ const MAX_FILES = 10;
108
+ const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
109
+ await (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.cleanupOldCrashes(MAX_FILES, MAX_AGE_MS), 'cleanupOldCrashes');
110
+ }
111
+ onCrashContextChange = context => {
112
+ try {
113
+ _NativeRumSdkReactnative.default.updateCrashContext(JSON.stringify(context));
114
+ } catch {
115
+ //
116
+ }
117
+ };
118
+
119
+ /**
120
+ * reporter 上报确认回调:
121
+ * - 成功:删除对应 crash_id 的崩溃文件(确保上报成功后才删,不丢数据);
122
+ * - 失败:保留文件,下次启动重试,仅从内存待确认集合中移除。
123
+ */
124
+ onCrashReportAck = ack => {
125
+ if (!ack || !Array.isArray(ack.crashIds) || ack.crashIds.length === 0) {
126
+ return;
127
+ }
128
+ // 只处理本采集器登记过的 id
129
+ const toClear = ack.crashIds.filter(id => this.pendingAckIds.has(id));
130
+ if (toClear.length === 0) return;
131
+ if (!ack.success) {
132
+ // 上报失败:文件保留,从待确认集合移除(下次启动重新登记与上报)
133
+ for (const id of toClear) this.pendingAckIds.delete(id);
134
+ return;
135
+ }
136
+ (0, _crash2.safeNativeCall)(() => _NativeRumSdkReactnative.default.clearCrashReports(JSON.stringify(toClear)), 'clearCrashReports').finally(() => {
137
+ for (const id of toClear) this.pendingAckIds.delete(id);
138
+ });
139
+ };
140
+ destroy() {
141
+ this.ctx?.emitter.off(_crash.CRASH_CONTEXT_EVENT, this.onCrashContextChange);
142
+ this.ctx?.emitter.off(_crash.CRASH_REPORT_ACK_EVENT, this.onCrashReportAck);
143
+ this.pendingAckIds.clear();
144
+ this.sendEvent = undefined;
145
+ }
146
+ }
147
+ exports.default = CrashCollector;
148
+ //# sourceMappingURL=crash.js.map
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _rumCore = require("@arms/rum-core");
8
+ class ExceptionCollector {
9
+ name = 'exception-collector';
10
+ installed = false;
11
+ /** fatal 去重保护:防止连续 fatal error 重复上报 */
12
+ handlingFatal = false;
13
+ /** 防止 errorHandle 内部 console.error 形成循环 */
14
+ inErrorHandle = false;
15
+ origin = {
16
+ consoleError: console.error,
17
+ originalOnError: null,
18
+ originalOnUnhandledRejection: null
19
+ };
20
+ setup(ctx, sendEvent) {
21
+ this.ctx = ctx;
22
+ this.sendEvent = sendEvent;
23
+ this.hackOrigin();
24
+ }
25
+ hackOrigin() {
26
+ // 防止重复安装覆盖 originalOnError
27
+ if (this.installed) return;
28
+ this.installed = true;
29
+ const self = this;
30
+ const {
31
+ collectors = {}
32
+ } = this.ctx.getConfig();
33
+ if (collectors.jsError !== false) {
34
+ if (ErrorUtils) {
35
+ this.origin.originalOnError = ErrorUtils.getGlobalHandler?.();
36
+ ErrorUtils.setGlobalHandler(this.onError);
37
+ }
38
+ // Promise rejection: 优先 Hermes,JSC 兜底
39
+ if (HermesInternal?.enablePromiseRejectionTracker && HermesInternal?.hasPromise?.()) {
40
+ HermesInternal.enablePromiseRejectionTracker({
41
+ allRejections: true,
42
+ onUnhandled: this.onUnhandled
43
+ });
44
+ } else {
45
+ // JSC / 其他引擎:监听 unhandledrejection 事件
46
+ this.setupJSCPromiseRejection();
47
+ }
48
+ }
49
+ if (collectors.consoleError !== false) {
50
+ (0, _rumCore.interceptFunction)(console, 'error', function (error) {
51
+ if (self.inErrorHandle) return; // 防止循环
52
+ self.errorHandle(error, 'console.error');
53
+ });
54
+ }
55
+ }
56
+
57
+ /** JSC 引擎 Promise rejection 兜底方案 */
58
+ setupJSCPromiseRejection() {
59
+ try {
60
+ if (typeof globalThis !== 'undefined') {
61
+ const self = this;
62
+ this.origin.originalOnUnhandledRejection = globalThis.onunhandledrejection || null;
63
+ globalThis.onunhandledrejection = function (event) {
64
+ if (event?.reason) {
65
+ self.errorHandle(event.reason, 'onUnhandled');
66
+ }
67
+ if (typeof self.origin.originalOnUnhandledRejection === 'function') {
68
+ self.origin.originalOnUnhandledRejection.call(this, event);
69
+ }
70
+ };
71
+ }
72
+ } catch {
73
+ // JSC 不支持时不影响主流程
74
+ }
75
+ }
76
+ onError = (e, isFatal) => {
77
+ // fatal 去重保护:防止连续 fatal error 重复上报或死循环
78
+ if (isFatal) {
79
+ if (this.handlingFatal) return;
80
+ this.handlingFatal = true;
81
+ }
82
+
83
+ // 先采集(确保数据不丢)
84
+ this.errorHandle(e, 'onError');
85
+
86
+ // fatal error:确保事件落盘后再终止进程
87
+ if (isFatal && this.ctx) {
88
+ try {
89
+ const reporter = this.ctx.reporter;
90
+ if (reporter && typeof reporter.flush === 'function') {
91
+ // 使用超时兜底,避免永久阻塞
92
+ Promise.race([reporter.flush(), new Promise(resolve => setTimeout(resolve, 2000))]).finally(() => {
93
+ if (this.origin.originalOnError) {
94
+ this.origin.originalOnError(e, isFatal);
95
+ }
96
+ });
97
+ return;
98
+ }
99
+ } catch {
100
+ // ignore flush error
101
+ }
102
+ }
103
+
104
+ // 非 fatal 或 flush 不可用时直接链式调用
105
+ if (this.origin.originalOnError) {
106
+ this.origin.originalOnError(e, isFatal);
107
+ }
108
+ if (!isFatal) {
109
+ this.handlingFatal = false;
110
+ }
111
+ };
112
+ onUnhandled = (_id, error) => {
113
+ this.errorHandle(error, 'onUnhandled');
114
+ };
115
+ errorHandle = (error, source = '') => {
116
+ if (this.inErrorHandle) return; // 防止循环
117
+ if (error == null) return; // null/undefined 直接跳过
118
+
119
+ this.inErrorHandle = true;
120
+ try {
121
+ let name = '';
122
+ let message = '';
123
+ let file = '';
124
+ let stack = '';
125
+ let line = 0;
126
+ let column = 0;
127
+ if (error instanceof Object) {
128
+ name = String(error.name || error.constructor?.name || 'Error');
129
+ message = String(error.message || '');
130
+ file = String(error.filename || error.fileName || '');
131
+ // stack 可能在 error.stack 或 error.componentStack(React 渲染错误)
132
+ stack = String(error.stack || '');
133
+ if (!stack && error.componentStack) {
134
+ stack = String(error.componentStack);
135
+ }
136
+ line = Number(error.lineno || error.lineNumber || 0);
137
+ column = Number(error.colno || error.columnNumber || 0);
138
+ } else if (typeof error === 'string') {
139
+ stack = error;
140
+ const err = this.getErrorByStack(error);
141
+ if (err) {
142
+ name = err.name || 'Error';
143
+ message = err.message || '';
144
+ } else {
145
+ name = 'Error';
146
+ message = error.substring(0, 200);
147
+ }
148
+ } else if (typeof error === 'number' || typeof error === 'boolean') {
149
+ name = 'Error';
150
+ message = String(error);
151
+ }
152
+ if (!name || !message && !stack || this.errorFilter(error)) {
153
+ return;
154
+ }
155
+ if (this.ctx && this.sendEvent) {
156
+ const baseRumEvent = this.ctx.session.getBaseEvent();
157
+ const normalizedSource = source === 'console.error' ? 'console' : 'event';
158
+ this.sendEvent({
159
+ ...baseRumEvent,
160
+ event_type: _rumCore.RumEventType.EXCEPTION,
161
+ source: normalizedSource,
162
+ type: 'error',
163
+ name,
164
+ message,
165
+ file,
166
+ stack,
167
+ line,
168
+ column,
169
+ times: 1
170
+ });
171
+ }
172
+ } finally {
173
+ this.inErrorHandle = false;
174
+ }
175
+ };
176
+
177
+ /**
178
+ * 根据stack获取Error信息
179
+ * TODO: 增加基于Stack解析filename和lineNumber的能力
180
+ * @param stack
181
+ * @returns
182
+ */
183
+ getErrorByStack(stack = '') {
184
+ const res = stack.split('\n');
185
+ const prefix = 'at ';
186
+ if (res.length < 2) return;
187
+ for (let i = 1; i < res.length; i++) {
188
+ const str = res[i] || '';
189
+ if (str.trim().startsWith(prefix)) {
190
+ const line = res[i - 1] || '';
191
+ const index = line.indexOf(': ');
192
+ return {
193
+ name: line.substring(0, index),
194
+ message: line.substring(index + 2)
195
+ };
196
+ }
197
+ }
198
+ return;
199
+ }
200
+ errorFilter(err) {
201
+ let {
202
+ exception: filters
203
+ } = this.ctx.getConfig().filters || {};
204
+ if (!filters) {
205
+ return false;
206
+ }
207
+ if (!(0, _rumCore.isArray)(filters)) {
208
+ filters = [filters];
209
+ }
210
+ return (0, _rumCore.matchList)(filters, err.name, true, err) || (0, _rumCore.matchList)(filters, err.message, true, err) || (0, _rumCore.matchList)(filters, err.stack || '', true, err);
211
+ }
212
+ destroy() {
213
+ if (!this.installed) return;
214
+ // 恢复 console.error
215
+ if (this.origin.consoleError) {
216
+ console.error = this.origin.consoleError;
217
+ }
218
+ // 恢复 ErrorUtils.setGlobalHandler
219
+ if (ErrorUtils && this.origin.originalOnError) {
220
+ try {
221
+ ErrorUtils.setGlobalHandler(this.origin.originalOnError);
222
+ } catch {
223
+ // ignore
224
+ }
225
+ }
226
+ // 恢复 onunhandledrejection
227
+ if (typeof globalThis !== 'undefined' && this.origin.originalOnUnhandledRejection !== null) {
228
+ try {
229
+ globalThis.onunhandledrejection = this.origin.originalOnUnhandledRejection;
230
+ } catch {
231
+ // ignore
232
+ }
233
+ }
234
+ this.installed = false;
235
+ }
236
+ }
237
+ exports.default = ExceptionCollector;
238
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "ActionCollector", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _index2.default;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "ApiCollector", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _api.default;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "CrashCollector", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _crash.default;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "ExceptionCollector", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _index.default;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "PvCollector", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _pv.default;
34
+ }
35
+ });
36
+ var _pv = _interopRequireDefault(require("./view/pv"));
37
+ var _index = _interopRequireDefault(require("./exception/index"));
38
+ var _crash = _interopRequireDefault(require("./exception/crash"));
39
+ var _api = _interopRequireDefault(require("./resource/api"));
40
+ var _index2 = _interopRequireDefault(require("./action/index"));
41
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
42
+ //# sourceMappingURL=index.js.map