@arms/rum-reactnative 0.1.2 → 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.
- package/README.md +79 -1
- package/RumSdkReactnative.podspec +28 -0
- package/android/build.gradle +83 -0
- package/android/gradle.properties +6 -0
- package/android/src/main/AndroidManifest.xml +13 -0
- package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativeModule.kt +512 -0
- package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativePackage.kt +33 -0
- package/android/src/main/java/com/rumsdkreactnative/crash/CrashContextManager.kt +157 -0
- package/android/src/main/java/com/rumsdkreactnative/crash/CrashHandler.kt +444 -0
- package/android/src/main/java/com/rumsdkreactnative/crash/CrashInitProvider.kt +50 -0
- package/android/src/main/java/com/rumsdkreactnative/crash/NdkCrashHandler.kt +66 -0
- package/android/src/main/jni/CMakeLists.txt +21 -0
- package/android/src/main/jni/rum_backtrace.c +144 -0
- package/android/src/main/jni/rum_crash_handler.c +200 -0
- package/android/src/main/jni/rum_crash_writer.c +442 -0
- package/android/src/main/jni/rum_module_info.c +316 -0
- package/android/src/main/jni/rum_module_info.h +54 -0
- package/android/src/main/jni/rum_test_crash.cpp +55 -0
- package/app.plugin.js +11 -0
- package/docs/ReactNative SDK/351/205/215/347/275/256/345/217/202/350/200/203.md" +671 -0
- package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +12 -0
- package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +238 -0
- package/ios/PrivacyInfo.xcprivacy +93 -0
- package/ios/RumCrashReporter.h +38 -0
- package/ios/RumCrashReporter.mm +861 -0
- package/ios/RumSdkReactnative.h +5 -0
- package/ios/RumSdkReactnative.mm +291 -0
- package/ios/fishhook/fishhook.c +264 -0
- package/ios/fishhook/fishhook.h +76 -0
- package/lib/commonjs/NativeRumSdkReactnative.js +50 -0
- package/lib/commonjs/collector/action/index.js +108 -0
- package/lib/commonjs/collector/exception/crash.js +148 -0
- package/lib/commonjs/collector/exception/index.js +238 -0
- package/lib/commonjs/collector/index.js +42 -0
- package/lib/commonjs/collector/resource/api.js +286 -0
- package/lib/commonjs/collector/view/perf.js +79 -0
- package/lib/commonjs/collector/view/pv.js +88 -0
- package/lib/commonjs/expoConfigPlugin.js +37 -0
- package/lib/commonjs/index.js +29 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/plugin.js +47 -0
- package/lib/commonjs/processor/default-processor.js +27 -0
- package/lib/commonjs/processor/session-processor.js +47 -0
- package/lib/commonjs/reporter/index.js +148 -0
- package/lib/commonjs/reporter/monitor-reporter.js +43 -0
- package/lib/commonjs/shell.js +91 -0
- package/lib/commonjs/types/client.js +6 -0
- package/lib/commonjs/types/crash.js +37 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/commonjs/utils/action.js +305 -0
- package/lib/commonjs/utils/api.js +83 -0
- package/lib/commonjs/utils/base.js +95 -0
- package/lib/commonjs/utils/crash.js +146 -0
- package/lib/commonjs/utils/platform.js +162 -0
- package/lib/commonjs/utils/session.js +158 -0
- package/lib/commonjs/utils/url.js +59 -0
- package/lib/commonjs/utils/view.js +93 -0
- package/lib/module/NativeRumSdkReactnative.js +47 -0
- package/lib/module/collector/action/index.js +45 -10
- package/lib/module/collector/exception/crash.js +143 -0
- package/lib/module/collector/exception/index.js +144 -46
- package/lib/module/collector/index.js +8 -0
- package/lib/module/collector/resource/api.js +6 -6
- package/lib/module/collector/view/pv.js +11 -0
- package/lib/module/expoConfigPlugin.js +33 -0
- package/lib/module/index.js +1 -0
- package/lib/module/processor/session-processor.js +22 -0
- package/lib/module/reporter/index.js +102 -16
- package/lib/module/reporter/monitor-reporter.js +38 -0
- package/lib/module/shell.js +11 -7
- package/lib/module/types/crash.js +33 -0
- package/lib/module/utils/action.js +299 -0
- package/lib/module/utils/crash.js +141 -0
- package/lib/module/utils/platform.js +124 -72
- package/lib/module/utils/session.js +23 -4
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/NativeRumSdkReactnative.d.ts +49 -0
- package/lib/typescript/{src → commonjs/src}/collector/action/index.d.ts +6 -0
- package/lib/typescript/commonjs/src/collector/exception/crash.d.ts +28 -0
- package/lib/typescript/{src → commonjs/src}/collector/exception/index.d.ts +7 -0
- package/lib/typescript/commonjs/src/collector/index.d.ts +6 -0
- package/lib/typescript/commonjs/src/expoConfigPlugin.d.ts +28 -0
- package/lib/typescript/commonjs/src/index.d.ts +6 -0
- package/lib/typescript/{src → commonjs/src}/processor/session-processor.d.ts +2 -0
- package/lib/typescript/{src → commonjs/src}/reporter/index.d.ts +3 -1
- package/lib/typescript/commonjs/src/reporter/monitor-reporter.d.ts +8 -0
- package/lib/typescript/{src → commonjs/src}/shell.d.ts +11 -0
- package/lib/typescript/commonjs/src/types/crash.d.ts +95 -0
- package/lib/typescript/commonjs/src/utils/action.d.ts +63 -0
- package/lib/typescript/commonjs/src/utils/crash.d.ts +12 -0
- package/lib/typescript/commonjs/src/utils/platform.d.ts +22 -0
- package/lib/typescript/{src → commonjs/src}/utils/session.d.ts +4 -0
- package/lib/typescript/module/src/NativeRumSdkReactnative.d.ts +49 -0
- package/lib/typescript/module/src/collector/action/index.d.ts +21 -0
- package/lib/typescript/module/src/collector/exception/crash.d.ts +28 -0
- package/lib/typescript/module/src/collector/exception/index.d.ts +32 -0
- package/lib/typescript/module/src/collector/index.d.ts +6 -0
- package/lib/typescript/module/src/collector/resource/api.d.ts +21 -0
- package/lib/typescript/module/src/collector/view/perf.d.ts +1 -0
- package/lib/typescript/module/src/collector/view/pv.d.ts +16 -0
- package/lib/typescript/module/src/expoConfigPlugin.d.ts +28 -0
- package/lib/typescript/module/src/index.d.ts +6 -0
- package/lib/typescript/module/src/plugin.d.ts +3 -0
- package/lib/typescript/module/src/processor/default-processor.d.ts +6 -0
- package/lib/typescript/module/src/processor/session-processor.d.ts +11 -0
- package/lib/typescript/module/src/reporter/index.d.ts +18 -0
- package/lib/typescript/module/src/reporter/monitor-reporter.d.ts +8 -0
- package/lib/typescript/module/src/shell.d.ts +57 -0
- package/lib/typescript/module/src/types/client.d.ts +27 -0
- package/lib/typescript/module/src/types/crash.d.ts +95 -0
- package/lib/typescript/module/src/types/index.d.ts +118 -0
- package/lib/typescript/module/src/utils/action.d.ts +63 -0
- package/lib/typescript/module/src/utils/api.d.ts +59 -0
- package/lib/typescript/module/src/utils/base.d.ts +8 -0
- package/lib/typescript/module/src/utils/crash.d.ts +12 -0
- package/lib/typescript/module/src/utils/platform.d.ts +22 -0
- package/lib/typescript/module/src/utils/session.d.ts +41 -0
- package/lib/typescript/module/src/utils/url.d.ts +17 -0
- package/lib/typescript/module/src/utils/view.d.ts +13 -0
- package/package.json +51 -28
- package/lib/module/collector/action/index.js.map +0 -1
- package/lib/module/collector/exception/index.js.map +0 -1
- package/lib/module/collector/resource/api.js.map +0 -1
- package/lib/module/collector/view/perf.js.map +0 -1
- package/lib/module/collector/view/pv.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/plugin.js.map +0 -1
- package/lib/module/processor/default-processor.js.map +0 -1
- package/lib/module/processor/session-processor.js.map +0 -1
- package/lib/module/reporter/index.js.map +0 -1
- package/lib/module/shell.js.map +0 -1
- package/lib/module/types/client.js.map +0 -1
- package/lib/module/types/index.js.map +0 -1
- package/lib/module/utils/api.js.map +0 -1
- package/lib/module/utils/base.js.map +0 -1
- package/lib/module/utils/platform.js.map +0 -1
- package/lib/module/utils/session.js.map +0 -1
- package/lib/module/utils/url.js.map +0 -1
- package/lib/module/utils/view.js.map +0 -1
- package/lib/typescript/src/collector/action/index.d.ts.map +0 -1
- package/lib/typescript/src/collector/exception/index.d.ts.map +0 -1
- package/lib/typescript/src/collector/resource/api.d.ts.map +0 -1
- package/lib/typescript/src/collector/view/perf.d.ts.map +0 -1
- package/lib/typescript/src/collector/view/pv.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts +0 -4
- package/lib/typescript/src/index.d.ts.map +0 -1
- package/lib/typescript/src/plugin.d.ts.map +0 -1
- package/lib/typescript/src/processor/default-processor.d.ts.map +0 -1
- package/lib/typescript/src/processor/session-processor.d.ts.map +0 -1
- package/lib/typescript/src/reporter/index.d.ts.map +0 -1
- package/lib/typescript/src/shell.d.ts.map +0 -1
- package/lib/typescript/src/types/client.d.ts.map +0 -1
- package/lib/typescript/src/types/index.d.ts.map +0 -1
- package/lib/typescript/src/utils/api.d.ts.map +0 -1
- package/lib/typescript/src/utils/base.d.ts.map +0 -1
- package/lib/typescript/src/utils/platform.d.ts +0 -15
- package/lib/typescript/src/utils/platform.d.ts.map +0 -1
- package/lib/typescript/src/utils/session.d.ts.map +0 -1
- package/lib/typescript/src/utils/url.d.ts.map +0 -1
- package/lib/typescript/src/utils/view.d.ts.map +0 -1
- /package/lib/typescript/{src → commonjs/src}/collector/resource/api.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/collector/view/perf.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/collector/view/pv.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/plugin.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/processor/default-processor.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/types/client.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/types/index.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/utils/api.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/utils/base.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/utils/url.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/utils/view.d.ts +0 -0
- /package/lib/typescript/{package.json → module/package.json} +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { RumEventType, logger } from '@arms/rum-core';
|
|
4
|
+
/**
|
|
5
|
+
* 将原生崩溃数据转换为 RumEvent 异常事件,对齐存储模型 Exception 表的
|
|
6
|
+
* Attributes(session/view/exception 基础信息)+ Metadata(堆栈、快照等)字段。
|
|
7
|
+
*/
|
|
8
|
+
export function convertCrashToRumEvent(crashData) {
|
|
9
|
+
const exceptionName = crashData.signal?.name || crashData.exception?.class_name || 'NativeCrash';
|
|
10
|
+
const exceptionMessage = buildMessage(crashData);
|
|
11
|
+
// NDK 崩溃的 frames 在顶层,Java 崩溃的 frames 在 crashed_thread 内
|
|
12
|
+
const frames = crashData.frames || crashData.crashed_thread?.frames || [];
|
|
13
|
+
const stack = formatStack(frames);
|
|
14
|
+
// 兼容旧版字符串格式:frames[0] 可能是字符串
|
|
15
|
+
const firstFrame = frames[0];
|
|
16
|
+
const file = typeof firstFrame === 'object' ? firstFrame?.library || '' : '';
|
|
17
|
+
|
|
18
|
+
// 从第一帧提取 line,原生崩溃无列号概念,column 固定为 0
|
|
19
|
+
let line = 0;
|
|
20
|
+
let column = 0;
|
|
21
|
+
if (frames.length > 0) {
|
|
22
|
+
const topFrame = frames[0];
|
|
23
|
+
if (topFrame && typeof topFrame === 'object' && typeof topFrame.line === 'number') {
|
|
24
|
+
line = topFrame.line;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const view = {
|
|
28
|
+
id: crashData.context?.view_id || '',
|
|
29
|
+
name: crashData.context?.view_name || ''
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// 防御性转换:NDK 旧版本使用秒级 timestamp,新版本已改为毫秒
|
|
33
|
+
// 如果 timestamp 小于 1e12(约 2001 年的毫秒值),说明是秒级,需乘以 1000
|
|
34
|
+
let timestamp = crashData.timestamp || Date.now();
|
|
35
|
+
if (timestamp < 1e12) {
|
|
36
|
+
timestamp = timestamp * 1000;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// binary_images uuid 字段兼容:统一为 uuid,保留原 build_id/debug_id
|
|
40
|
+
const rawImages = crashData.binary_images || [];
|
|
41
|
+
const normalizedImages = rawImages.map(img => {
|
|
42
|
+
if (!img.uuid && (img.build_id || img.debug_id)) {
|
|
43
|
+
return {
|
|
44
|
+
...img,
|
|
45
|
+
uuid: img.build_id || img.debug_id
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return img;
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
event_type: RumEventType.EXCEPTION,
|
|
52
|
+
timestamp,
|
|
53
|
+
// 设置崩溃时的原始 session_id,新版 rum-core dispatchEvents 会按
|
|
54
|
+
// session_id 分组上报,不再丢弃非当前 session 的事件
|
|
55
|
+
session_id: crashData.context?.session_id,
|
|
56
|
+
view,
|
|
57
|
+
times: 1,
|
|
58
|
+
// === Attributes ===
|
|
59
|
+
source: 'event',
|
|
60
|
+
type: 'crash',
|
|
61
|
+
name: exceptionName,
|
|
62
|
+
message: exceptionMessage,
|
|
63
|
+
file,
|
|
64
|
+
line,
|
|
65
|
+
column,
|
|
66
|
+
// === Metadata ===
|
|
67
|
+
stack,
|
|
68
|
+
caused_by: crashData.exception?.message || (crashData.signal ? `${crashData.signal.name || ''} at ${crashData.signal.fault_address || ''}` : ''),
|
|
69
|
+
binary_images: JSON.stringify(normalizedImages),
|
|
70
|
+
snapshots: JSON.stringify({
|
|
71
|
+
device: crashData.device || {},
|
|
72
|
+
registers: crashData.registers || {},
|
|
73
|
+
app: crashData.app || {},
|
|
74
|
+
crash_context: crashData.context || {},
|
|
75
|
+
// NDK 特有字段透传:arch 决定后端符号化的寄存器解释方式和地址宽度;
|
|
76
|
+
// pid 用于关联系统日志;signal.number 为 NDK 写入的原始信号编号
|
|
77
|
+
arch: crashData.arch || '',
|
|
78
|
+
pid: crashData.pid,
|
|
79
|
+
signal_number: crashData.signal?.number,
|
|
80
|
+
// 崩溃线程 ID:NDK 崩溃使用顶层 tid,Java 崩溃使用 crashed_thread.id
|
|
81
|
+
thread_id: String(crashData.crashed_thread?.id ?? crashData.tid ?? ''),
|
|
82
|
+
// 崩溃机制信息放入 snapshots 容器
|
|
83
|
+
...(crashData.mechanism ? {
|
|
84
|
+
mechanism: crashData.mechanism
|
|
85
|
+
} : {})
|
|
86
|
+
})
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function buildMessage(crashData) {
|
|
90
|
+
if (crashData.exception?.message) {
|
|
91
|
+
return crashData.exception.message;
|
|
92
|
+
}
|
|
93
|
+
const sig = crashData.signal;
|
|
94
|
+
if (sig) {
|
|
95
|
+
const addr = sig.fault_address || '';
|
|
96
|
+
return `${sig.name || ''} (${sig.code ?? ''})${addr ? ' at ' + addr : ''}`.trim();
|
|
97
|
+
}
|
|
98
|
+
return 'Native crash';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 格式化堆栈为可读字符串。
|
|
103
|
+
* 兼容两种 frames 格式:
|
|
104
|
+
* - 新版(对象数组):[{address, library, symbol, offset}, ...]
|
|
105
|
+
* - 旧版(字符串数组):["0x1234", ...](旧版 NDK 崩溃文件)
|
|
106
|
+
*/
|
|
107
|
+
function formatStack(frames) {
|
|
108
|
+
if (!frames || frames.length === 0) return '';
|
|
109
|
+
return frames.map((frame, index) => {
|
|
110
|
+
// 兼容旧版 NDK 的纯字符串格式
|
|
111
|
+
if (typeof frame === 'string') {
|
|
112
|
+
return `#${index} <unknown> ${frame} ()`;
|
|
113
|
+
}
|
|
114
|
+
// 截断标记帧:双侧截断时插入的中间标记
|
|
115
|
+
if (frame.truncated) {
|
|
116
|
+
const count = frame.omitted_count ?? -1;
|
|
117
|
+
return `#${index} ... ${count} frames omitted ...`;
|
|
118
|
+
}
|
|
119
|
+
const library = frame.library || '<unknown>';
|
|
120
|
+
const symbol = frame.symbol || '';
|
|
121
|
+
const address = frame.address || '';
|
|
122
|
+
const offset = frame.offset || '';
|
|
123
|
+
if (symbol) {
|
|
124
|
+
return `#${index} ${library} ${symbol} + ${offset}`;
|
|
125
|
+
}
|
|
126
|
+
return `#${index} ${library} ${address} (${offset})`;
|
|
127
|
+
}).join('\n');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 安全调用原生桥方法,异常时静默降级。
|
|
132
|
+
*/
|
|
133
|
+
export async function safeNativeCall(fn, label) {
|
|
134
|
+
try {
|
|
135
|
+
return await fn();
|
|
136
|
+
} catch (e) {
|
|
137
|
+
logger.warn('native-bridge', `${label || 'native call'} failed`, e);
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=crash.js.map
|
|
@@ -1,90 +1,136 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { AppType } from '@arms/rum-core';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export const VERSION = 'test';
|
|
4
|
+
import { Dimensions, Platform } from 'react-native';
|
|
5
|
+
import NativeRumSdkReactnative from "../NativeRumSdkReactnative.js";
|
|
6
|
+
const _pkg = {"version":"0.1.3-beta.0"};
|
|
7
|
+
export const VERSION = _pkg.version;
|
|
9
8
|
|
|
10
9
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
10
|
|
|
12
11
|
export const appName = 'react-native';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 从 react-native/package.json 获取 RN 运行时版本号,
|
|
15
|
+
* 用于 os.container_version。
|
|
16
|
+
*/
|
|
17
|
+
function getReactNativeVersion() {
|
|
18
|
+
try {
|
|
19
|
+
const pkg = require('react-native/package.json');
|
|
20
|
+
return pkg.version ?? '';
|
|
21
|
+
} catch {
|
|
22
|
+
const info = Platform.constants?.reactNativeVersion;
|
|
23
|
+
if (info) {
|
|
24
|
+
return `${info.major}.${info.minor}.${info.patch}`;
|
|
25
|
+
}
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// region Storage
|
|
31
|
+
|
|
13
32
|
export function getStorage(key) {
|
|
14
|
-
return
|
|
33
|
+
return NativeRumSdkReactnative.getItem(key);
|
|
15
34
|
}
|
|
16
35
|
export function setStorage(key, data) {
|
|
17
|
-
return
|
|
36
|
+
return NativeRumSdkReactnative.setItem(key, data);
|
|
37
|
+
}
|
|
38
|
+
export function removeStorage(key) {
|
|
39
|
+
return NativeRumSdkReactnative.removeItem(key);
|
|
40
|
+
}
|
|
41
|
+
export function clearStorage() {
|
|
42
|
+
return NativeRumSdkReactnative.clear();
|
|
43
|
+
}
|
|
44
|
+
export function getAllStorageKeys() {
|
|
45
|
+
return NativeRumSdkReactnative.getAllKeys();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// endregion
|
|
49
|
+
|
|
50
|
+
// region Device Info
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 调用原生桥采集设备信息。
|
|
54
|
+
* 失败时静默降级到 JS Platform API 填充基础字段。
|
|
55
|
+
*/
|
|
56
|
+
async function fetchDeviceInfo() {
|
|
57
|
+
try {
|
|
58
|
+
return await NativeRumSdkReactnative.getDeviceInfo();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.warn('[rum] getDeviceInfo failed, falling back to JS defaults', err);
|
|
61
|
+
return {
|
|
62
|
+
os_type: Platform.OS === 'ios' ? 'iOS' : 'Android',
|
|
63
|
+
os_version: String(Platform.Version ?? '')
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 模块级缓存,首次调用 fixAttrs 时懒初始化,避免模块加载时原生桥尚未就绪。
|
|
70
|
+
* null 表示尚未触发采集。
|
|
71
|
+
*/
|
|
72
|
+
let _cachedDeviceInfo = null;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 获取设备信息(懒初始化,仅触发一次原生桥调用)。
|
|
76
|
+
*/
|
|
77
|
+
function getDeviceInfo() {
|
|
78
|
+
if (!_cachedDeviceInfo) {
|
|
79
|
+
_cachedDeviceInfo = fetchDeviceInfo();
|
|
80
|
+
}
|
|
81
|
+
return _cachedDeviceInfo;
|
|
18
82
|
}
|
|
19
83
|
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// },
|
|
28
|
-
// fail: function (res) {
|
|
29
|
-
// resolve(undefined)
|
|
30
|
-
// }
|
|
31
|
-
// });
|
|
32
|
-
// } catch (e) {
|
|
33
|
-
// resolve(undefined)
|
|
34
|
-
// }
|
|
35
|
-
// })
|
|
36
|
-
// }
|
|
37
|
-
|
|
38
|
-
export const fixAttrs = function (bundle) {
|
|
84
|
+
// endregion
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 将设备 / 系统 / 网络等公共属性注入 bundle。
|
|
88
|
+
* 在 Reporter.request 中被调用;首次调用时懒触发设备信息采集。
|
|
89
|
+
*/
|
|
90
|
+
export const fixAttrs = async function (bundle) {
|
|
39
91
|
if (!bundle) return;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// os.container_version = `${rn.major}.${rn.minor}.${rn.patch}`;
|
|
79
|
-
// } catch (e) {
|
|
80
|
-
// //
|
|
81
|
-
// }
|
|
92
|
+
const native = await getDeviceInfo();
|
|
93
|
+
|
|
94
|
+
// device.*
|
|
95
|
+
const device = {
|
|
96
|
+
id: native.device_id,
|
|
97
|
+
type: native.device_type,
|
|
98
|
+
brand: native.device_brand,
|
|
99
|
+
model: native.device_model,
|
|
100
|
+
name: native.device_name
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// os.*
|
|
104
|
+
const rnVersion = getReactNativeVersion();
|
|
105
|
+
const os = {
|
|
106
|
+
type: native.os_type ?? (Platform.OS === 'ios' ? 'iOS' : 'Android'),
|
|
107
|
+
version: native.os_version ?? String(Platform.Version ?? ''),
|
|
108
|
+
container: appName,
|
|
109
|
+
container_version: rnVersion || undefined
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// viewport:优先使用原生采集的物理像素,兜底 JS Dimensions(逻辑像素)
|
|
113
|
+
let viewport;
|
|
114
|
+
if (native.viewport_width && native.viewport_height) {
|
|
115
|
+
viewport = {
|
|
116
|
+
width: native.viewport_width,
|
|
117
|
+
height: native.viewport_height
|
|
118
|
+
};
|
|
119
|
+
} else {
|
|
120
|
+
try {
|
|
121
|
+
const screen = Dimensions.get('screen');
|
|
122
|
+
viewport = {
|
|
123
|
+
width: Math.round(screen.width),
|
|
124
|
+
height: Math.round(screen.height)
|
|
125
|
+
};
|
|
126
|
+
} catch {
|
|
127
|
+
// 忽略
|
|
128
|
+
}
|
|
129
|
+
}
|
|
82
130
|
bundle.app.type = AppType.reactnative;
|
|
131
|
+
bundle.app.package = bundle.app.package ?? native.app_package;
|
|
132
|
+
bundle.app.version = bundle.app.version ?? native.app_version;
|
|
83
133
|
bundle._v = VERSION;
|
|
84
|
-
bundle.net = {
|
|
85
|
-
...net,
|
|
86
|
-
...bundle.net
|
|
87
|
-
};
|
|
88
134
|
bundle.device = {
|
|
89
135
|
...device,
|
|
90
136
|
...bundle.device
|
|
@@ -93,6 +139,12 @@ export const fixAttrs = function (bundle) {
|
|
|
93
139
|
...os,
|
|
94
140
|
...bundle.os
|
|
95
141
|
};
|
|
142
|
+
if (viewport) {
|
|
143
|
+
bundle.viewport = {
|
|
144
|
+
...bundle.viewport,
|
|
145
|
+
...viewport
|
|
146
|
+
};
|
|
147
|
+
}
|
|
96
148
|
return bundle;
|
|
97
149
|
};
|
|
98
150
|
//# sourceMappingURL=platform.js.map
|
|
@@ -6,11 +6,21 @@ import { getCurView } from "./view.js";
|
|
|
6
6
|
import { getStorage, setStorage } from "./platform.js";
|
|
7
7
|
|
|
8
8
|
// 存储userID的键名
|
|
9
|
-
const USER_ID = '
|
|
9
|
+
const USER_ID = '_rum_uid';
|
|
10
|
+
// 旧版键名(用于迁移)
|
|
11
|
+
const LEGACY_USER_ID = '_arms_uid';
|
|
10
12
|
// 存储session
|
|
11
|
-
// const RUM_SESSION = '
|
|
13
|
+
// const RUM_SESSION = '_rum_session';
|
|
12
14
|
|
|
13
15
|
export class RumSession {
|
|
16
|
+
/** 平台类型标识 */
|
|
17
|
+
appType = 'reactnative';
|
|
18
|
+
|
|
19
|
+
/** SDK 版本号(延迟导入避免循环依赖) */
|
|
20
|
+
get sdkVersion() {
|
|
21
|
+
return require('./platform').VERSION;
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
// @ts-ignore
|
|
15
25
|
|
|
16
26
|
// private sessionId = '';
|
|
@@ -54,8 +64,8 @@ export class RumSession {
|
|
|
54
64
|
let info = {
|
|
55
65
|
sessionId: sid,
|
|
56
66
|
sampled: sampled !== '0',
|
|
57
|
-
startTime: parseInt(startTime || '') || 0,
|
|
58
|
-
lastTime: parseInt(lastTime || '') || 0
|
|
67
|
+
startTime: parseInt(startTime || '', 10) || 0,
|
|
68
|
+
lastTime: parseInt(lastTime || '', 10) || 0
|
|
59
69
|
};
|
|
60
70
|
if (!this.checkSession(info)) {
|
|
61
71
|
info = this.resetSession();
|
|
@@ -71,6 +81,15 @@ export class RumSession {
|
|
|
71
81
|
}
|
|
72
82
|
async initUser() {
|
|
73
83
|
this.userId = await getStorage(USER_ID);
|
|
84
|
+
// 迁移旧版键名 _arms_uid → _rum_uid
|
|
85
|
+
if (!this.userId) {
|
|
86
|
+
const legacyId = await getStorage(LEGACY_USER_ID);
|
|
87
|
+
if (legacyId) {
|
|
88
|
+
this.userId = legacyId;
|
|
89
|
+
await setStorage(USER_ID, this.userId);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
74
93
|
if (!this.userId) {
|
|
75
94
|
this.userId = `uid_${generateSpanId(16, 36)}`;
|
|
76
95
|
await setStorage(USER_ID, this.userId);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
/**
|
|
3
|
+
* 原生设备信息,对应存储模型中的公共属性:
|
|
4
|
+
* - device.* (id / type / brand / model / name)
|
|
5
|
+
* - os.* (type / version / container / container_version)
|
|
6
|
+
* - app.package
|
|
7
|
+
* - viewport.width / viewport.height
|
|
8
|
+
*/
|
|
9
|
+
export interface NativeDeviceInfo {
|
|
10
|
+
device_id?: string;
|
|
11
|
+
device_type?: string;
|
|
12
|
+
device_brand?: string;
|
|
13
|
+
device_model?: string;
|
|
14
|
+
device_name?: string;
|
|
15
|
+
os_type?: string;
|
|
16
|
+
os_version?: string;
|
|
17
|
+
app_package?: string;
|
|
18
|
+
app_version?: string;
|
|
19
|
+
viewport_width?: number;
|
|
20
|
+
viewport_height?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface Spec extends TurboModule {
|
|
23
|
+
getItem(key: string): Promise<string | null>;
|
|
24
|
+
setItem(key: string, value: string): Promise<void>;
|
|
25
|
+
removeItem(key: string): Promise<void>;
|
|
26
|
+
clear(): Promise<void>;
|
|
27
|
+
getAllKeys(): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* 采集原生平台设备信息,仅在初始化时调用一次。
|
|
30
|
+
*/
|
|
31
|
+
getDeviceInfo(): Promise<NativeDeviceInfo>;
|
|
32
|
+
/** 获取待上报的崩溃报告列表(下次启动时调用) */
|
|
33
|
+
getPendingCrashes(): Promise<string>;
|
|
34
|
+
/** 清除已上报的崩溃文件 */
|
|
35
|
+
clearCrashReports(crashIds: string): Promise<void>;
|
|
36
|
+
/** 清除所有崩溃报告文件(用于清理无 crash_id 的旧版文件) */
|
|
37
|
+
clearAllCrashReports(): Promise<void>;
|
|
38
|
+
/** 清理过期和超限的崩溃文件(maxFiles 上限,maxAgeMs 过期时间) */
|
|
39
|
+
cleanupOldCrashes(maxFiles: number, maxAgeMs: number): Promise<void>;
|
|
40
|
+
/** 查询上次运行是否发生过崩溃 */
|
|
41
|
+
crashedLastRun(): Promise<boolean>;
|
|
42
|
+
/** 更新崩溃上下文快照(session/view 变更时调用) */
|
|
43
|
+
updateCrashContext(context: string): void;
|
|
44
|
+
/** 触发测试崩溃(仅用于开发调试,调用后 App 立即崩溃) */
|
|
45
|
+
triggerTestCrash(crashType: string): void;
|
|
46
|
+
}
|
|
47
|
+
declare const _default: Spec;
|
|
48
|
+
export default _default;
|
|
49
|
+
//# sourceMappingURL=NativeRumSdkReactnative.d.ts.map
|
|
@@ -6,9 +6,15 @@ export default class ActionCollector implements ICollector {
|
|
|
6
6
|
sendEvent?: (payload: RumEvent) => void;
|
|
7
7
|
events: string[];
|
|
8
8
|
lastEvent?: RumActionEvent;
|
|
9
|
+
lastActionId?: string;
|
|
9
10
|
timer: any;
|
|
10
11
|
setup(ctx: IContext, sendEvent: (payload: RumEvent) => void): void;
|
|
11
12
|
onEvent: (e: any) => void;
|
|
13
|
+
/**
|
|
14
|
+
* 组装热力图相关的 target 信息(selector/宽高/可交互性/可信度)。
|
|
15
|
+
* 当没有任何字段时返回 undefined,避免上报空对象。
|
|
16
|
+
*/
|
|
17
|
+
private buildTarget;
|
|
12
18
|
sendAction: () => void;
|
|
13
19
|
destroy(): void;
|
|
14
20
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ICollector, IContext, SendEventFn } from '@arms/rum-core';
|
|
2
|
+
/**
|
|
3
|
+
* 崩溃采集器(Exception 的子类型):
|
|
4
|
+
* 1. 初始化时读取上次运行写入的原生崩溃文件,转换为 RumEvent 通过标准管线上报;
|
|
5
|
+
* 2. 通过 ctx.emitter 订阅上下文变更事件,同步到原生侧
|
|
6
|
+
* (用于下一次启动时崩溃报告携带正确上下文)。
|
|
7
|
+
*/
|
|
8
|
+
export default class CrashCollector implements ICollector {
|
|
9
|
+
name: string;
|
|
10
|
+
private ctx?;
|
|
11
|
+
private sendEvent?;
|
|
12
|
+
private initialized;
|
|
13
|
+
/** 已上报待确认(ack)的 crash_id,成功后才删文件 */
|
|
14
|
+
private pendingAckIds;
|
|
15
|
+
setup(ctx: IContext, sendEvent: SendEventFn): void;
|
|
16
|
+
private processPendingCrashes;
|
|
17
|
+
/** 兜底清理:删除过期和超限的崩溃文件,防止存储耗尽 */
|
|
18
|
+
private cleanupOldCrashes;
|
|
19
|
+
private onCrashContextChange;
|
|
20
|
+
/**
|
|
21
|
+
* reporter 上报确认回调:
|
|
22
|
+
* - 成功:删除对应 crash_id 的崩溃文件(确保上报成功后才删,不丢数据);
|
|
23
|
+
* - 失败:保留文件,下次启动重试,仅从内存待确认集合中移除。
|
|
24
|
+
*/
|
|
25
|
+
private onCrashReportAck;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=crash.d.ts.map
|
|
@@ -3,9 +3,16 @@ export default class ExceptionCollector implements ICollector {
|
|
|
3
3
|
name: string;
|
|
4
4
|
ctx?: IContext;
|
|
5
5
|
sendEvent?: (payload: RumEvent) => void;
|
|
6
|
+
private installed;
|
|
7
|
+
/** fatal 去重保护:防止连续 fatal error 重复上报 */
|
|
8
|
+
private handlingFatal;
|
|
9
|
+
/** 防止 errorHandle 内部 console.error 形成循环 */
|
|
10
|
+
private inErrorHandle;
|
|
6
11
|
private origin;
|
|
7
12
|
setup(ctx: IContext, sendEvent: (payload: RumEvent) => void): void;
|
|
8
13
|
hackOrigin(): void;
|
|
14
|
+
/** JSC 引擎 Promise rejection 兜底方案 */
|
|
15
|
+
private setupJSCPromiseRejection;
|
|
9
16
|
onError: (e: Error | string, isFatal?: boolean) => void;
|
|
10
17
|
onUnhandled: (_id: string, error: unknown) => void;
|
|
11
18
|
errorHandle: (error: any, source?: string) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as PvCollector } from './view/pv';
|
|
2
|
+
export { default as ExceptionCollector } from './exception/index';
|
|
3
|
+
export { default as CrashCollector } from './exception/crash';
|
|
4
|
+
export { default as ApiCollector } from './resource/api';
|
|
5
|
+
export { default as ActionCollector } from './action/index';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expo config plugin for @arms/rum-reactnative.
|
|
3
|
+
*
|
|
4
|
+
* 在 app.config 中声明后,将 SDK 配置写入 `expoConfig.extra.rumSdk`,运行时可通过
|
|
5
|
+
* `Constants.expoConfig?.extra?.rumSdk` 读取,避免在 JS 入口硬编码 endpoint。
|
|
6
|
+
*
|
|
7
|
+
* app.config.ts 示例:
|
|
8
|
+
* plugins: [['@arms/rum-reactnative', { endpoint: '...', env: 'prod' }]]
|
|
9
|
+
*
|
|
10
|
+
* 仅做配置透传,不注入原生构建设置(podspec / gradle 已由 autolinking 处理)。
|
|
11
|
+
* 零运行时依赖,非 Expo 用户安装本包不会拉入 @expo/* 。
|
|
12
|
+
*/
|
|
13
|
+
/** 本插件触碰到的 expo config 切片,故意放宽以避免对 @expo/config-types 的硬依赖。 */
|
|
14
|
+
export interface RumExpoConfig {
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
extra?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface RumSdkPluginProps {
|
|
19
|
+
/** ARMS 上报地址,可在控制台创建应用后获取 */
|
|
20
|
+
endpoint?: string;
|
|
21
|
+
/** 环境,默认 'prod' */
|
|
22
|
+
env?: 'prod' | 'gray' | 'pre' | 'daily' | 'local';
|
|
23
|
+
/** 应用版本号 */
|
|
24
|
+
version?: string;
|
|
25
|
+
}
|
|
26
|
+
declare const withRumSdk: (config: RumExpoConfig, props?: RumSdkPluginProps) => RumExpoConfig;
|
|
27
|
+
export default withRumSdk;
|
|
28
|
+
//# sourceMappingURL=expoConfigPlugin.d.ts.map
|
|
@@ -2,8 +2,10 @@ import { IContext, IProcessor } from '@arms/rum-core';
|
|
|
2
2
|
export default class SessionProcessor implements IProcessor {
|
|
3
3
|
name: string;
|
|
4
4
|
ctx?: IContext;
|
|
5
|
+
private lastSessionId;
|
|
5
6
|
setup(ctx: IContext): void;
|
|
6
7
|
update: (e?: Event) => void;
|
|
7
8
|
process(ctx: IContext): import("@arms/rum-core").RumEvent;
|
|
9
|
+
private syncCrashContext;
|
|
8
10
|
}
|
|
9
11
|
//# sourceMappingURL=session-processor.d.ts.map
|
|
@@ -8,7 +8,9 @@ declare class RNReporter extends Reporter implements IReporter {
|
|
|
8
8
|
constructor();
|
|
9
9
|
init(ctx: IContext): void;
|
|
10
10
|
onAppStateChanged: (nextAppState: string) => void;
|
|
11
|
-
request(ctx: IContext, bundle: RumEventBundle): void
|
|
11
|
+
request(ctx: IContext, bundle: RumEventBundle): Promise<void>;
|
|
12
|
+
/** 通过共享 emitter 通知崩溃采集器上报结果(成功则删文件,失败保留重试) */
|
|
13
|
+
private ackCrashes;
|
|
12
14
|
catchHandle: (err: any) => void;
|
|
13
15
|
destroy(): void;
|
|
14
16
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IMonitorReporter, MonitorEventBundle } from '@arms/rum-core';
|
|
2
|
+
export declare class RNMonitorReporter implements IMonitorReporter {
|
|
3
|
+
private endpoint;
|
|
4
|
+
constructor(endpoint: string);
|
|
5
|
+
send(data: MonitorEventBundle[]): void;
|
|
6
|
+
private buildMonitorEndpoint;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=monitor-reporter.d.ts.map
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { Shell } from '@arms/rum-core';
|
|
2
|
+
import * as collectors from './collector';
|
|
2
3
|
import { IRNConfig } from './types/client';
|
|
3
4
|
import { NavigationContainerRef } from './types';
|
|
5
|
+
declare const builtInCollectors: readonly (typeof collectors.PvCollector | typeof collectors.ExceptionCollector | typeof collectors.CrashCollector | typeof collectors.ApiCollector | typeof collectors.ActionCollector)[];
|
|
6
|
+
type CollectorName = (typeof builtInCollectors)[number]['prototype']['name'];
|
|
7
|
+
type CollectorMap = {
|
|
8
|
+
[K in CollectorName]: InstanceType<Extract<(typeof builtInCollectors)[number], {
|
|
9
|
+
prototype: {
|
|
10
|
+
name: K;
|
|
11
|
+
};
|
|
12
|
+
}>>;
|
|
13
|
+
};
|
|
4
14
|
/**
|
|
5
15
|
* 对外导出 shell 层, 所有 shell 层模型的 API 设计约定:
|
|
6
16
|
* 1. API 命名空间按照 variables / functions / events 来组织
|
|
@@ -40,6 +50,7 @@ export declare class ArmsRum extends Shell {
|
|
|
40
50
|
*/
|
|
41
51
|
startTrackingViews(navigationRef: NavigationContainerRef | any): void;
|
|
42
52
|
stopTrackingViews(): void;
|
|
53
|
+
getCollector<T extends CollectorName>(name: T): CollectorMap[T] | undefined;
|
|
43
54
|
}
|
|
44
55
|
declare const _default: ArmsRum;
|
|
45
56
|
export default _default;
|