@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
@@ -0,0 +1,46 @@
1
+ /**
2
+ * This code was generated by "react-native codegen-lib-harmony"
3
+ */
4
+
5
+ import { Tag } from "@rnoh/react-native-openharmony/ts"
6
+
7
+ export namespace RumSdkReactnative {
8
+ export const NAME = 'RumSdkReactnative' as const
9
+
10
+ export type NativeDeviceInfo = {device_id?: string, device_type?: string, device_brand?: string, device_model?: string, device_name?: string, os_type?: string, os_version?: string, app_package?: string, app_version?: string, viewport_width?: number, viewport_height?: number}
11
+
12
+ export interface Spec {
13
+ getItem(key: string): Promise<null | string>;
14
+
15
+ setItem(key: string, value: string): Promise<void>;
16
+
17
+ removeItem(key: string): Promise<void>;
18
+
19
+ clear(): Promise<void>;
20
+
21
+ getAllKeys(): Promise<string[]>;
22
+
23
+ getDeviceInfo(): Promise<NativeDeviceInfo>;
24
+
25
+ getPendingCrashes(): Promise<string>;
26
+
27
+ clearCrashReports(crashIds: string): Promise<void>;
28
+
29
+ clearAllCrashReports(): Promise<void>;
30
+
31
+ cleanupOldCrashes(maxFiles: number, maxAgeMs: number): Promise<void>;
32
+
33
+ crashedLastRun(): Promise<boolean>;
34
+
35
+ updateCrashContext(context: string): void;
36
+
37
+ triggerTestCrash(crashType: string): void;
38
+
39
+ getPendingOomReports(): Promise<string>;
40
+
41
+ clearOomReports(oomIds: string): Promise<void>;
42
+
43
+ updateCollectorsConfig(config: string): void;
44
+
45
+ }
46
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This code was generated by "react-native codegen-lib-harmony"
3
+ */
4
+
5
+ export * from "./RumSdkReactnative"
@@ -0,0 +1,9 @@
1
+ {
2
+ "module": {
3
+ "name": "rum_sdk",
4
+ "type": "har",
5
+ "deviceTypes": [
6
+ "default"
7
+ ]
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ export * from './src/main/ets/RumSdkTurboModule';
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _reactNative=require("react-native");const nativeModule=_reactNative.TurboModuleRegistry.get("RumSdkReactnative")??_reactNative.NativeModules.RumSdkReactnative;nativeModule||console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.");const fallback={getItem:async()=>null,setItem:async()=>{},removeItem:async()=>{},clear:async()=>{},getAllKeys:async()=>[],getDeviceInfo:async()=>({}),getPendingCrashes:async()=>"[]",clearCrashReports:async()=>{},clearAllCrashReports:async()=>{},cleanupOldCrashes:async()=>{},crashedLastRun:async()=>!1,updateCrashContext:()=>{},triggerTestCrash:()=>{},getPendingOomReports:async()=>"[]",clearOomReports:async()=>{},updateCollectorsConfig:()=>{}};var _default=exports.default=nativeModule??fallback;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _reactNative=require("react-native");let nativeModule;try{nativeModule=_reactNative.TurboModuleRegistry.get("RumSdkReactnative")??_reactNative.NativeModules.RumSdkReactnative}catch(e){console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.",e)}nativeModule||console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.");const fallback={getItem:async()=>null,setItem:async()=>{},removeItem:async()=>{},clear:async()=>{},getAllKeys:async()=>[],getDeviceInfo:async()=>({}),getPendingCrashes:async()=>"[]",clearCrashReports:async()=>{},clearAllCrashReports:async()=>{},cleanupOldCrashes:async()=>{},crashedLastRun:async()=>!1,updateCrashContext:()=>{},triggerTestCrash:()=>{},getPendingOomReports:async()=>"[]",clearOomReports:async()=>{},updateCollectorsConfig:()=>{}};var _default=exports.default=nativeModule??fallback;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.convertCrashToRumEvent=convertCrashToRumEvent,exports.convertOomToRumEvent=convertOomToRumEvent,exports.safeNativeCall=safeNativeCall;var _rumCore=require("@arms/rum-core");function convertCrashToRumEvent(e){const t=e.signal?.name||e.exception?.class_name||"NativeCrash",n=buildMessage(e),a=e.frames||e.crashed_thread?.frames||[],s=formatStack(a),i=a[0],r="object"==typeof i&&i?.library||"";let o=0;if(a.length>0){const e=a[0];e&&"object"==typeof e&&"number"==typeof e.line&&(o=e.line)}const m={id:e.context?.view_id||"",name:e.context?.view_name||""};let c=e.timestamp||Date.now();c<1e12&&(c*=1e3);const u=(e.binary_images||[]).map(e=>e.uuid||!e.build_id&&!e.debug_id?e:{...e,uuid:e.build_id||e.debug_id});return{event_type:_rumCore.RumEventType.EXCEPTION,timestamp:c,session_id:e.context?.session_id,view:m,times:1,source:"event",type:"crash",name:t,message:n,file:r,line:o,column:0,stack:s,caused_by:e.exception?.message||(e.signal?`${e.signal.name||""} at ${e.signal.fault_address||""}`:""),binary_images:JSON.stringify(u),snapshots:JSON.stringify({device:e.device||{},registers:e.registers||{},app:e.app||{},crash_context:e.context||{},arch:e.arch||"",pid:e.pid,signal_number:e.signal?.number,thread_id:String(e.crashed_thread?.id??e.tid??""),...e.mechanism?{mechanism:e.mechanism}:{}})}}const OOM_DEFAULT_MESSAGE="App was killed while active with no crash report (suspected watchdog termination)",OOM_DEFAULT_MECHANISM={type:"watchdog_termination",handled:!1};function convertOomToRumEvent(e){let t=e.timestamp||Date.now();return t<1e12&&(t*=1e3),{event_type:_rumCore.RumEventType.EXCEPTION,timestamp:t,session_id:e.context?.session_id,view:{id:e.context?.view_id||"",name:e.context?.view_name||""},times:1,source:"event",type:"crash",subtype:"oom",name:e.name||"WatchdogTermination",message:e.message||OOM_DEFAULT_MESSAGE,stack:"",snapshots:JSON.stringify({mechanism:e.mechanism||OOM_DEFAULT_MECHANISM,platform:e.platform||"ios",app_state:e.app_state||{},crash_context:e.context||{},estimated:!0})}}function buildMessage(e){if(e.exception?.message)return e.exception.message;const t=e.signal;if(t){const e=t.fault_address||"";return`${t.name||""} (${t.code??""})${e?" at "+e:""}`.trim()}return"Native crash"}function formatStack(e){return e&&0!==e.length?e.map((e,t)=>{if("string"==typeof e)return`#${t} <unknown> ${e} ()`;if(e.truncated){const n=e.omitted_count??-1;return n<0?`#${t} ... frames omitted (unknown count) ...`:`#${t} ... ${n} frames omitted ...`}const n=e.library||"<unknown>",a=e.symbol||"",s=e.address||"",i=e.offset||"";return a?`#${t} ${n} ${a} + ${i}`:`#${t} ${n} ${s} (${i})`}).join("\n"):""}async function safeNativeCall(e,t){try{return await e()}catch(e){return void _rumCore.logger.warn("native-bridge",`${t||"native call"} failed`,e)}}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.convertCrashToRumEvent=convertCrashToRumEvent,exports.convertOomToRumEvent=convertOomToRumEvent,exports.safeNativeCall=safeNativeCall;var _rumCore=require("@arms/rum-core");function convertCrashToRumEvent(e){const t=e.signal?.name||e.exception?.class_name||"NativeCrash",n=buildMessage(e),a=e.frames||e.crashed_thread?.frames||[],s=formatStack(a),i=a[0],r="object"==typeof i&&i?.library||"";let o=0;if(a.length>0){const e=a[0];e&&"object"==typeof e&&"number"==typeof e.line&&(o=e.line)}const m={id:e.context?.view_id||"",name:e.context?.view_name||""};let c=e.timestamp||Date.now();c<1e12&&(c*=1e3);const u=(e.binary_images||[]).map(e=>e.uuid||!e.build_id&&!e.debug_id?e:{...e,uuid:e.build_id||e.debug_id});return{event_type:_rumCore.RumEventType.EXCEPTION,timestamp:c,session_id:e.context?.session_id,view:m,times:1,source:"event",type:"crash",name:t,message:n,file:r,line:o,column:0,stack:s,caused_by:e.exception?.message||(e.signal?`${e.signal.name||""} at ${e.signal.fault_address||""}`:""),binary_images:JSON.stringify(u),snapshots:JSON.stringify({device:e.device||{},registers:e.registers||{},app:e.app||{},crash_context:e.context||{},arch:e.arch||"",pid:e.pid,signal_number:e.signal?.number,thread_id:String(e.crashed_thread?.id??e.tid??""),...e.mechanism?{mechanism:e.mechanism}:{},...e.raw_log?{raw_log:e.raw_log}:{}})}}const OOM_DEFAULT_MESSAGE="App was killed while active with no crash report (suspected watchdog termination)",OOM_DEFAULT_MECHANISM={type:"watchdog_termination",handled:!1};function convertOomToRumEvent(e){let t=e.timestamp||Date.now();return t<1e12&&(t*=1e3),{event_type:_rumCore.RumEventType.EXCEPTION,timestamp:t,session_id:e.context?.session_id,view:{id:e.context?.view_id||"",name:e.context?.view_name||""},times:1,source:"event",type:"crash",subtype:"oom",name:e.name||"WatchdogTermination",message:e.message||OOM_DEFAULT_MESSAGE,stack:"",snapshots:JSON.stringify({mechanism:e.mechanism||OOM_DEFAULT_MECHANISM,platform:e.platform||"ios",app_state:e.app_state||{},crash_context:e.context||{},estimated:!0})}}function buildMessage(e){if(e.exception?.message)return e.exception.message;const t=e.signal;if(t){const e=t.fault_address||"";return`${t.name||""} (${t.code??""})${e?" at "+e:""}`.trim()}return"Native crash"}function formatStack(e){return e&&0!==e.length?e.map((e,t)=>{if("string"==typeof e)return`#${t} <unknown> ${e} ()`;if(e.truncated){const n=e.omitted_count??-1;return n<0?`#${t} ... frames omitted (unknown count) ...`:`#${t} ... ${n} frames omitted ...`}const n=e.library||"<unknown>",a=e.symbol||"",s=e.address||"",i=e.offset||"";return a?`#${t} ${n} ${a} + ${i}`:`#${t} ${n} ${s} (${i})`}).join("\n"):""}async function safeNativeCall(e,t){try{return await e()}catch(e){return void _rumCore.logger.warn("native-bridge",`${t||"native call"} failed`,e)}}
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.appName=exports.VERSION=void 0,exports.clearStorage=clearStorage,exports.fixAttrs=void 0,exports.getAllStorageKeys=getAllStorageKeys,exports.getStorage=getStorage,exports.removeStorage=removeStorage,exports.setStorage=setStorage;var _rumCore=require("@arms/rum-core"),_reactNative=require("react-native"),_NativeRumSdkReactnative=_interopRequireDefault(require("../NativeRumSdkReactnative"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const _pkg={version:"0.1.4"},VERSION=exports.VERSION=_pkg.version,appName=exports.appName="react-native";function getReactNativeVersion(){try{return require("react-native/package.json").version??""}catch{const e=_reactNative.Platform.constants?.reactNativeVersion;return e?`${e.major}.${e.minor}.${e.patch}`:""}}function getStorage(e){return _NativeRumSdkReactnative.default.getItem(e)}function setStorage(e,t){return _NativeRumSdkReactnative.default.setItem(e,t)}function removeStorage(e){return _NativeRumSdkReactnative.default.removeItem(e)}function clearStorage(){return _NativeRumSdkReactnative.default.clear()}function getAllStorageKeys(){return _NativeRumSdkReactnative.default.getAllKeys()}async function fetchDeviceInfo(){try{return await _NativeRumSdkReactnative.default.getDeviceInfo()}catch(e){return console.warn("[rum] getDeviceInfo failed, falling back to JS defaults",e),{os_type:"ios"===_reactNative.Platform.OS?"iOS":"Android",os_version:String(_reactNative.Platform.Version??"")}}}let _cachedDeviceInfo=null;function getDeviceInfo(){return _cachedDeviceInfo||(_cachedDeviceInfo=fetchDeviceInfo()),_cachedDeviceInfo}const fixAttrs=async function(e){if(!e)return;const t=await getDeviceInfo(),r={id:t.device_id,type:t.device_type,brand:t.device_brand,model:t.device_model,name:t.device_name},a=getReactNativeVersion(),i={type:t.os_type??("ios"===_reactNative.Platform.OS?"iOS":"Android"),version:t.os_version??String(_reactNative.Platform.Version??""),container:appName,container_version:a||void 0};let o;if(t.viewport_width&&t.viewport_height)o={width:t.viewport_width,height:t.viewport_height};else try{const e=_reactNative.Dimensions.get("screen");o={width:Math.round(e.width),height:Math.round(e.height)}}catch{}return e.app.type=_rumCore.AppType.reactnative,e.app.package=e.app.package??t.app_package,e.app.version=e.app.version??t.app_version,e._v=VERSION,e.device={...r,...e.device},e.os={...i,...e.os},o&&(e.viewport={...e.viewport,...o}),e};exports.fixAttrs=fixAttrs;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.appName=exports.VERSION=void 0,exports.clearStorage=clearStorage,exports.fixAttrs=void 0,exports.getAllStorageKeys=getAllStorageKeys,exports.getStorage=getStorage,exports.removeStorage=removeStorage,exports.resolveOsType=resolveOsType,exports.setStorage=setStorage;var _rumCore=require("@arms/rum-core"),_reactNative=require("react-native"),_NativeRumSdkReactnative=_interopRequireDefault(require("../NativeRumSdkReactnative"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const _pkg={version:"0.1.5"},VERSION=exports.VERSION=_pkg.version,appName=exports.appName="react-native";function resolveOsType(){switch(_reactNative.Platform.OS){case"ios":return"iOS";case"harmony":return"HarmonyOS";default:return"Android"}}function getReactNativeVersion(){try{return require("react-native/package.json").version??""}catch{const e=_reactNative.Platform.constants?.reactNativeVersion;return e?`${e.major}.${e.minor}.${e.patch}`:""}}function getStorage(e){return _NativeRumSdkReactnative.default.getItem(e)}function setStorage(e,t){return _NativeRumSdkReactnative.default.setItem(e,t)}function removeStorage(e){return _NativeRumSdkReactnative.default.removeItem(e)}function clearStorage(){return _NativeRumSdkReactnative.default.clear()}function getAllStorageKeys(){return _NativeRumSdkReactnative.default.getAllKeys()}async function fetchDeviceInfo(){try{return await _NativeRumSdkReactnative.default.getDeviceInfo()}catch(e){return console.warn("[rum] getDeviceInfo failed, falling back to JS defaults",e),{os_type:resolveOsType(),os_version:String(_reactNative.Platform.Version??"")}}}let _cachedDeviceInfo=null;function getDeviceInfo(){return _cachedDeviceInfo||(_cachedDeviceInfo=fetchDeviceInfo()),_cachedDeviceInfo}const fixAttrs=async function(e){if(!e)return;const t=await getDeviceInfo(),r={id:t.device_id,type:t.device_type,brand:t.device_brand,model:t.device_model,name:t.device_name},a=getReactNativeVersion(),i={type:t.os_type??resolveOsType(),version:t.os_version??String(_reactNative.Platform.Version??""),container:appName,container_version:a||void 0};let o;if(t.viewport_width&&t.viewport_height)o={width:t.viewport_width,height:t.viewport_height};else try{const e=_reactNative.Dimensions.get("screen");o={width:Math.round(e.width),height:Math.round(e.height)}}catch{}return e.app.type=_rumCore.AppType.reactnative,e.app.package=e.app.package??t.app_package,e.app.version=e.app.version??t.app_version,e._v=VERSION,e.device={...r,...e.device},e.os={...i,...e.os},o&&(e.viewport={...e.viewport,...o}),e};exports.fixAttrs=fixAttrs;
@@ -1 +1 @@
1
- "use strict";import{NativeModules,TurboModuleRegistry}from"react-native";const nativeModule=TurboModuleRegistry.get("RumSdkReactnative")??NativeModules.RumSdkReactnative;nativeModule||console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.");const fallback={getItem:async()=>null,setItem:async()=>{},removeItem:async()=>{},clear:async()=>{},getAllKeys:async()=>[],getDeviceInfo:async()=>({}),getPendingCrashes:async()=>"[]",clearCrashReports:async()=>{},clearAllCrashReports:async()=>{},cleanupOldCrashes:async()=>{},crashedLastRun:async()=>!1,updateCrashContext:()=>{},triggerTestCrash:()=>{},getPendingOomReports:async()=>"[]",clearOomReports:async()=>{},updateCollectorsConfig:()=>{}};export default nativeModule??fallback;
1
+ "use strict";import{NativeModules,TurboModuleRegistry}from"react-native";let nativeModule;try{nativeModule=TurboModuleRegistry.get("RumSdkReactnative")??NativeModules.RumSdkReactnative}catch(e){console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.",e)}nativeModule||console.warn("[rum] Native module 'RumSdkReactnative' not found in the native binary. Crash reporting and native device info are disabled. Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, or `pod install` + rebuild) so the module gets registered.");const fallback={getItem:async()=>null,setItem:async()=>{},removeItem:async()=>{},clear:async()=>{},getAllKeys:async()=>[],getDeviceInfo:async()=>({}),getPendingCrashes:async()=>"[]",clearCrashReports:async()=>{},clearAllCrashReports:async()=>{},cleanupOldCrashes:async()=>{},crashedLastRun:async()=>!1,updateCrashContext:()=>{},triggerTestCrash:()=>{},getPendingOomReports:async()=>"[]",clearOomReports:async()=>{},updateCollectorsConfig:()=>{}};export default nativeModule??fallback;
@@ -1 +1 @@
1
- "use strict";import{RumEventType,logger}from"@arms/rum-core";export function convertCrashToRumEvent(e){const t=e.signal?.name||e.exception?.class_name||"NativeCrash",n=buildMessage(e),a=e.frames||e.crashed_thread?.frames||[],i=formatStack(a),s=a[0],r="object"==typeof s&&s?.library||"";let o=0;if(a.length>0){const e=a[0];e&&"object"==typeof e&&"number"==typeof e.line&&(o=e.line)}const c={id:e.context?.view_id||"",name:e.context?.view_name||""};let m=e.timestamp||Date.now();m<1e12&&(m*=1e3);const d=(e.binary_images||[]).map(e=>e.uuid||!e.build_id&&!e.debug_id?e:{...e,uuid:e.build_id||e.debug_id});return{event_type:RumEventType.EXCEPTION,timestamp:m,session_id:e.context?.session_id,view:c,times:1,source:"event",type:"crash",name:t,message:n,file:r,line:o,column:0,stack:i,caused_by:e.exception?.message||(e.signal?`${e.signal.name||""} at ${e.signal.fault_address||""}`:""),binary_images:JSON.stringify(d),snapshots:JSON.stringify({device:e.device||{},registers:e.registers||{},app:e.app||{},crash_context:e.context||{},arch:e.arch||"",pid:e.pid,signal_number:e.signal?.number,thread_id:String(e.crashed_thread?.id??e.tid??""),...e.mechanism?{mechanism:e.mechanism}:{}})}}const OOM_DEFAULT_MESSAGE="App was killed while active with no crash report (suspected watchdog termination)",OOM_DEFAULT_MECHANISM={type:"watchdog_termination",handled:!1};export function convertOomToRumEvent(e){let t=e.timestamp||Date.now();return t<1e12&&(t*=1e3),{event_type:RumEventType.EXCEPTION,timestamp:t,session_id:e.context?.session_id,view:{id:e.context?.view_id||"",name:e.context?.view_name||""},times:1,source:"event",type:"crash",subtype:"oom",name:e.name||"WatchdogTermination",message:e.message||OOM_DEFAULT_MESSAGE,stack:"",snapshots:JSON.stringify({mechanism:e.mechanism||OOM_DEFAULT_MECHANISM,platform:e.platform||"ios",app_state:e.app_state||{},crash_context:e.context||{},estimated:!0})}}function buildMessage(e){if(e.exception?.message)return e.exception.message;const t=e.signal;if(t){const e=t.fault_address||"";return`${t.name||""} (${t.code??""})${e?" at "+e:""}`.trim()}return"Native crash"}function formatStack(e){return e&&0!==e.length?e.map((e,t)=>{if("string"==typeof e)return`#${t} <unknown> ${e} ()`;if(e.truncated){const n=e.omitted_count??-1;return n<0?`#${t} ... frames omitted (unknown count) ...`:`#${t} ... ${n} frames omitted ...`}const n=e.library||"<unknown>",a=e.symbol||"",i=e.address||"",s=e.offset||"";return a?`#${t} ${n} ${a} + ${s}`:`#${t} ${n} ${i} (${s})`}).join("\n"):""}export async function safeNativeCall(e,t){try{return await e()}catch(e){return void logger.warn("native-bridge",`${t||"native call"} failed`,e)}}
1
+ "use strict";import{RumEventType,logger}from"@arms/rum-core";export function convertCrashToRumEvent(e){const t=e.signal?.name||e.exception?.class_name||"NativeCrash",n=buildMessage(e),a=e.frames||e.crashed_thread?.frames||[],i=formatStack(a),s=a[0],r="object"==typeof s&&s?.library||"";let o=0;if(a.length>0){const e=a[0];e&&"object"==typeof e&&"number"==typeof e.line&&(o=e.line)}const c={id:e.context?.view_id||"",name:e.context?.view_name||""};let m=e.timestamp||Date.now();m<1e12&&(m*=1e3);const d=(e.binary_images||[]).map(e=>e.uuid||!e.build_id&&!e.debug_id?e:{...e,uuid:e.build_id||e.debug_id});return{event_type:RumEventType.EXCEPTION,timestamp:m,session_id:e.context?.session_id,view:c,times:1,source:"event",type:"crash",name:t,message:n,file:r,line:o,column:0,stack:i,caused_by:e.exception?.message||(e.signal?`${e.signal.name||""} at ${e.signal.fault_address||""}`:""),binary_images:JSON.stringify(d),snapshots:JSON.stringify({device:e.device||{},registers:e.registers||{},app:e.app||{},crash_context:e.context||{},arch:e.arch||"",pid:e.pid,signal_number:e.signal?.number,thread_id:String(e.crashed_thread?.id??e.tid??""),...e.mechanism?{mechanism:e.mechanism}:{},...e.raw_log?{raw_log:e.raw_log}:{}})}}const OOM_DEFAULT_MESSAGE="App was killed while active with no crash report (suspected watchdog termination)",OOM_DEFAULT_MECHANISM={type:"watchdog_termination",handled:!1};export function convertOomToRumEvent(e){let t=e.timestamp||Date.now();return t<1e12&&(t*=1e3),{event_type:RumEventType.EXCEPTION,timestamp:t,session_id:e.context?.session_id,view:{id:e.context?.view_id||"",name:e.context?.view_name||""},times:1,source:"event",type:"crash",subtype:"oom",name:e.name||"WatchdogTermination",message:e.message||OOM_DEFAULT_MESSAGE,stack:"",snapshots:JSON.stringify({mechanism:e.mechanism||OOM_DEFAULT_MECHANISM,platform:e.platform||"ios",app_state:e.app_state||{},crash_context:e.context||{},estimated:!0})}}function buildMessage(e){if(e.exception?.message)return e.exception.message;const t=e.signal;if(t){const e=t.fault_address||"";return`${t.name||""} (${t.code??""})${e?" at "+e:""}`.trim()}return"Native crash"}function formatStack(e){return e&&0!==e.length?e.map((e,t)=>{if("string"==typeof e)return`#${t} <unknown> ${e} ()`;if(e.truncated){const n=e.omitted_count??-1;return n<0?`#${t} ... frames omitted (unknown count) ...`:`#${t} ... ${n} frames omitted ...`}const n=e.library||"<unknown>",a=e.symbol||"",i=e.address||"",s=e.offset||"";return a?`#${t} ${n} ${a} + ${s}`:`#${t} ${n} ${i} (${s})`}).join("\n"):""}export async function safeNativeCall(e,t){try{return await e()}catch(e){return void logger.warn("native-bridge",`${t||"native call"} failed`,e)}}
@@ -1 +1 @@
1
- "use strict";import{AppType}from"@arms/rum-core";import{Dimensions,Platform}from"react-native";import NativeRumSdkReactnative from"../NativeRumSdkReactnative.js";const _pkg={version:"0.1.4"};export const VERSION=_pkg.version;export const appName="react-native";function getReactNativeVersion(){try{return require("react-native/package.json").version??""}catch{const e=Platform.constants?.reactNativeVersion;return e?`${e.major}.${e.minor}.${e.patch}`:""}}export function getStorage(e){return NativeRumSdkReactnative.getItem(e)}export function setStorage(e,t){return NativeRumSdkReactnative.setItem(e,t)}export function removeStorage(e){return NativeRumSdkReactnative.removeItem(e)}export function clearStorage(){return NativeRumSdkReactnative.clear()}export function getAllStorageKeys(){return NativeRumSdkReactnative.getAllKeys()}async function fetchDeviceInfo(){try{return await NativeRumSdkReactnative.getDeviceInfo()}catch(e){return console.warn("[rum] getDeviceInfo failed, falling back to JS defaults",e),{os_type:"ios"===Platform.OS?"iOS":"Android",os_version:String(Platform.Version??"")}}}let _cachedDeviceInfo=null;function getDeviceInfo(){return _cachedDeviceInfo||(_cachedDeviceInfo=fetchDeviceInfo()),_cachedDeviceInfo}export const fixAttrs=async function(e){if(!e)return;const t=await getDeviceInfo(),i={id:t.device_id,type:t.device_type,brand:t.device_brand,model:t.device_model,name:t.device_name},r=getReactNativeVersion(),n={type:t.os_type??("ios"===Platform.OS?"iOS":"Android"),version:t.os_version??String(Platform.Version??""),container:appName,container_version:r||void 0};let o;if(t.viewport_width&&t.viewport_height)o={width:t.viewport_width,height:t.viewport_height};else try{const e=Dimensions.get("screen");o={width:Math.round(e.width),height:Math.round(e.height)}}catch{}return e.app.type=AppType.reactnative,e.app.package=e.app.package??t.app_package,e.app.version=e.app.version??t.app_version,e._v=VERSION,e.device={...i,...e.device},e.os={...n,...e.os},o&&(e.viewport={...e.viewport,...o}),e};
1
+ "use strict";import{AppType}from"@arms/rum-core";import{Dimensions,Platform}from"react-native";import NativeRumSdkReactnative from"../NativeRumSdkReactnative.js";const _pkg={version:"0.1.5"};export const VERSION=_pkg.version;export const appName="react-native";export function resolveOsType(){switch(Platform.OS){case"ios":return"iOS";case"harmony":return"HarmonyOS";default:return"Android"}}function getReactNativeVersion(){try{return require("react-native/package.json").version??""}catch{const e=Platform.constants?.reactNativeVersion;return e?`${e.major}.${e.minor}.${e.patch}`:""}}export function getStorage(e){return NativeRumSdkReactnative.getItem(e)}export function setStorage(e,t){return NativeRumSdkReactnative.setItem(e,t)}export function removeStorage(e){return NativeRumSdkReactnative.removeItem(e)}export function clearStorage(){return NativeRumSdkReactnative.clear()}export function getAllStorageKeys(){return NativeRumSdkReactnative.getAllKeys()}async function fetchDeviceInfo(){try{return await NativeRumSdkReactnative.getDeviceInfo()}catch(e){return console.warn("[rum] getDeviceInfo failed, falling back to JS defaults",e),{os_type:resolveOsType(),os_version:String(Platform.Version??"")}}}let _cachedDeviceInfo=null;function getDeviceInfo(){return _cachedDeviceInfo||(_cachedDeviceInfo=fetchDeviceInfo()),_cachedDeviceInfo}export const fixAttrs=async function(e){if(!e)return;const t=await getDeviceInfo(),r={id:t.device_id,type:t.device_type,brand:t.device_brand,model:t.device_model,name:t.device_name},i=getReactNativeVersion(),n={type:t.os_type??resolveOsType(),version:t.os_version??String(Platform.Version??""),container:appName,container_version:i||void 0};let o;if(t.viewport_width&&t.viewport_height)o={width:t.viewport_width,height:t.viewport_height};else try{const e=Dimensions.get("screen");o={width:Math.round(e.width),height:Math.round(e.height)}}catch{}return e.app.type=AppType.reactnative,e.app.package=e.app.package??t.app_package,e.app.version=e.app.version??t.app_version,e._v=VERSION,e.device={...r,...e.device},e.os={...n,...e.os},o&&(e.viewport={...e.viewport,...o}),e};
@@ -91,5 +91,7 @@ export interface NativeCrashData {
91
91
  };
92
92
  /** 崩溃机制信息(iOS normalizeKSCrashReport / Android getPendingCrashes 写入) */
93
93
  mechanism?: Record<string, unknown>;
94
+ /** 原始崩溃日志(鸿蒙 faultlog 全文,已截断),解析失败时的兜底信息 */
95
+ raw_log?: string;
94
96
  }
95
97
  //# sourceMappingURL=crash.d.ts.map
@@ -9,6 +9,13 @@ export interface Global {
9
9
  }
10
10
  export declare var global: Global;
11
11
  export declare const appName = "react-native";
12
+ /**
13
+ * 将 Platform.OS 映射为存储模型 os.type 的取值。
14
+ * RNOH(React Native for OpenHarmony)环境下 Platform.OS === 'harmony',
15
+ * 该取值由 @react-native-oh/react-native-harmony 的类型扩展提供,
16
+ * 标准RN类型中不存在,故此处按 string 收窄。
17
+ */
18
+ export declare function resolveOsType(): string;
12
19
  export declare function getStorage(key: string): Promise<string | null>;
13
20
  export declare function setStorage(key: string, data: string): Promise<void>;
14
21
  export declare function removeStorage(key: string): Promise<void>;
@@ -91,5 +91,7 @@ export interface NativeCrashData {
91
91
  };
92
92
  /** 崩溃机制信息(iOS normalizeKSCrashReport / Android getPendingCrashes 写入) */
93
93
  mechanism?: Record<string, unknown>;
94
+ /** 原始崩溃日志(鸿蒙 faultlog 全文,已截断),解析失败时的兜底信息 */
95
+ raw_log?: string;
94
96
  }
95
97
  //# sourceMappingURL=crash.d.ts.map
@@ -9,6 +9,13 @@ export interface Global {
9
9
  }
10
10
  export declare var global: Global;
11
11
  export declare const appName = "react-native";
12
+ /**
13
+ * 将 Platform.OS 映射为存储模型 os.type 的取值。
14
+ * RNOH(React Native for OpenHarmony)环境下 Platform.OS === 'harmony',
15
+ * 该取值由 @react-native-oh/react-native-harmony 的类型扩展提供,
16
+ * 标准RN类型中不存在,故此处按 string 收窄。
17
+ */
18
+ export declare function resolveOsType(): string;
12
19
  export declare function getStorage(key: string): Promise<string | null>;
13
20
  export declare function setStorage(key: string, data: string): Promise<void>;
14
21
  export declare function removeStorage(key: string): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arms/rum-reactnative",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "RUM SDK For ReactNative",
5
5
  "homepage": "https://help.aliyun.com/zh/arms/user-experience-monitoring/",
6
6
  "main": "./lib/commonjs/index.js",
@@ -24,6 +24,7 @@
24
24
  "src/NativeRumSdkReactnative.ts",
25
25
  "android",
26
26
  "ios",
27
+ "harmony",
27
28
  "docs",
28
29
  "*.podspec",
29
30
  "app.plugin.js",
@@ -31,6 +32,9 @@
31
32
  "!android/.gradle",
32
33
  "!android/local.properties",
33
34
  "!ios/build",
35
+ "!harmony/**/build",
36
+ "!harmony/**/oh_modules",
37
+ "!harmony/**/oh-package-lock.json5",
34
38
  "!**/__tests__",
35
39
  "!**/__fixtures__",
36
40
  "!**/__mocks__",
@@ -64,13 +68,17 @@
64
68
  "clean": "del-cli android/build example/ios example/android lib",
65
69
  "build": "bob build && node scripts/inject-version.js",
66
70
  "build:prod": "bob build && node scripts/minify-prod.js",
71
+ "codegen:harmony": "node scripts/rnoh-codegen.js",
67
72
  "prepack": "yarn build:prod",
68
73
  "release": "release-it --only-version"
69
74
  },
70
75
  "keywords": [
71
76
  "react-native",
72
77
  "ios",
73
- "android"
78
+ "android",
79
+ "harmonyos",
80
+ "harmony",
81
+ "ohos"
74
82
  ],
75
83
  "author": "guangli.fj <guangli.fj@alibaba-inc.com>",
76
84
  "license": "MIT",
@@ -85,6 +93,7 @@
85
93
  "@eslint/js": "^9.22.0",
86
94
  "@evilmartians/lefthook": "^1.5.0",
87
95
  "@react-native-community/cli": "15.0.0-alpha.2",
96
+ "@react-native-oh/react-native-harmony-cli": "0.77.71",
88
97
  "@react-native/babel-preset": "0.79.2",
89
98
  "@react-native/eslint-config": "^0.78.0",
90
99
  "@release-it/conventional-changelog": "^9.0.2",
@@ -112,7 +121,8 @@
112
121
  "react-native": ">=0.68.0"
113
122
  },
114
123
  "workspaces": [
115
- "example"
124
+ "example",
125
+ "example-harmony"
116
126
  ],
117
127
  "packageManager": "yarn@3.6.1",
118
128
  "commitlint": {
@@ -175,5 +185,14 @@
175
185
  "android": {
176
186
  "javaPackageName": "com.rumsdkreactnative"
177
187
  }
188
+ },
189
+ "harmony": {
190
+ "alias": "@arms/rum-reactnative",
191
+ "codegenConfig": {
192
+ "version": 2,
193
+ "specPaths": [
194
+ "./src"
195
+ ]
196
+ }
178
197
  }
179
198
  }
@@ -80,18 +80,30 @@ export interface Spec extends TurboModule {
80
80
  * 若未找到则降级到 Legacy Bridge 的 NativeModules(RN 0.68-0.70 未开启 New Arch 时),
81
81
  * 若均不可用则返回一组空实现兜底。
82
82
  *
83
- * 使用非强制的 `TurboModuleRegistry.get`(而非 `getEnforcing`),避免在原生
84
- * 二进制未注册该模块时于「模块加载阶段」直接抛异常——那会连锁导致整个 JS
85
- * bundle 评估失败(表现为所有路由丢失 default export、App 白屏)。
83
+ * iOS / Android 的 TurboModuleRegistry.get 在模块缺失时返回 null;
84
+ * 但 RNOH(鸿蒙)的 TurboModuleProxy 在原生侧未注册模块时会直接抛异常
85
+ * ("Couldn't find Turbo Module on the ArkTs side"),若不捕获会导致整个
86
+ * JS bundle 评估失败(App 白屏)。因此这里用 try/catch 包裹,异常时同样降级。
86
87
  *
87
88
  * 当原生模块缺失时(通常是新增原生代码后未重新编译原生 App,只重跑了 Metro),
88
89
  * 返回一组空实现兜底:崩溃采集与原生设备信息降级为不可用,但 PV / 行为 / API /
89
90
  * JS 异常等纯 JS 能力不受影响。需重新构建原生工程(如 `expo run:ios` /
90
91
  * `pod install` + 重新编译)后崩溃采集才会真正生效。
91
92
  */
92
- const nativeModule =
93
- TurboModuleRegistry.get<Spec>('RumSdkReactnative') ??
94
- (NativeModules.RumSdkReactnative as Spec | undefined);
93
+ let nativeModule: Spec | undefined;
94
+ try {
95
+ nativeModule =
96
+ TurboModuleRegistry.get<Spec>('RumSdkReactnative') ??
97
+ (NativeModules.RumSdkReactnative as Spec | undefined);
98
+ } catch (err) {
99
+ console.warn(
100
+ "[rum] Native module 'RumSdkReactnative' not found in the native binary. " +
101
+ 'Crash reporting and native device info are disabled. ' +
102
+ 'Rebuild the native app (e.g. `expo run:ios` / `expo run:android`, ' +
103
+ 'or `pod install` + rebuild) so the module gets registered.',
104
+ err
105
+ );
106
+ }
95
107
 
96
108
  if (!nativeModule) {
97
109
  console.warn(