@arms/rum-reactnative 0.1.4 → 0.1.5

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 (32) hide show
  1. package/README.md +47 -0
  2. package/docs/ReactNative SDK/351/205/215/347/275/256/345/217/202/350/200/203.md" +13 -0
  3. package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +9 -0
  4. package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +64 -1
  5. package/harmony/rum_sdk/BuildProfile.ets +17 -0
  6. package/harmony/rum_sdk/Index.ets +2 -0
  7. package/harmony/rum_sdk/build-profile.json5 +22 -0
  8. package/harmony/rum_sdk/hvigorfile.ts +1 -0
  9. package/harmony/rum_sdk/oh-package.json5 +10 -0
  10. package/harmony/rum_sdk/src/main/ets/RumSdkPackage.ets +15 -0
  11. package/harmony/rum_sdk/src/main/ets/RumSdkTurboModule.ts +274 -0
  12. package/harmony/rum_sdk/src/main/ets/crash/CrashManager.ts +344 -0
  13. package/harmony/rum_sdk/src/main/ets/crash/FaultLogParser.ts +331 -0
  14. package/harmony/rum_sdk/src/main/ets/generated/components/ts.ts +5 -0
  15. package/harmony/rum_sdk/src/main/ets/generated/index.ets +5 -0
  16. package/harmony/rum_sdk/src/main/ets/generated/ts.ts +6 -0
  17. package/harmony/rum_sdk/src/main/ets/generated/turboModules/RumSdkReactnative.ts +46 -0
  18. package/harmony/rum_sdk/src/main/ets/generated/turboModules/ts.ts +5 -0
  19. package/harmony/rum_sdk/src/main/module.json5 +9 -0
  20. package/harmony/rum_sdk/ts.ts +1 -0
  21. package/lib/commonjs/NativeRumSdkReactnative.js +1 -1
  22. package/lib/commonjs/utils/crash.js +1 -1
  23. package/lib/commonjs/utils/platform.js +1 -1
  24. package/lib/module/NativeRumSdkReactnative.js +1 -1
  25. package/lib/module/utils/crash.js +1 -1
  26. package/lib/module/utils/platform.js +1 -1
  27. package/lib/typescript/commonjs/src/types/crash.d.ts +2 -0
  28. package/lib/typescript/commonjs/src/utils/platform.d.ts +7 -0
  29. package/lib/typescript/module/src/types/crash.d.ts +2 -0
  30. package/lib/typescript/module/src/utils/platform.d.ts +7 -0
  31. package/package.json +22 -3
  32. package/src/NativeRumSdkReactnative.ts +18 -6
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  ## 功能特性
6
6
 
7
7
  - **原生崩溃采集** — 自动捕获 iOS(KSCrash)与 Android(Java + NDK)原生崩溃,支持堆栈双侧截断与数据体积优化
8
+ - **鸿蒙(HarmonyOS)支持** — 通过 RNOH 接入鸿蒙 Next,原生能力(存储 / 设备信息 / 崩溃采集)由 ArkTS TurboModule 提供,崩溃经系统 faultLogger 事后拉取上报
8
9
  - **OOM采集(iOS)** — 看门狗终止(Watchdog Termination / FOOM)的事后推断上报,默认关闭,需显式开启
9
10
  - **API性能监控** — 自动拦截 XMLHttpRequest / fetch 请求,采集耗时、状态码等指标
10
11
  - **JS错误捕获** — 自动捕获 JavaScript 运行时异常
@@ -263,6 +264,50 @@ armsRum.init({ endpoint: cfg?.endpoint, env: cfg?.env });
263
264
 
264
265
  > 即便不使用 config plugin,Expo 工程在 `npm install` 后执行 `expo prebuild --clean` 即可由 autolinking 自动接入原生模块;plugin 仅提供配置透传的便利。
265
266
 
267
+ ## 鸿蒙(HarmonyOS / RNOH)接入
268
+
269
+ SDK 支持通过 RNOH(React Native for OpenHarmony)接入鸿蒙应用,JS 侧初始化与 iOS / Android 完全一致,无需修改业务代码;原生能力由 SDK 内置的 ArkTS TurboModule(`harmony/rum_sdk`)提供。
270
+
271
+ **前提条件**:
272
+
273
+ - RNOH 0.77.71 线(宿主工程依赖 `@react-native-oh/react-native-harmony` 0.77.71、`react` 18.3.1、`react-native` 0.77.1)
274
+ - DevEco Studio(含 OpenHarmony SDK 与 ohpm)
275
+
276
+ **接入步骤**:
277
+
278
+ 1. 在 JS 工程安装 npm 包(同 iOS / Android):`npm install @arms/rum-reactnative`。
279
+ 2. 在鸿蒙宿主工程的 `entry/oh-package.json5` 中以本地路径引用 SDK 的鸿蒙模块,并执行 `ohpm install`:
280
+
281
+ ```json5
282
+ {
283
+ "dependencies": {
284
+ "@arms/rum-reactnative": "file:../node_modules/@arms/rum-reactnative/harmony/rum_sdk"
285
+ }
286
+ }
287
+ ```
288
+
289
+ 3. 在 `entry/src/main/ets/PackageProvider.ets` 中注册 SDK 的 Package:
290
+
291
+ ```typescript
292
+ import { RumSdkPackage } from '@arms/rum-reactnative';
293
+
294
+ // packages 数组中追加
295
+ new RumSdkPackage(ctx),
296
+ ```
297
+
298
+ 4. 重新构建 HAP(DevEco Studio Build,或 `hvigorw assembleHap`)。
299
+
300
+ **能力差异**:
301
+
302
+ | 能力 | 鸿蒙行为 |
303
+ |------|----------|
304
+ | 原生崩溃采集 | 经系统 faultLogger 事后拉取:崩溃发生后的**下次启动**时读取并上报;采集 JS_CRASH 与 CPP_CRASH,APP_FREEZE 不采集 |
305
+ | OOM 采集 | 不支持(仅 iOS) |
306
+ | 存储 | `@ohos.data.preferences`,命名空间与 iOS / Android 一致 |
307
+ | 纯 JS 能力(API 监控 / JS 错误 / PV / Action / 链路追踪) | 与其他平台一致,原生模块缺失时自动降级为纯 JS 模式 |
308
+
309
+ 完整示例工程参见仓库内 `example-harmony`(含 hdc 驱动的端到端验证脚本)。
310
+
266
311
  ## 原生代码集成方式
267
312
 
268
313
  SDK 的原生崩溃采集层通过**源码编译**集成,不预编译二进制随 npm 包发布:
@@ -400,6 +445,7 @@ SDK 仅持久化一个键 `_arms_uid`(匿名用户 UID),用于跨冷启动
400
445
  |------|------|----------|
401
446
  | iOS | `NSUserDefaults`(独立 suite) | `com.aliyun.arms.rum.reactnative` |
402
447
  | Android | `SharedPreferences`(独立 prefs 文件) | `com.aliyun.arms.rum.reactnative` |
448
+ | HarmonyOS | `@ohos.data.preferences`(独立 store) | `com.aliyun.rum.reactnative` |
403
449
 
404
450
  ### 原生存储 API
405
451
 
@@ -446,6 +492,7 @@ SDK 的 peerDependencies 声明为 `react-native: >=0.68.0`,原生构建配置
446
492
  | **设备信息采集** | `Platform.OS` / `Dimensions.get()` | 0.68 | 全版本可用,原生桥失败有 JS 降级 |
447
493
  | **自监控(Self-Monitoring)** | `fetch` 上报 Protobuf 至 `/rum/monitor` | 0.68 | 纯 JS 实现 |
448
494
  | **Expo 集成** | Expo Config Plugin | Expo SDK 49+(RN 0.72+) | 仅配置透传,零运行时依赖 |
495
+ | **鸿蒙(HarmonyOS)** | RNOH + ArkTS TurboModule + `@ohos.faultLogger` | RNOH 0.77.71(RN 0.77.1 + react 18.3.1) | 依赖宿主为 RNOH 工程;崩溃采集为下次启动事后拉取;App 的 RN 版本不受 0.68 下限约束(鸿蒙侧独立实现) |
449
496
 
450
497
  > **总结**:SDK 声明支持 RN ≥ 0.68。iOS 经 `__has_include` 条件协议 + `RCT_EXPORT_METHOD` 旧桥导出、Android 经 `@ReactMethod` 方法表 + `namespace` DSL 条件守卫,原生能力在 0.68-0.70(旧桥路径)与 0.71+(TurboModule 协议 / interop)均可用;构建层 RN 0.71+ 使用 `install_modules_dependencies` / `react-android`,0.68-0.70 使用手动依赖 / `react-native:+`。JS 侧通过 `TurboModuleRegistry.get` + `NativeModules` 双路径获取原生模块,原生模块缺失时自动降级为空实现,不影响纯 JS 能力。RN ≤0.70 的 Android 宿主需满足 Kotlin ≥1.8 前置条件(见「升级 / 接入注意事项」第 4 条)。
451
498
 
@@ -421,6 +421,19 @@ armsRum.init({
421
421
  });
422
422
  ```
423
423
 
424
+ ## 平台能力差异
425
+
426
+ SDK 的配置项在各平台通用,部分采集能力存在平台差异:
427
+
428
+ | 能力 / 配置 | iOS | Android | HarmonyOS(RNOH) |
429
+ |------------|-----|---------|-------------------|
430
+ | 原生崩溃采集(crash) | KSCrash 现场捕获,下次启动读取上报 | Java + NDK 现场捕获,下次启动读取上报 | 系统 faultLogger 持久化,**下次启动拉取**上报;采集 JS_CRASH / CPP_CRASH,APP_FREEZE 暂不采集 |
431
+ | oom | 支持(`collectors.oom: true` 显式开启) | 空实现(`OutOfMemoryError` 走崩溃链路) | 不支持 |
432
+ | 存储 | `NSUserDefaults`(独立 suite) | `SharedPreferences`(独立 prefs 文件) | `@ohos.data.preferences`(独立 store) |
433
+ | 设备信息 | 原生采集,失败回退 JS 兜底 | 原生采集,失败回退 JS 兜底 | 原生采集,失败回退 JS 兜底 |
434
+
435
+ > **说明**:HarmonyOS 端崩溃在下次启动时上报,`exception` 事件中会携带 `snapshots.raw_log`(系统 faultlog 原文,超长截断)作为解析兜底;重复启动不会重复上报同一次崩溃(ack 删除 + 崩溃指纹去重)。
436
+
424
437
  ## 完整配置示例
425
438
 
426
439
  ```typescript
@@ -4,6 +4,15 @@
4
4
 
5
5
  ## 版本列表
6
6
 
7
+ ### v0.1.5(2026年11月)
8
+
9
+ 新增鸿蒙(HarmonyOS)平台支持,通过 RNOH 接入,JS 侧初始化与 iOS / Android 完全一致。
10
+
11
+ - 新增鸿蒙平台支持:内置 ArkTS TurboModule 提供存储、设备信息与原生崩溃采集,宿主需 RNOH 0.77.71 线(RN 0.77.1 + react 18.3.1)与 DevEco Studio
12
+ - 鸿蒙原生崩溃经系统 faultLogger 于下次启动时拉取上报,采集 JS 崩溃与 Native 崩溃,应用卡死(APP_FREEZE)不采集
13
+ - 鸿蒙端未接入原生模块时自动降级为纯 JS 模式,API 监控 / JS 错误 / PV / Action / 链路追踪照常可用
14
+ - OOM 采集仍仅 iOS 提供,鸿蒙端不支持
15
+
7
16
  ### v0.1.4(2026年10月)
8
17
 
9
18
  iOS 看门狗终止(OOM)推断采集、RN 0.68-0.70 原生兼容打通、API 采集合并为 XHR 单一通道与发布产物混淆修复。
@@ -1,6 +1,6 @@
1
1
  # 接入React Native应用
2
2
 
3
- 阿里云ARMS用户体验监控支持监控React Native应用(编译为Android和iOS等原生应用),通过集成npm包的方式,采集应用运行过程中的性能指标、异常问题和用户行为数据,并上报至ARMS控制台,帮助您提升应用的稳定性和用户体验。
3
+ 阿里云ARMS用户体验监控支持监控React Native应用(编译为Android、iOS及鸿蒙HarmonyOS等原生应用),通过集成npm包的方式,采集应用运行过程中的性能指标、异常问题和用户行为数据,并上报至ARMS控制台,帮助您提升应用的稳定性和用户体验。
4
4
 
5
5
  ## 创建应用
6
6
 
@@ -24,6 +24,7 @@
24
24
  - Android 构建:需安装 NDK 与 CMake(由宿主工程的 `ndkVersion` 决定,SDK 不强制特定版本)
25
25
  - **RN 0.68-0.70 的 Android 工程额外要求**:宿主 `android/build.gradle` 的 buildscript 需声明 `kotlin-gradle-plugin` classpath,且 Kotlin 版本 **≥ 1.8.0**(RN 0.70 模板默认 1.6.x,与 SDK 依赖的 kotlin-stdlib 1.8 metadata 不兼容,需手动提升);AGP 7.2 及以下无需改动,SDK 构建脚本自动回退 AndroidManifest package 属性
26
26
  - iOS 构建:需 CocoaPods(用于拉取 `KSCrash` 崩溃采集依赖);RN 0.68-0.70 无需额外配置,`pod install` 后自动走旧桥导出路径
27
+ - 鸿蒙构建(可选):需 RNOH 0.77.71 线(`@react-native-oh/react-native-harmony` 0.77.71、`react` 18.3.1、`react-native` 0.77.1)与 DevEco Studio,详见下方[接入鸿蒙(HarmonyOS / RNOH)](#接入鸿蒙harmonyos--rnoh)
27
28
 
28
29
  ### 安装步骤
29
30
 
@@ -167,6 +168,64 @@ export default function App() {
167
168
 
168
169
  > **说明**:集成后,SDK会自动采集页面切换事件,包括页面名称、加载时间等信息。
169
170
 
171
+ ## 接入鸿蒙(HarmonyOS / RNOH)
172
+
173
+ SDK 支持通过 RNOH(React Native for OpenHarmony)接入鸿蒙应用。JS 侧初始化代码与 iOS / Android 完全一致,无需修改业务代码;原生能力(存储、设备信息、崩溃采集)由 SDK 内置的 ArkTS TurboModule 提供。
174
+
175
+ ### 前提条件
176
+
177
+ - 宿主工程为 RNOH 工程,且位于 0.77.71 线(`@react-native-oh/react-native-harmony` 0.77.71、`react` 18.3.1、`react-native` 0.77.1)
178
+ - 已安装 DevEco Studio(含 OpenHarmony SDK 与 ohpm)
179
+
180
+ ### 接入步骤
181
+
182
+ **1. 安装 npm 包**
183
+
184
+ 在 JS 工程根目录执行(与 iOS / Android 共用同一安装步骤):
185
+
186
+ ```bash
187
+ npm install @arms/rum-reactnative
188
+ ```
189
+
190
+ **2. 鸿蒙宿主工程添加 ohpm 依赖**
191
+
192
+ 在宿主工程 `entry/oh-package.json5` 中以本地路径引用 SDK 的鸿蒙模块,然后执行 `ohpm install`:
193
+
194
+ ```json5
195
+ {
196
+ "dependencies": {
197
+ "@arms/rum-reactnative": "file:../node_modules/@arms/rum-reactnative/harmony/rum_sdk"
198
+ }
199
+ }
200
+ ```
201
+
202
+ **3. 注册 TurboModule Package**
203
+
204
+ 在 `entry/src/main/ets/PackageProvider.ets` 中注册:
205
+
206
+ ```typescript
207
+ import { RumSdkPackage } from '@arms/rum-reactnative';
208
+
209
+ // 在 packages 数组中追加
210
+ new RumSdkPackage(ctx),
211
+ ```
212
+
213
+ **4. 重新构建 HAP**
214
+
215
+ 使用 DevEco Studio Build,或命令行执行 `hvigorw assembleHap`。构建完成后部署到鸿蒙设备即可,JS 侧 `armsRum.init` 无需任何改动。
216
+
217
+ ### 鸿蒙端能力说明
218
+
219
+ | 能力 | 鸿蒙端行为 |
220
+ |------|-----------|
221
+ | 原生崩溃采集 | 崩溃发生后由系统 faultLogger 服务持久化,SDK 在**下次启动**时拉取并上报;采集 JS 崩溃(JS_CRASH)与 Native 崩溃(CPP_CRASH),应用卡死(APP_FREEZE)暂不采集 |
222
+ | JS 异常 / API 监控 / PV / Action / 链路追踪 | 与 iOS / Android 行为一致 |
223
+ | OOM 采集 | 不支持(仅 iOS 提供) |
224
+ | 存储 | `@ohos.data.preferences`,与应用自身偏好数据相互隔离 |
225
+ | 降级容错 | 原生模块未接入时,SDK 自动降级为纯 JS 模式,事件照常上报 |
226
+
227
+ > **说明**:SDK 使用 `@ohos.faultLogger` 读取应用自身的崩溃记录,无需在 `module.json5` 中声明任何权限。
228
+
170
229
  ## 验证接入
171
230
 
172
231
  完成上述步骤后,启动您的React Native应用并进行一些操作(如点击按钮、发起网络请求等)。等待约1-2分钟后,在ARMS控制台的**用户体验监控** > **应用列表**中查看您的应用,确认有数据上报。
@@ -237,3 +296,7 @@ SDK 的 Android 崩溃采集模块通过 CMake 从源码编译,需要 NDK 与
237
296
  ### 6. iOS `pod install` 拉取 KSCrash 失败?
238
297
 
239
298
  `KSCrash` 通过 CocoaPods 源码依赖引入。若拉取失败,先执行 `pod repo update` 更新本地 spec 仓库后重试;网络受限环境可配置 CocoaPods 镜像源。
299
+
300
+ ### 7. 鸿蒙端崩溃为什么在应用重启后才上报?
301
+
302
+ 鸿蒙端崩溃采集基于系统 faultLogger 服务:崩溃发生时由系统持久化崩溃记录,进程已终止无法现场上报;SDK 在下次启动初始化时拉取、解析并上报,随后删除本地缓存并通过崩溃指纹去重,不会重复上报。这是鸿蒙端的预期行为。
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Use these variables when you tailor your ArkTS code. They must be of the const type.
3
+ */
4
+ export const HAR_VERSION = '0.1.4';
5
+ export const BUILD_MODE_NAME = 'debug';
6
+ export const DEBUG = true;
7
+ export const TARGET_NAME = 'default';
8
+
9
+ /**
10
+ * BuildProfile Class is used only for compatibility purposes.
11
+ */
12
+ export default class BuildProfile {
13
+ static readonly HAR_VERSION = HAR_VERSION;
14
+ static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
15
+ static readonly DEBUG = DEBUG;
16
+ static readonly TARGET_NAME = TARGET_NAME;
17
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ts';
2
+ export * from './src/main/ets/RumSdkPackage';
@@ -0,0 +1,22 @@
1
+ {
2
+ "apiType": "stageMode",
3
+ "buildOption": {},
4
+ "buildOptionSet": [
5
+ {
6
+ "name": "release",
7
+ "arkOptions": {
8
+ "obfuscation": {
9
+ "ruleOptions": {
10
+ "enable": false,
11
+ "files": ["./obfuscation-rules.txt"]
12
+ }
13
+ }
14
+ }
15
+ }
16
+ ],
17
+ "targets": [
18
+ {
19
+ "name": "default"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1 @@
1
+ export { harTasks } from '@ohos/hvigor-ohos-plugin';
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "@arms/rum-reactnative",
3
+ "version": "0.1.5",
4
+ "description": "RUM SDK for React Native - HarmonyOS (RNOH) TurboModule",
5
+ "main": "Index.ets",
6
+ "license": "MIT",
7
+ "dependencies": {
8
+ "@rnoh/react-native-openharmony": "0.77.71"
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ import { RNOHPackage } from '@rnoh/react-native-openharmony'
2
+ import type { AnyThreadTurboModule, AnyThreadTurboModuleContext } from '@rnoh/react-native-openharmony/ts'
3
+ import { TM } from './generated/ts'
4
+ import { RumSdkTurboModule } from './RumSdkTurboModule'
5
+
6
+ export class RumSdkPackage extends RNOHPackage {
7
+ override getAnyThreadTurboModuleFactoryByNameMap(): Map<string, (ctx: AnyThreadTurboModuleContext) => AnyThreadTurboModule | null> {
8
+ return new Map<string, (ctx: AnyThreadTurboModuleContext) => AnyThreadTurboModule>()
9
+ .set(TM.RumSdkReactnative.NAME, (ctx) => new RumSdkTurboModule(ctx))
10
+ }
11
+
12
+ override getDebugName(): string {
13
+ return 'rum_sdk'
14
+ }
15
+ }
@@ -0,0 +1,274 @@
1
+ import { AnyThreadTurboModule } from '@rnoh/react-native-openharmony/ts'
2
+ import type { AnyThreadTurboModuleContext } from '@rnoh/react-native-openharmony/ts'
3
+ import { TM } from './generated/ts'
4
+ import deviceInfo from '@ohos.deviceInfo'
5
+ import dataPreferences from '@ohos.data.preferences'
6
+ import bundleManager from '@ohos.bundle.bundleManager'
7
+ import display from '@ohos.display'
8
+ import util from '@ohos.util'
9
+ import type common from '@ohos.app.ability.common'
10
+ import { CrashManager, triggerArkTsCrash } from './crash/CrashManager'
11
+
12
+ const PREFS_NAME = 'com.aliyun.rum.reactnative'
13
+ const DEVICE_ID_KEY = 'rum_device_id'
14
+
15
+ type RumTurboModuleContext = AnyThreadTurboModuleContext
16
+
17
+ /**
18
+ * RUM SDK 鸿蒙端 TurboModule 实现(P0 阶段):
19
+ * - 存储:@ohos.data.preferences(与 Android SharedPreferences 语义对齐)
20
+ * - 设备信息:deviceInfo / bundleManager / display
21
+ * - 崩溃 / OOM:P2 阶段对接 faultLogger 前的空实现(与 JS 侧降级语义一致)
22
+ *
23
+ * 继承 AnyThreadTurboModule:Worker 线程与 UI 线程均可实例化,
24
+ * RNOH 按任一工厂提供的映射解析。
25
+ */
26
+ export class RumSdkTurboModule extends AnyThreadTurboModule implements TM.RumSdkReactnative.Spec {
27
+ private context: common.UIAbilityContext | undefined = undefined
28
+ private crashManager: CrashManager | undefined = undefined
29
+
30
+ constructor(ctx: RumTurboModuleContext) {
31
+ super(ctx)
32
+ this.context = ctx.uiAbilityContext as common.UIAbilityContext
33
+ }
34
+
35
+ private getCrashManager(): CrashManager {
36
+ if (!this.crashManager && this.context) {
37
+ this.crashManager = new CrashManager(this.context)
38
+ }
39
+ if (!this.crashManager) {
40
+ throw new Error('uiAbilityContext is unavailable')
41
+ }
42
+ return this.crashManager
43
+ }
44
+
45
+ private getPrefs(): dataPreferences.Preferences {
46
+ if (!this.context) {
47
+ throw new Error('uiAbilityContext is unavailable')
48
+ }
49
+ return dataPreferences.getPreferencesSync(this.context, { name: PREFS_NAME })
50
+ }
51
+
52
+ // region Storage
53
+
54
+ getItem(key: string): Promise<null | string> {
55
+ return new Promise<null | string>((resolve, reject) => {
56
+ try {
57
+ const prefs = this.getPrefs()
58
+ if (!prefs.hasSync(key)) {
59
+ resolve(null)
60
+ return
61
+ }
62
+ const value = prefs.getSync(key, '') as string
63
+ resolve(value)
64
+ } catch (e) {
65
+ reject(new Error(`RUM_STORAGE_ERROR: ${e}`))
66
+ }
67
+ })
68
+ }
69
+
70
+ setItem(key: string, value: string): Promise<void> {
71
+ return new Promise<void>((resolve, reject) => {
72
+ try {
73
+ const prefs = this.getPrefs()
74
+ prefs.putSync(key, value)
75
+ prefs.flush()
76
+ resolve()
77
+ } catch (e) {
78
+ reject(new Error(`RUM_STORAGE_ERROR: ${e}`))
79
+ }
80
+ })
81
+ }
82
+
83
+ removeItem(key: string): Promise<void> {
84
+ return new Promise<void>((resolve, reject) => {
85
+ try {
86
+ const prefs = this.getPrefs()
87
+ prefs.deleteSync(key)
88
+ prefs.flush()
89
+ resolve()
90
+ } catch (e) {
91
+ reject(new Error(`RUM_STORAGE_ERROR: ${e}`))
92
+ }
93
+ })
94
+ }
95
+
96
+ clear(): Promise<void> {
97
+ return new Promise<void>((resolve, reject) => {
98
+ try {
99
+ const prefs = this.getPrefs()
100
+ prefs.clearSync()
101
+ prefs.flush()
102
+ resolve()
103
+ } catch (e) {
104
+ reject(new Error(`RUM_STORAGE_ERROR: ${e}`))
105
+ }
106
+ })
107
+ }
108
+
109
+ getAllKeys(): Promise<string[]> {
110
+ return new Promise<string[]>((resolve, reject) => {
111
+ try {
112
+ const prefs = this.getPrefs()
113
+ const all = prefs.getAllSync()
114
+ resolve(Object.keys(all))
115
+ } catch (e) {
116
+ reject(new Error(`RUM_STORAGE_ERROR: ${e}`))
117
+ }
118
+ })
119
+ }
120
+
121
+ // endregion
122
+
123
+ // region Device Info
124
+
125
+ /**
126
+ * OpenHarmony 无公开的设备级稳定 ID API(udid 需系统权限),
127
+ * 采用「本地生成 UUID 并持久化」作为 device_id(应用级稳定,
128
+ * 卸载重装后变化,与 Android ANDROID_ID 恢复出厂重置的语义最接近)。
129
+ */
130
+ private getOrCreateDeviceId(): string {
131
+ try {
132
+ const prefs = this.getPrefs()
133
+ if (prefs.hasSync(DEVICE_ID_KEY)) {
134
+ return prefs.getSync(DEVICE_ID_KEY, '') as string
135
+ }
136
+ const id = util.generateRandomUUID(false)
137
+ prefs.putSync(DEVICE_ID_KEY, id)
138
+ prefs.flush()
139
+ return id
140
+ } catch (e) {
141
+ // 存储不可用时返回临时 ID,避免设备信息整体采集失败
142
+ return util.generateRandomUUID(false)
143
+ }
144
+ }
145
+
146
+ /** deviceInfo.deviceType(phone/tablet/2in1/...)→ 存储模型 device.type 取值 */
147
+ private resolveDeviceType(type: string): string {
148
+ if (type === 'tablet') {
149
+ return 'tablet'
150
+ }
151
+ return 'mobile'
152
+ }
153
+
154
+ getDeviceInfo(): Promise<TM.RumSdkReactnative.NativeDeviceInfo> {
155
+ return new Promise<TM.RumSdkReactnative.NativeDeviceInfo>((resolve, reject) => {
156
+ try {
157
+ const info: TM.RumSdkReactnative.NativeDeviceInfo = {}
158
+ info.device_id = this.getOrCreateDeviceId()
159
+ info.device_brand = deviceInfo.manufacture
160
+ info.device_model = deviceInfo.productModel
161
+ info.device_name = deviceInfo.hardwareModel
162
+ info.device_type = this.resolveDeviceType(deviceInfo.deviceType)
163
+ info.os_type = 'HarmonyOS'
164
+ info.os_version = deviceInfo.osFullName
165
+ try {
166
+ const bundleInfo = bundleManager.getBundleInfoForSelfSync(
167
+ bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT
168
+ )
169
+ info.app_package = bundleInfo.name
170
+ info.app_version = bundleInfo.versionName
171
+ } catch (e) {
172
+ // 忽略,交由 JS 层兜底
173
+ }
174
+ try {
175
+ const d = display.getDefaultDisplaySync()
176
+ info.viewport_width = d.width
177
+ info.viewport_height = d.height
178
+ } catch (e) {
179
+ // 忽略,交由 JS 层 Dimensions 兜底
180
+ }
181
+ resolve(info)
182
+ } catch (e) {
183
+ reject(new Error(`RUM_DEVICE_INFO_ERROR: ${e}`))
184
+ }
185
+ })
186
+ }
187
+
188
+ // endregion
189
+
190
+ // region Crash(对接 @ohos.faultLogger,详见 crash/CrashManager.ts)
191
+
192
+ getPendingCrashes(): Promise<string> {
193
+ return this.getCrashManager().getPendingCrashes()
194
+ }
195
+
196
+ clearCrashReports(crashIds: string): Promise<void> {
197
+ return new Promise<void>((resolve, reject) => {
198
+ try {
199
+ this.getCrashManager().clearCrashReports(crashIds)
200
+ resolve()
201
+ } catch (e) {
202
+ reject(new Error(`RUM_CRASH_ERROR: ${e}`))
203
+ }
204
+ })
205
+ }
206
+
207
+ clearAllCrashReports(): Promise<void> {
208
+ return new Promise<void>((resolve, reject) => {
209
+ try {
210
+ this.getCrashManager().clearAllCrashReports()
211
+ resolve()
212
+ } catch (e) {
213
+ reject(new Error(`RUM_CRASH_ERROR: ${e}`))
214
+ }
215
+ })
216
+ }
217
+
218
+ cleanupOldCrashes(maxFiles: number, maxAgeMs: number): Promise<void> {
219
+ return new Promise<void>((resolve, reject) => {
220
+ try {
221
+ this.getCrashManager().cleanupOldCrashes(maxFiles, maxAgeMs)
222
+ resolve()
223
+ } catch (e) {
224
+ reject(new Error(`RUM_CRASH_ERROR: ${e}`))
225
+ }
226
+ })
227
+ }
228
+
229
+ crashedLastRun(): Promise<boolean> {
230
+ return new Promise<boolean>((resolve, reject) => {
231
+ try {
232
+ resolve(this.getCrashManager().hasCrashFiles())
233
+ } catch (e) {
234
+ reject(new Error(`RUM_CRASH_ERROR: ${e}`))
235
+ }
236
+ })
237
+ }
238
+
239
+ updateCrashContext(context: string): void {
240
+ try {
241
+ this.getCrashManager().updateContext(context)
242
+ } catch (e) {
243
+ // ignore
244
+ }
245
+ }
246
+
247
+ triggerTestCrash(crashType: string): void {
248
+ if (crashType === 'js_crash' || crashType === 'js_exception' || crashType === 'java_exception') {
249
+ triggerArkTsCrash()
250
+ }
251
+ }
252
+
253
+ // endregion
254
+
255
+ // region OOM(看门狗终止为 iOS 能力,鸿蒙端空实现)
256
+
257
+ getPendingOomReports(): Promise<string> {
258
+ return new Promise<string>((resolve) => {
259
+ resolve('[]')
260
+ })
261
+ }
262
+
263
+ clearOomReports(oomIds: string): Promise<void> {
264
+ return new Promise<void>((resolve, reject) => {
265
+ resolve()
266
+ })
267
+ }
268
+
269
+ updateCollectorsConfig(config: string): void {
270
+ // 鸿蒙端暂无可同步的原生采集配置,接受但忽略
271
+ }
272
+
273
+ // endregion
274
+ }