@arms/rum-reactnative 0.1.3-beta.2 → 0.1.3-beta.3
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 +1 -0
- package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +78 -6
- package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +1 -1
- package/lib/commonjs/collector/resource/api.js +17 -11
- package/lib/commonjs/reporter/index.js +1 -1
- package/lib/commonjs/utils/api.js +3 -2
- package/lib/commonjs/utils/platform.js +1 -1
- package/lib/module/collector/resource/api.js +17 -11
- package/lib/module/reporter/index.js +1 -1
- package/lib/module/utils/api.js +3 -2
- package/lib/module/utils/platform.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,9 +4,81 @@
|
|
|
4
4
|
|
|
5
5
|
## 版本列表
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
### v0.1.3(2026年07月)
|
|
8
|
+
|
|
9
|
+
原生崩溃采集安全加固与自监控系统集成。
|
|
10
|
+
|
|
11
|
+
- 修复 Android/iOS 原生崩溃采集多项安全漏洞(缓冲区溢出、路径遍历、crash_id 校验)
|
|
12
|
+
- 提升采集稳定性(栈帧上限 256、线程安全、多格式时间戳解析)
|
|
13
|
+
- 集成 rum-core Telemetry 自监控,SDK 内部异常自动上报
|
|
14
|
+
- 公开导出 logger、callMonitored 供用户扩展使用
|
|
15
|
+
|
|
16
|
+
#### v0.1.3-beta.3(2026年07月16日)
|
|
17
|
+
|
|
18
|
+
API 监控增强与代码规范化。
|
|
19
|
+
|
|
20
|
+
- 新增 XMLHttpRequest abort 事件处理,触发时标记 success 为 Failed
|
|
21
|
+
- 修正 reviseApiAttr 保留 success 三态值(-1/0/1)的行为
|
|
22
|
+
- 将 reporter sendRequest 失败日志等级由 error 降为 warn
|
|
23
|
+
|
|
24
|
+
#### v0.1.3-beta.2(2026年07月16日)
|
|
25
|
+
|
|
26
|
+
React Native 0.68-0.70 多版本兼容适配。
|
|
27
|
+
|
|
28
|
+
- react-native peerDependencies 版本下限调整为 0.68.0
|
|
29
|
+
- podspec / Android build.gradle 按 RN 版本条件适配依赖与插件配置
|
|
30
|
+
- iOS crash 处理和代码生成适配多 RN 版本环境
|
|
31
|
+
- 修复多平台崩溃采集数据不统一问题,保证字段和结构一致性
|
|
32
|
+
- 强化 NDK 崩溃处理边界检查,提升稳定性
|
|
33
|
+
- 缺少原生模块时自动降级,不影响纯 JS 功能运行
|
|
34
|
+
|
|
35
|
+
#### v0.1.3-beta.1(2026年07月16日)
|
|
36
|
+
|
|
37
|
+
崩溃堆栈截断策略与模块基址计算修复。
|
|
38
|
+
|
|
39
|
+
- 统一安卓与 iOS 端双侧截断堆栈帧策略,保留前 256 + 后 256 帧,中间插入标记帧
|
|
40
|
+
- NDK 最大帧数由 256 扩充至 512
|
|
41
|
+
- 模块基址计算改用 rum_module_base_for_seg,确保 referenced_addrs 与 binary_images 过滤一致
|
|
42
|
+
- 添加边界检查防止 ELF note section 解析时二次 SIGSEGV 崩溃
|
|
43
|
+
|
|
44
|
+
#### v0.1.3-beta.0(2026年07月15日)
|
|
45
|
+
|
|
46
|
+
iOS 与 Android NDK 崩溃采集修复及数据体积优化。
|
|
47
|
+
|
|
48
|
+
- 修复 iOS objc_exception 和 cpp_exception 被 RN 桥拦截问题,改为新 NSThread 抛出异常绕过拦截
|
|
49
|
+
- 修复 iOS KSCrash 安装失败静默吞掉、userInfo 异步更新竞态及 context 同步延迟问题
|
|
50
|
+
- 优化 binary_images 按需过滤,iOS 减少 70-85%、Android NDK 减少 70-90% 崩溃数据体积
|
|
51
|
+
- 移除 Android Java 崩溃 all_threads 字段,减少 60-80% 负载
|
|
52
|
+
- 修复 Android NDK 崩溃文件重复上报问题,统一 crash_id 和文件名前缀匹配逻辑
|
|
53
|
+
- 补充双平台缺失字段:iOS device brand/app package,Android rn_version,NDK platform/exception 结构
|
|
54
|
+
- 修复 NDK 崩溃信号处理器二次 SIGSEGV,增加地址映射检测和缓冲区中间刷新
|
|
55
|
+
|
|
56
|
+
### v0.1.2(2026年05月12日)
|
|
57
|
+
|
|
58
|
+
包名正式化与核心采集能力修复。
|
|
59
|
+
|
|
60
|
+
- rum-core 升级至 >=0.1.4,包管理迁移至 Yarn 3 workspaces
|
|
61
|
+
- 修复 PV 路由采集(首屏丢失、无 path 路由过滤、navigationRef 时序)
|
|
62
|
+
- 修复 API 监控默认配置误关闭、propagatorTypes 空值崩溃
|
|
63
|
+
- Reporter AppState 回调 this 绑定修复
|
|
64
|
+
- 完善 README、接入指南、配置参考等文档
|
|
65
|
+
|
|
66
|
+
### v0.1.1(2025年11月28日)
|
|
67
|
+
|
|
68
|
+
React Native SDK 首个正式版本,提供各种配置、API,并提供了以下采集能力:
|
|
69
|
+
|
|
70
|
+
- API 监控(XMLHttpRequest / fetch),包括链路追踪等特性的支持
|
|
71
|
+
- 异常监控(JS Error、Promise Rejection、console.error)
|
|
72
|
+
- Session 相关功能(采样、超时管理)
|
|
73
|
+
- 自定义上报(Custom、Exception、Resource、View、Event)
|
|
74
|
+
- React Navigation 集成支持
|
|
75
|
+
|
|
76
|
+
### v0.1.0(2025年08月20日)
|
|
77
|
+
|
|
78
|
+
React Native 首个版本,提供各种配置、API,并提供了以下采集能力:
|
|
79
|
+
|
|
80
|
+
- API 监控(XMLHttpRequest / fetch),包括链路追踪等特性的支持
|
|
81
|
+
- 异常监控(JS Error、Promise Rejection、console.error)
|
|
82
|
+
- Session 相关功能(采样、超时管理)
|
|
83
|
+
- 自定义上报(Custom、Exception、Resource、View、Event)
|
|
84
|
+
- React Navigation 集成支持
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
### 前提条件
|
|
20
20
|
|
|
21
|
-
- React Native版本 >= 0.
|
|
21
|
+
- React Native版本 >= 0.68(SDK 已适配 0.68-0.70 多版本环境,原生模块缺失时自动降级为纯 JS 模式)
|
|
22
22
|
- Node.js >= 18
|
|
23
23
|
- npm或yarn包管理工具
|
|
24
24
|
- Android 构建:需安装 NDK 与 CMake(由宿主工程的 `ndkVersion` 决定,SDK 不强制特定版本)
|
|
@@ -77,9 +77,9 @@ class ApiCollector {
|
|
|
77
77
|
}
|
|
78
78
|
hackXhr() {
|
|
79
79
|
const oldXHRProto = XMLHttpRequest.prototype;
|
|
80
|
-
const
|
|
80
|
+
const that = this;
|
|
81
81
|
(0, _rumCore.interceptFunction)(oldXHRProto, 'open', function (method, url, async, user, password) {
|
|
82
|
-
const filters =
|
|
82
|
+
const filters = that.ctx.getConfig().filters || {};
|
|
83
83
|
const urlStr = String(url);
|
|
84
84
|
const methodStr = method.toUpperCase();
|
|
85
85
|
// chrome 对 URL 的最大长度为 8182 个字符
|
|
@@ -93,7 +93,7 @@ class ApiCollector {
|
|
|
93
93
|
password,
|
|
94
94
|
headers: {}
|
|
95
95
|
};
|
|
96
|
-
const baseRumEvent =
|
|
96
|
+
const baseRumEvent = that.ctx.session.getBaseEvent();
|
|
97
97
|
this.apiAttr = {
|
|
98
98
|
...baseRumEvent,
|
|
99
99
|
url: urlStr,
|
|
@@ -111,7 +111,7 @@ class ApiCollector {
|
|
|
111
111
|
if (!this.apiAttr || !this.apiCache) return;
|
|
112
112
|
let apiAttr = this.apiAttr;
|
|
113
113
|
this.apiCache.data = body;
|
|
114
|
-
|
|
114
|
+
that.injectTracing(this.apiAttr, tracingHeaders => {
|
|
115
115
|
Object.keys(tracingHeaders).forEach(key => {
|
|
116
116
|
tracingHeaders[key] && this.setRequestHeader(key, tracingHeaders[key]);
|
|
117
117
|
});
|
|
@@ -124,7 +124,7 @@ class ApiCollector {
|
|
|
124
124
|
} = this;
|
|
125
125
|
const {
|
|
126
126
|
evaluateApi
|
|
127
|
-
} =
|
|
127
|
+
} = that.ctx.getConfig();
|
|
128
128
|
if (!this.apiAttr) return;
|
|
129
129
|
apiAttr.status_code = status;
|
|
130
130
|
apiAttr.message = statusText;
|
|
@@ -148,15 +148,21 @@ class ApiCollector {
|
|
|
148
148
|
_rumCore.logger.warn('api-collector', 'evaluateApi failed for XHR', e);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
that.sendAPI(apiAttr, entry);
|
|
152
152
|
});
|
|
153
153
|
this.addEventListener('error', () => {
|
|
154
154
|
this.apiAttr && (this.apiAttr.success = _rumCore.ResourceStatus.Failed);
|
|
155
155
|
});
|
|
156
|
+
this.addEventListener('abort', () => {
|
|
157
|
+
if (this.apiAttr) {
|
|
158
|
+
this.apiAttr.success = _rumCore.ResourceStatus.Failed;
|
|
159
|
+
this.apiAttr.message = 'abort';
|
|
160
|
+
}
|
|
161
|
+
});
|
|
156
162
|
}, true);
|
|
157
163
|
}
|
|
158
164
|
hackFetch() {
|
|
159
|
-
const
|
|
165
|
+
const that = this;
|
|
160
166
|
const originFetch = this.originFetch = globalThis.fetch;
|
|
161
167
|
const filters = this.ctx.getConfig().filters || {};
|
|
162
168
|
globalThis.fetch = function (input, init = {}) {
|
|
@@ -175,7 +181,7 @@ class ApiCollector {
|
|
|
175
181
|
if ((0, _rumCore.urlMatch)(urlStr, filters.resource) || method === 'HEAD' || init?.mode === 'no-cors' || urlStr.length > 8182) {
|
|
176
182
|
return originFetch.call(global, input, init);
|
|
177
183
|
}
|
|
178
|
-
const baseRumEvent =
|
|
184
|
+
const baseRumEvent = that.ctx.session.getBaseEvent();
|
|
179
185
|
let apiAttr = {
|
|
180
186
|
...baseRumEvent,
|
|
181
187
|
url: urlStr,
|
|
@@ -184,7 +190,7 @@ class ApiCollector {
|
|
|
184
190
|
};
|
|
185
191
|
let apiResp;
|
|
186
192
|
let apiError;
|
|
187
|
-
|
|
193
|
+
that.injectTracing(apiAttr, tracingHeaders => {
|
|
188
194
|
Object.keys(tracingHeaders).forEach(key => {
|
|
189
195
|
if (!headers) return;
|
|
190
196
|
if (headers instanceof Headers) {
|
|
@@ -198,7 +204,7 @@ class ApiCollector {
|
|
|
198
204
|
async function fetchFinally() {
|
|
199
205
|
const {
|
|
200
206
|
evaluateApi
|
|
201
|
-
} =
|
|
207
|
+
} = that.ctx.getConfig();
|
|
202
208
|
const entry = {
|
|
203
209
|
name: apiAttr.url,
|
|
204
210
|
entryType: _api.ApiType.FETCH,
|
|
@@ -218,7 +224,7 @@ class ApiCollector {
|
|
|
218
224
|
_rumCore.logger.warn('api-collector', 'evaluateApi failed for fetch', e);
|
|
219
225
|
}
|
|
220
226
|
}
|
|
221
|
-
|
|
227
|
+
that.sendAPI(apiAttr, entry);
|
|
222
228
|
}
|
|
223
229
|
return originFetch.call(globalThis, input, init).then(response => {
|
|
224
230
|
// @ts-ignore
|
|
@@ -138,7 +138,7 @@ class RNReporter extends _rumCore.Reporter {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
catchHandle = err => {
|
|
141
|
-
_rumCore.logger.
|
|
141
|
+
_rumCore.logger.warn('reporter', 'sendRequest failed', err);
|
|
142
142
|
};
|
|
143
143
|
destroy() {
|
|
144
144
|
this.appStateListener?.remove();
|
|
@@ -23,8 +23,9 @@ function reviseApiAttr(attrs) {
|
|
|
23
23
|
if ((0, _rumCore.isString)(attrs.message)) {
|
|
24
24
|
obj.message = attrs.message.substring(0, 1e3);
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// 对齐 Browser 端:保留三态 (-1/0/1),避免 Unknown(-1) 被误转为 Success(1)
|
|
27
|
+
if ((0, _rumCore.isNumber)(attrs.success) && attrs.success >= -1 && attrs.success <= 1) {
|
|
28
|
+
obj.success = attrs.success;
|
|
28
29
|
}
|
|
29
30
|
if ((0, _rumCore.isNumber)(attrs.duration) && attrs.duration >= 0) {
|
|
30
31
|
obj.duration = attrs.duration;
|
|
@@ -14,7 +14,7 @@ var _rumCore = require("@arms/rum-core");
|
|
|
14
14
|
var _reactNative = require("react-native");
|
|
15
15
|
var _NativeRumSdkReactnative = _interopRequireDefault(require("../NativeRumSdkReactnative"));
|
|
16
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
-
const _pkg = {"version":"0.1.3-beta.
|
|
17
|
+
const _pkg = {"version":"0.1.3-beta.3"};
|
|
18
18
|
const VERSION = exports.VERSION = _pkg.version;
|
|
19
19
|
|
|
20
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -73,9 +73,9 @@ export default class ApiCollector {
|
|
|
73
73
|
}
|
|
74
74
|
hackXhr() {
|
|
75
75
|
const oldXHRProto = XMLHttpRequest.prototype;
|
|
76
|
-
const
|
|
76
|
+
const that = this;
|
|
77
77
|
interceptFunction(oldXHRProto, 'open', function (method, url, async, user, password) {
|
|
78
|
-
const filters =
|
|
78
|
+
const filters = that.ctx.getConfig().filters || {};
|
|
79
79
|
const urlStr = String(url);
|
|
80
80
|
const methodStr = method.toUpperCase();
|
|
81
81
|
// chrome 对 URL 的最大长度为 8182 个字符
|
|
@@ -89,7 +89,7 @@ export default class ApiCollector {
|
|
|
89
89
|
password,
|
|
90
90
|
headers: {}
|
|
91
91
|
};
|
|
92
|
-
const baseRumEvent =
|
|
92
|
+
const baseRumEvent = that.ctx.session.getBaseEvent();
|
|
93
93
|
this.apiAttr = {
|
|
94
94
|
...baseRumEvent,
|
|
95
95
|
url: urlStr,
|
|
@@ -107,7 +107,7 @@ export default class ApiCollector {
|
|
|
107
107
|
if (!this.apiAttr || !this.apiCache) return;
|
|
108
108
|
let apiAttr = this.apiAttr;
|
|
109
109
|
this.apiCache.data = body;
|
|
110
|
-
|
|
110
|
+
that.injectTracing(this.apiAttr, tracingHeaders => {
|
|
111
111
|
Object.keys(tracingHeaders).forEach(key => {
|
|
112
112
|
tracingHeaders[key] && this.setRequestHeader(key, tracingHeaders[key]);
|
|
113
113
|
});
|
|
@@ -120,7 +120,7 @@ export default class ApiCollector {
|
|
|
120
120
|
} = this;
|
|
121
121
|
const {
|
|
122
122
|
evaluateApi
|
|
123
|
-
} =
|
|
123
|
+
} = that.ctx.getConfig();
|
|
124
124
|
if (!this.apiAttr) return;
|
|
125
125
|
apiAttr.status_code = status;
|
|
126
126
|
apiAttr.message = statusText;
|
|
@@ -144,15 +144,21 @@ export default class ApiCollector {
|
|
|
144
144
|
logger.warn('api-collector', 'evaluateApi failed for XHR', e);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
that.sendAPI(apiAttr, entry);
|
|
148
148
|
});
|
|
149
149
|
this.addEventListener('error', () => {
|
|
150
150
|
this.apiAttr && (this.apiAttr.success = ResourceStatus.Failed);
|
|
151
151
|
});
|
|
152
|
+
this.addEventListener('abort', () => {
|
|
153
|
+
if (this.apiAttr) {
|
|
154
|
+
this.apiAttr.success = ResourceStatus.Failed;
|
|
155
|
+
this.apiAttr.message = 'abort';
|
|
156
|
+
}
|
|
157
|
+
});
|
|
152
158
|
}, true);
|
|
153
159
|
}
|
|
154
160
|
hackFetch() {
|
|
155
|
-
const
|
|
161
|
+
const that = this;
|
|
156
162
|
const originFetch = this.originFetch = globalThis.fetch;
|
|
157
163
|
const filters = this.ctx.getConfig().filters || {};
|
|
158
164
|
globalThis.fetch = function (input, init = {}) {
|
|
@@ -171,7 +177,7 @@ export default class ApiCollector {
|
|
|
171
177
|
if (urlMatch(urlStr, filters.resource) || method === 'HEAD' || init?.mode === 'no-cors' || urlStr.length > 8182) {
|
|
172
178
|
return originFetch.call(global, input, init);
|
|
173
179
|
}
|
|
174
|
-
const baseRumEvent =
|
|
180
|
+
const baseRumEvent = that.ctx.session.getBaseEvent();
|
|
175
181
|
let apiAttr = {
|
|
176
182
|
...baseRumEvent,
|
|
177
183
|
url: urlStr,
|
|
@@ -180,7 +186,7 @@ export default class ApiCollector {
|
|
|
180
186
|
};
|
|
181
187
|
let apiResp;
|
|
182
188
|
let apiError;
|
|
183
|
-
|
|
189
|
+
that.injectTracing(apiAttr, tracingHeaders => {
|
|
184
190
|
Object.keys(tracingHeaders).forEach(key => {
|
|
185
191
|
if (!headers) return;
|
|
186
192
|
if (headers instanceof Headers) {
|
|
@@ -194,7 +200,7 @@ export default class ApiCollector {
|
|
|
194
200
|
async function fetchFinally() {
|
|
195
201
|
const {
|
|
196
202
|
evaluateApi
|
|
197
|
-
} =
|
|
203
|
+
} = that.ctx.getConfig();
|
|
198
204
|
const entry = {
|
|
199
205
|
name: apiAttr.url,
|
|
200
206
|
entryType: ApiType.FETCH,
|
|
@@ -214,7 +220,7 @@ export default class ApiCollector {
|
|
|
214
220
|
logger.warn('api-collector', 'evaluateApi failed for fetch', e);
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
|
-
|
|
223
|
+
that.sendAPI(apiAttr, entry);
|
|
218
224
|
}
|
|
219
225
|
return originFetch.call(globalThis, input, init).then(response => {
|
|
220
226
|
// @ts-ignore
|
package/lib/module/utils/api.js
CHANGED
|
@@ -15,8 +15,9 @@ export function reviseApiAttr(attrs) {
|
|
|
15
15
|
if (isString(attrs.message)) {
|
|
16
16
|
obj.message = attrs.message.substring(0, 1e3);
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// 对齐 Browser 端:保留三态 (-1/0/1),避免 Unknown(-1) 被误转为 Success(1)
|
|
19
|
+
if (isNumber(attrs.success) && attrs.success >= -1 && attrs.success <= 1) {
|
|
20
|
+
obj.success = attrs.success;
|
|
20
21
|
}
|
|
21
22
|
if (isNumber(attrs.duration) && attrs.duration >= 0) {
|
|
22
23
|
obj.duration = attrs.duration;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { AppType } from '@arms/rum-core';
|
|
4
4
|
import { Dimensions, Platform } from 'react-native';
|
|
5
5
|
import NativeRumSdkReactnative from "../NativeRumSdkReactnative.js";
|
|
6
|
-
const _pkg = {"version":"0.1.3-beta.
|
|
6
|
+
const _pkg = {"version":"0.1.3-beta.3"};
|
|
7
7
|
export const VERSION = _pkg.version;
|
|
8
8
|
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
package/package.json
CHANGED