@arms/rum-reactnative 0.1.3-beta.5 → 0.1.4-beta.2

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 (89) hide show
  1. package/README.md +9 -2
  2. package/android/build.gradle +12 -1
  3. package/android/gradle.properties +3 -1
  4. package/android/src/main/AndroidManifest.xml +4 -1
  5. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativeModule.kt +67 -14
  6. package/android/src/main/java/com/rumsdkreactnative/RumSdkReactnativePackage.kt +9 -2
  7. package/docs/ReactNative SDK/351/205/215/347/275/256/345/217/202/350/200/203.md" +25 -0
  8. package/docs/SDK /347/211/210/346/234/254/350/257/264/346/230/216.md" +20 -0
  9. package/docs//346/216/245/345/205/245ReactNative/345/272/224/347/224/250.md +2 -1
  10. package/ios/RumAppStateRecorder.h +69 -0
  11. package/ios/RumAppStateRecorder.mm +547 -0
  12. package/ios/RumCrashReporter.h +32 -0
  13. package/ios/RumCrashReporter.mm +97 -11
  14. package/ios/RumSdkReactnative.h +11 -1
  15. package/ios/RumSdkReactnative.mm +115 -29
  16. package/lib/commonjs/NativeRumSdkReactnative.js +1 -54
  17. package/lib/commonjs/collector/action/index.js +1 -108
  18. package/lib/commonjs/collector/exception/crash.js +1 -148
  19. package/lib/commonjs/collector/exception/index.js +1 -238
  20. package/lib/commonjs/collector/exception/oom.js +1 -0
  21. package/lib/commonjs/collector/index.js +1 -42
  22. package/lib/commonjs/collector/resource/api.js +1 -292
  23. package/lib/commonjs/collector/view/perf.js +1 -79
  24. package/lib/commonjs/collector/view/pv.js +1 -88
  25. package/lib/commonjs/expoConfigPlugin.js +1 -37
  26. package/lib/commonjs/index.js +1 -29
  27. package/lib/commonjs/plugin.js +1 -47
  28. package/lib/commonjs/processor/default-processor.js +1 -27
  29. package/lib/commonjs/processor/session-processor.js +1 -47
  30. package/lib/commonjs/reporter/index.js +1 -148
  31. package/lib/commonjs/reporter/monitor-reporter.js +1 -43
  32. package/lib/commonjs/shell.js +1 -91
  33. package/lib/commonjs/types/client.js +1 -6
  34. package/lib/commonjs/types/crash.js +1 -37
  35. package/lib/commonjs/types/index.js +1 -2
  36. package/lib/commonjs/types/oom.js +1 -0
  37. package/lib/commonjs/utils/action.js +1 -305
  38. package/lib/commonjs/utils/api.js +1 -84
  39. package/lib/commonjs/utils/base.js +1 -95
  40. package/lib/commonjs/utils/crash.js +1 -149
  41. package/lib/commonjs/utils/platform.js +1 -162
  42. package/lib/commonjs/utils/session.js +1 -158
  43. package/lib/commonjs/utils/url.js +1 -59
  44. package/lib/commonjs/utils/view.js +1 -93
  45. package/lib/module/NativeRumSdkReactnative.js +1 -51
  46. package/lib/module/collector/action/index.js +1 -103
  47. package/lib/module/collector/exception/crash.js +1 -143
  48. package/lib/module/collector/exception/index.js +1 -233
  49. package/lib/module/collector/exception/oom.js +1 -0
  50. package/lib/module/collector/index.js +1 -8
  51. package/lib/module/collector/resource/api.js +1 -287
  52. package/lib/module/collector/view/perf.js +1 -79
  53. package/lib/module/collector/view/pv.js +1 -83
  54. package/lib/module/expoConfigPlugin.js +1 -33
  55. package/lib/module/index.js +1 -7
  56. package/lib/module/plugin.js +1 -42
  57. package/lib/module/processor/default-processor.js +1 -22
  58. package/lib/module/processor/session-processor.js +1 -42
  59. package/lib/module/reporter/index.js +1 -144
  60. package/lib/module/reporter/monitor-reporter.js +1 -38
  61. package/lib/module/shell.js +1 -84
  62. package/lib/module/types/client.js +1 -4
  63. package/lib/module/types/crash.js +1 -33
  64. package/lib/module/types/index.js +1 -2
  65. package/lib/module/types/oom.js +1 -0
  66. package/lib/module/utils/action.js +1 -299
  67. package/lib/module/utils/api.js +1 -76
  68. package/lib/module/utils/base.js +1 -90
  69. package/lib/module/utils/crash.js +1 -144
  70. package/lib/module/utils/platform.js +1 -150
  71. package/lib/module/utils/session.js +1 -154
  72. package/lib/module/utils/url.js +1 -54
  73. package/lib/module/utils/view.js +1 -88
  74. package/lib/typescript/commonjs/src/NativeRumSdkReactnative.d.ts +10 -0
  75. package/lib/typescript/commonjs/src/collector/exception/oom.d.ts +34 -0
  76. package/lib/typescript/commonjs/src/collector/index.d.ts +1 -0
  77. package/lib/typescript/commonjs/src/shell.d.ts +1 -1
  78. package/lib/typescript/commonjs/src/types/client.d.ts +27 -0
  79. package/lib/typescript/commonjs/src/types/oom.d.ts +58 -0
  80. package/lib/typescript/commonjs/src/utils/crash.d.ts +13 -0
  81. package/lib/typescript/module/src/NativeRumSdkReactnative.d.ts +10 -0
  82. package/lib/typescript/module/src/collector/exception/oom.d.ts +34 -0
  83. package/lib/typescript/module/src/collector/index.d.ts +1 -0
  84. package/lib/typescript/module/src/shell.d.ts +1 -1
  85. package/lib/typescript/module/src/types/client.d.ts +27 -0
  86. package/lib/typescript/module/src/types/oom.d.ts +58 -0
  87. package/lib/typescript/module/src/utils/crash.d.ts +13 -0
  88. package/package.json +1 -2
  89. package/src/NativeRumSdkReactnative.ts +18 -0
@@ -1,83 +1 @@
1
- "use strict";
2
-
3
- import { isFunction, RumEventType } from '@arms/rum-core';
4
- import { addNavigateListener, removeNavigateListener } from "../../utils/view.js";
5
- import { CRASH_CONTEXT_EVENT } from "../../types/crash.js";
6
- export default class PvCollector {
7
- name = 'pv-collector';
8
- pageMap = {};
9
- setup(ctx, sendEvent) {
10
- this.ctx = ctx;
11
- this.sendEvent = sendEvent;
12
- addNavigateListener(this.onChange);
13
- }
14
- onChange = route => {
15
- // {"name":"index","path":"/","key":"index-SB2hXmOGNdpiLskG5sXwj"}
16
- // {"name":"__root","key":"__root-jPbNqG7-HaM-OUx_FcCUw"}
17
- const {
18
- key,
19
- name,
20
- path,
21
- params
22
- } = route;
23
- const page = {
24
- name,
25
- path,
26
- id: key,
27
- params
28
- };
29
- if (name === '__root') return;
30
- this.sendPv(page);
31
- };
32
- sendPv = page => {
33
- const prevPage = this.prevPage;
34
- const ctx = this.ctx;
35
- if (page.id === prevPage?.id) {
36
- // 路由没有发生变化,不发送
37
- return;
38
- }
39
- page.name = this.getViewName(page.path || page.name || '', page);
40
- if (prevPage && prevPage.id in this.pageMap) {
41
- delete this.pageMap[prevPage.id];
42
- ctx.removeView(prevPage.id);
43
- }
44
- this.prevPage = page;
45
- ctx.addView(page);
46
-
47
- // 路由回退情况下已经上报
48
- if (page.id in this.pageMap) {
49
- return;
50
- }
51
- this.pageMap[page.id] = page;
52
- this.sendEvent?.({
53
- event_type: RumEventType.VIEW,
54
- type: 'pv',
55
- loading_type: 'initial_load',
56
- ...page
57
- });
58
-
59
- // 同步当前 view 上下文到原生侧(崩溃报告关联用)
60
- const sessionId = ctx.session?.getSessionId?.() || '';
61
- const userId = ctx.session?.getUserId?.() || '';
62
- ctx.emitter.emit(CRASH_CONTEXT_EVENT, {
63
- session_id: sessionId,
64
- user_id: userId,
65
- view_id: page.id,
66
- view_name: page.name
67
- });
68
- };
69
- getViewName(url, page) {
70
- let {
71
- parseViewName
72
- } = this.ctx?.getConfig();
73
- let name = page.name;
74
- if (parseViewName && isFunction(parseViewName)) {
75
- name = parseViewName(url, page) || name;
76
- }
77
- return name;
78
- }
79
- destroy() {
80
- removeNavigateListener(this.onChange);
81
- }
82
- }
83
- //# sourceMappingURL=pv.js.map
1
+ "use strict";import{isFunction,RumEventType}from"@arms/rum-core";import{addNavigateListener,removeNavigateListener}from"../../utils/view.js";import{CRASH_CONTEXT_EVENT}from"../../types/crash.js";export default class PvCollector{name="pv-collector";pageMap={};setup(e,t){this.ctx=e,this.sendEvent=t,addNavigateListener(this.onChange)}onChange=e=>{const{key:t,name:i,path:s,params:a}=e,n={name:i,path:s,id:t,params:a};"__root"!==i&&this.sendPv(n)};sendPv=e=>{const t=this.prevPage,i=this.ctx;if(e.id===t?.id)return;if(e.name=this.getViewName(e.path||e.name||"",e),t&&t.id in this.pageMap&&(delete this.pageMap[t.id],i.removeView(t.id)),this.prevPage=e,i.addView(e),e.id in this.pageMap)return;this.pageMap[e.id]=e,this.sendEvent?.({event_type:RumEventType.VIEW,type:"pv",loading_type:"initial_load",...e});const s=i.session?.getSessionId?.()||"",a=i.session?.getUserId?.()||"";i.emitter.emit(CRASH_CONTEXT_EVENT,{session_id:s,user_id:a,view_id:e.id,view_name:e.name})};getViewName(e,t){let{parseViewName:i}=this.ctx?.getConfig(),s=t.name;return i&&isFunction(i)&&(s=i(e,t)||s),s}destroy(){removeNavigateListener(this.onChange)}}
@@ -1,33 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Expo config plugin for @arms/rum-reactnative.
5
- *
6
- * 在 app.config 中声明后,将 SDK 配置写入 `expoConfig.extra.rumSdk`,运行时可通过
7
- * `Constants.expoConfig?.extra?.rumSdk` 读取,避免在 JS 入口硬编码 endpoint。
8
- *
9
- * app.config.ts 示例:
10
- * plugins: [['@arms/rum-reactnative', { endpoint: '...', env: 'prod' }]]
11
- *
12
- * 仅做配置透传,不注入原生构建设置(podspec / gradle 已由 autolinking 处理)。
13
- * 零运行时依赖,非 Expo 用户安装本包不会拉入 @expo/* 。
14
- */
15
-
16
- /** 本插件触碰到的 expo config 切片,故意放宽以避免对 @expo/config-types 的硬依赖。 */
17
-
18
- const withRumSdk = (config, props) => {
19
- const extra = {
20
- ...(config.extra ?? {})
21
- };
22
- extra.rumSdk = {
23
- endpoint: props?.endpoint,
24
- env: props?.env ?? 'prod',
25
- version: props?.version
26
- };
27
- return {
28
- ...config,
29
- extra
30
- };
31
- };
32
- export default withRumSdk;
33
- //# sourceMappingURL=expoConfigPlugin.js.map
1
+ "use strict";const withRumSdk=(t,e)=>{const n={...t.extra??{}};return n.rumSdk={endpoint:e?.endpoint,env:e?.env??"prod",version:e?.version},{...t,extra:n}};export default withRumSdk;
@@ -1,7 +1 @@
1
- "use strict";
2
-
3
- import armsRum, { ArmsRum } from "./shell.js";
4
- export { logger, callMonitored } from '@arms/rum-core';
5
- export { ArmsRum };
6
- export default armsRum;
7
- //# sourceMappingURL=index.js.map
1
+ "use strict";import armsRum,{ArmsRum}from"./shell.js";export{logger,callMonitored}from"@arms/rum-core";export{ArmsRum};export default armsRum;
@@ -1,42 +1 @@
1
- "use strict";
2
-
3
- import { NativeModules, NativeEventEmitter } from 'react-native';
4
- import { isString } from '@arms/rum-core';
5
- import { VERSION } from "./utils/platform.js";
6
- import armsRum from "./shell.js";
7
- const RumSdkModule = NativeModules.RumSdkModule;
8
- function initRum(config) {
9
- armsRum.init({
10
- ...config,
11
- beforeReport(bundle) {
12
- RumSdkModule.sendEvent(JSON.stringify(bundle));
13
- return null;
14
- }
15
- });
16
- }
17
- if (RumSdkModule) {
18
- const eventEmitter = new NativeEventEmitter(RumSdkModule);
19
- eventEmitter.addListener('rumNativeEvent', config => {
20
- if (isString(config)) {
21
- try {
22
- config = JSON.parse(config);
23
- } catch (e) {
24
- console.warn('getConfig error', e);
25
- return;
26
- }
27
- }
28
- // pid 为可选配置,未提供时使用默认值(格式:react-native@{VERSION})
29
- // 这确保了即使未在ARMS控制台创建应用,SDK也能正常初始化和上报
30
- if (!config.pid) {
31
- config.pid = `react-native@${VERSION}`;
32
- }
33
- // endpoint 为必填配置,未提供时使用本地回环地址作为兜底
34
- if (!config.endpoint) {
35
- config.endpoint = `http://127.0.0.1/?version=${VERSION}`;
36
- }
37
- initRum(config);
38
- });
39
- RumSdkModule?.getConfig?.();
40
- }
41
- export default armsRum;
42
- //# sourceMappingURL=plugin.js.map
1
+ "use strict";import{NativeModules,NativeEventEmitter}from"react-native";import{isString}from"@arms/rum-core";import{VERSION}from"./utils/platform.js";import armsRum from"./shell.js";const RumSdkModule=NativeModules.RumSdkModule;function initRum(t){armsRum.init({...t,beforeReport:t=>(RumSdkModule.sendEvent(JSON.stringify(t)),null)})}if(RumSdkModule){new NativeEventEmitter(RumSdkModule).addListener("rumNativeEvent",t=>{if(isString(t))try{t=JSON.parse(t)}catch(t){return void console.warn("getConfig error",t)}t.pid||(t.pid=`react-native@${VERSION}`),t.endpoint||(t.endpoint=`http://127.0.0.1/?version=${VERSION}`),initRum(t)}),RumSdkModule?.getConfig?.()}export default armsRum;
@@ -1,22 +1 @@
1
- "use strict";
2
-
3
- import { getCurrentTime } from "../utils/base.js";
4
- import { getCurView } from "../utils/view.js";
5
- export default class DefaultProcessor {
6
- name = 'default-processor';
7
- process(ctx) {
8
- const event = ctx.getRumEvent();
9
- const view = getCurView(ctx);
10
- const session_id = ctx.session.getSessionId();
11
- const event_id = ctx.session.getEventId();
12
- const rumEvent = {
13
- timestamp: getCurrentTime(),
14
- session_id,
15
- event_id,
16
- view,
17
- ...event
18
- };
19
- return rumEvent;
20
- }
21
- }
22
- //# sourceMappingURL=default-processor.js.map
1
+ "use strict";import{getCurrentTime}from"../utils/base.js";import{getCurView}from"../utils/view.js";export default class DefaultProcessor{name="default-processor";process(e){const s=e.getRumEvent(),t=getCurView(e),r=e.session.getSessionId(),i=e.session.getEventId();return{timestamp:getCurrentTime(),session_id:r,event_id:i,view:t,...s}}}
@@ -1,42 +1 @@
1
- "use strict";
2
-
3
- import { debounce, ONE_SECOND } from '@arms/rum-core';
4
- import { CRASH_CONTEXT_EVENT } from "../types/crash.js";
5
- import { getCurView } from "../utils/view.js";
6
- export default class SessionProcessor {
7
- name = 'session-processor';
8
- lastSessionId = '';
9
- setup(ctx) {
10
- this.ctx = ctx;
11
- this.update = debounce(this.update, ONE_SECOND);
12
- // 延迟到下一个事件循环执行,确保 collectors 已完成 setup 并注册了
13
- // CRASH_CONTEXT_EVENT 监听器(rum-core 中 processors.setup() 先于
14
- // collectors.setup() 执行)。消除 session 创建后 1 秒内的 context
15
- // 同步窗口,同时避免 emit 事件因无监听器而被丢弃
16
- setTimeout(() => this.syncCrashContext(), 0);
17
- // sdk.onTouchStart(this.update)
18
- }
19
- update = e => {
20
- if (e && !e.isTrusted) return;
21
- this.ctx?.session.updateSession();
22
- this.syncCrashContext();
23
- };
24
- process(ctx) {
25
- this.update();
26
- return ctx.getRumEvent();
27
- }
28
- syncCrashContext() {
29
- if (!this.ctx) return;
30
- const sessionId = this.ctx.session.getSessionId();
31
- if (sessionId === this.lastSessionId) return;
32
- this.lastSessionId = sessionId;
33
- const view = getCurView(this.ctx);
34
- this.ctx.emitter.emit(CRASH_CONTEXT_EVENT, {
35
- session_id: sessionId,
36
- user_id: this.ctx.session.getUserId(),
37
- view_id: view?.id || '',
38
- view_name: view?.name || ''
39
- });
40
- }
41
- }
42
- //# sourceMappingURL=session-processor.js.map
1
+ "use strict";import{debounce,ONE_SECOND}from"@arms/rum-core";import{CRASH_CONTEXT_EVENT}from"../types/crash.js";import{getCurView}from"../utils/view.js";export default class SessionProcessor{name="session-processor";lastSessionId="";setup(s){this.ctx=s,this.update=debounce(this.update,ONE_SECOND),setTimeout(()=>this.syncCrashContext(),0)}update=s=>{s&&!s.isTrusted||(this.ctx?.session.updateSession(),this.syncCrashContext())};process(s){return this.update(),s.getRumEvent()}syncCrashContext(){if(!this.ctx)return;const s=this.ctx.session.getSessionId();if(s===this.lastSessionId)return;this.lastSessionId=s;const t=getCurView(this.ctx);this.ctx.emitter.emit(CRASH_CONTEXT_EVENT,{session_id:s,user_id:this.ctx.session.getUserId(),view_id:t?.id||"",view_name:t?.name||""})}}
@@ -1,144 +1 @@
1
- "use strict";
2
-
3
- import { Reporter, Telemetry, logger } from '@arms/rum-core';
4
- import { fixAttrs } from "../utils/platform.js";
5
- import { CRASH_ID_FIELD, CRASH_REPORT_ACK_EVENT } from "../types/crash.js";
6
- // @ts-ignore
7
- import { AppState } from 'react-native';
8
-
9
- /**
10
- * 从 bundle.events 的 snapshots 中提取携带的 crash_id(瞬态字段)。
11
- * crash_id 由 CrashCollector 注入到 snapshots JSON 字符串中,
12
- * reporter 提取后用于 ack,并在序列化前从 snapshots 中剥离,不会发送到后端。
13
- * 兼容旧版降级路径:crash_id 可能残留在事件根级。
14
- */
15
- function extractCrashIds(bundle) {
16
- const ids = [];
17
- const events = bundle?.events;
18
- if (Array.isArray(events)) {
19
- for (const ev of events) {
20
- if (!ev) continue;
21
- // 优先从 snapshots 提取
22
- let cid;
23
- try {
24
- const snapshotsObj = JSON.parse(ev.snapshots);
25
- cid = snapshotsObj?.[CRASH_ID_FIELD];
26
- } catch {
27
- // snapshots 解析失败
28
- }
29
- // 兼容旧版降级路径:检查根级
30
- if (!cid) {
31
- cid = ev[CRASH_ID_FIELD];
32
- }
33
- if (typeof cid === 'string' && cid) ids.push(cid);
34
- }
35
- }
36
- return ids;
37
- }
38
-
39
- /**
40
- * 序列化前剥离事件上的 crash_id 瞬态字段:
41
- * - 从 snapshots JSON 字符串中移除;
42
- * - 兼容旧版降级路径:从事件根级移除。
43
- */
44
- function stripCrashIds(bundle) {
45
- const events = bundle?.events;
46
- if (!Array.isArray(events)) return;
47
- for (const ev of events) {
48
- if (!ev) continue;
49
- // 从 snapshots 中移除
50
- if (typeof ev.snapshots === 'string') {
51
- try {
52
- const snapshotsObj = JSON.parse(ev.snapshots);
53
- if (snapshotsObj && CRASH_ID_FIELD in snapshotsObj) {
54
- delete snapshotsObj[CRASH_ID_FIELD];
55
- ev.snapshots = JSON.stringify(snapshotsObj);
56
- }
57
- } catch {
58
- // snapshots 解析失败,跳过
59
- }
60
- }
61
- // 兼容旧版降级路径:从根级移除
62
- if (CRASH_ID_FIELD in ev) {
63
- delete ev[CRASH_ID_FIELD];
64
- }
65
- }
66
- }
67
-
68
- /**
69
- * rn-app reporter
70
- */
71
- class RNReporter extends Reporter {
72
- name = 'rn-reporter';
73
- constructor() {
74
- super();
75
- // 离开之前 flushEventQueue
76
- try {
77
- this.appStateListener = AppState.addEventListener('change', this.onAppStateChanged);
78
- } catch (error) {
79
- logger.warn('reporter', 'AppState listener binding failed', error);
80
- }
81
- }
82
- init(ctx) {
83
- this.ctx = ctx;
84
- }
85
- onAppStateChanged = nextAppState => {
86
- if (nextAppState === 'background') {
87
- // 执行后台操作:暂停动画、保存数据、停止网络请求等
88
- if (typeof this.flushEventQueue === 'function') {
89
- this.flushEventQueue();
90
- }
91
- // 后台前 flush 自监控数据
92
- Telemetry.get()?.flush();
93
- }
94
- // else if (nextAppState === 'active') {
95
- // console.warn('RUM:应用回到前台');
96
- // }
97
- };
98
- async request(ctx, bundle) {
99
- // 先从事件中提取崩溃 crash_id(瞬态字段),用于上报后 ack 删文件
100
- const crashIds = extractCrashIds(bundle);
101
- try {
102
- const batchedEvents = await fixAttrs(bundle);
103
- // 序列化前剥离瞬态字段,避免发送到后端
104
- stripCrashIds(batchedEvents);
105
- const config = ctx.getConfig();
106
- fetch(config.endpoint, {
107
- method: 'POST',
108
- headers: {
109
- 'Content-Type': 'text/plain'
110
- },
111
- body: JSON.stringify(batchedEvents)
112
- }).then(res => {
113
- this.ackCrashes(ctx, crashIds, !!(res && res.ok));
114
- }).catch(err => {
115
- this.catchHandle(err);
116
- this.ackCrashes(ctx, crashIds, false);
117
- });
118
- } catch (err) {
119
- this.catchHandle(err);
120
- this.ackCrashes(ctx, crashIds, false);
121
- }
122
- }
123
-
124
- /** 通过共享 emitter 通知崩溃采集器上报结果(成功则删文件,失败保留重试) */
125
- ackCrashes(ctx, crashIds, success) {
126
- if (!crashIds.length) return;
127
- try {
128
- ctx.emitter?.emit(CRASH_REPORT_ACK_EVENT, {
129
- crashIds,
130
- success
131
- });
132
- } catch (e) {
133
- logger.warn('reporter', 'emit crash ack failed', e);
134
- }
135
- }
136
- catchHandle = err => {
137
- logger.warn('reporter', 'sendRequest failed', err);
138
- };
139
- destroy() {
140
- this.appStateListener?.remove();
141
- }
142
- }
143
- export default RNReporter;
144
- //# sourceMappingURL=index.js.map
1
+ "use strict";import{Reporter,Telemetry,logger}from"@arms/rum-core";import{fixAttrs}from"../utils/platform.js";import{CRASH_ID_FIELD,CRASH_REPORT_ACK_EVENT}from"../types/crash.js";import{AppState}from"react-native";function extractCrashIds(t){const e=[],r=t?.events;if(Array.isArray(r))for(const t of r){if(!t)continue;let r;try{const e=JSON.parse(t.snapshots);r=e?.[CRASH_ID_FIELD]}catch{}r||(r=t[CRASH_ID_FIELD]),"string"==typeof r&&r&&e.push(r)}return e}function stripCrashIds(t){const e=t?.events;if(Array.isArray(e))for(const t of e)if(t){if("string"==typeof t.snapshots)try{const e=JSON.parse(t.snapshots);e&&CRASH_ID_FIELD in e&&(delete e[CRASH_ID_FIELD],t.snapshots=JSON.stringify(e))}catch{}CRASH_ID_FIELD in t&&delete t[CRASH_ID_FIELD]}}class RNReporter extends Reporter{name="rn-reporter";constructor(){super();try{this.appStateListener=AppState.addEventListener("change",this.onAppStateChanged)}catch(t){logger.warn("reporter","AppState listener binding failed",t)}}init(t){this.ctx=t}onAppStateChanged=t=>{"background"===t&&("function"==typeof this.flushEventQueue&&this.flushEventQueue(),Telemetry.get()?.flush())};async request(t,e){const r=extractCrashIds(e);try{const s=await fixAttrs(e);stripCrashIds(s);const a=t.getConfig();fetch(a.endpoint,{method:"POST",headers:{"Content-Type":"text/plain"},body:JSON.stringify(s)}).then(e=>{this.ackCrashes(t,r,!(!e||!e.ok))}).catch(e=>{this.catchHandle(e),this.ackCrashes(t,r,!1)})}catch(e){this.catchHandle(e),this.ackCrashes(t,r,!1)}}ackCrashes(t,e,r){if(e.length)try{t.emitter?.emit(CRASH_REPORT_ACK_EVENT,{crashIds:e,success:r})}catch(t){logger.warn("reporter","emit crash ack failed",t)}}catchHandle=t=>{logger.warn("reporter","sendRequest failed",t)};destroy(){this.appStateListener?.remove()}}export default RNReporter;
@@ -1,38 +1 @@
1
- "use strict";
2
-
3
- import { convertBundlesToLogGroup } from '@arms/rum-core';
4
- export class RNMonitorReporter {
5
- constructor(endpoint) {
6
- this.endpoint = this.buildMonitorEndpoint(endpoint);
7
- }
8
- send(data) {
9
- if (!data || data.length === 0) return;
10
- try {
11
- // 使用 rum-core 的 Protobuf 编码器将数据编码为 SLS LogGroup 二进制格式
12
- const protobufBody = convertBundlesToLogGroup(data);
13
- fetch(this.endpoint, {
14
- method: 'POST',
15
- headers: {
16
- 'Content-Type': 'application/x-protobuf',
17
- 'x-log-apiversion': '0.6.0',
18
- 'x-log-compresstype': '',
19
- 'x-log-date': new Date().toUTCString()
20
- },
21
- body: protobufBody
22
- }).catch(() => {
23
- // 静默处理,避免反馈循环(不调用 logger)
24
- });
25
- } catch (_) {
26
- // 吞掉异常,防止自监控影响宿主应用
27
- }
28
- }
29
- buildMonitorEndpoint(endpoint) {
30
- try {
31
- const url = new URL(endpoint);
32
- return `${url.origin}/rum/monitor`;
33
- } catch (_) {
34
- return endpoint;
35
- }
36
- }
37
- }
38
- //# sourceMappingURL=monitor-reporter.js.map
1
+ "use strict";import{convertBundlesToLogGroup}from"@arms/rum-core";export class RNMonitorReporter{constructor(o){this.endpoint=this.buildMonitorEndpoint(o)}send(o){if(o&&0!==o.length)try{const t=convertBundlesToLogGroup(o);fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/x-protobuf","x-log-apiversion":"0.6.0","x-log-compresstype":"","x-log-date":(new Date).toUTCString()},body:t}).catch(()=>{})}catch(o){}}buildMonitorEndpoint(o){try{return`${new URL(o).origin}/rum/monitor`}catch(t){return o}}}
@@ -1,84 +1 @@
1
- "use strict";
2
-
3
- import { isFunction, Shell, callMonitored } from '@arms/rum-core';
4
- import * as collectors from "./collector/index.js";
5
- import DefaultProcessor from "./processor/default-processor.js";
6
- import SessionProcessor from "./processor/session-processor.js";
7
- import Reporter from "./reporter/index.js";
8
- import { RNMonitorReporter } from "./reporter/monitor-reporter.js";
9
- import { VERSION } from "./utils/platform.js";
10
- import { RumSession } from "./utils/session.js";
11
- import { startTrackingViews, stopTrackingViews } from "./utils/view.js";
12
- const builtInCollectors = [...Object.values(collectors).filter(Collector => isFunction(Collector))];
13
- /**
14
- * 对外导出 shell 层, 所有 shell 层模型的 API 设计约定:
15
- * 1. API 命名空间按照 variables / functions / events 来组织
16
- * 2. 事件(events)的命名格式为:on[Will|Did]VerbNoun?,参考 https://code.visualstudio.com/api/references/vscode-api#events
17
- * 3. 基于 Disposable 模式,对于事件的绑定、快捷键的绑定函数,返回值则是解绑函数
18
- */
19
- export class ArmsRum extends Shell {
20
- version = VERSION;
21
-
22
- /**
23
- * 初始化
24
- */
25
- init(config) {
26
- this.client.useCollectors(builtInCollectors.map(Collector => callMonitored(() => new Collector(), undefined, [], 'shell', `init ${Collector.name}`)).filter(Boolean));
27
- this.client.useProcessors([new DefaultProcessor(), new SessionProcessor()]);
28
- this.client.useReporter(new Reporter());
29
- // 传入 MonitorReporter 激活自监控
30
- const monitorReporter = config.endpoint ? new RNMonitorReporter(config.endpoint) : undefined;
31
- this.client.init(config, new RumSession(), undefined, monitorReporter);
32
- return this;
33
- }
34
-
35
- /**
36
- * set config
37
- */
38
-
39
- setConfig(...params) {
40
- const ctx = this.client.getContext();
41
- if (params.length === 2) {
42
- const oldConfig = ctx.getConfig();
43
- ctx.setConfig({
44
- ...oldConfig,
45
- [params[0]]: params[1]
46
- });
47
- } else {
48
- ctx.setConfig(params[0]);
49
- }
50
- }
51
-
52
- /**
53
- * 开启路由变化监听,自动采集 PV 数据
54
- *
55
- * 必须在 NavigationContainer 的 `onReady` 回调中调用,以确保
56
- * navigationRef 已正确初始化。
57
- *
58
- * @example
59
- * ```tsx
60
- * <NavigationContainer
61
- * ref={navigationRef}
62
- * onReady={() => {
63
- * ArmsRum.startTrackingViews(navigationRef);
64
- * }}
65
- * >
66
- * ...
67
- * </NavigationContainer>
68
- * ```
69
- *
70
- * @param navigationRef - NavigationContainer 的 ref 引用
71
- */
72
- startTrackingViews(navigationRef) {
73
- if (!navigationRef) return;
74
- startTrackingViews(navigationRef);
75
- }
76
- stopTrackingViews() {
77
- stopTrackingViews();
78
- }
79
- getCollector(name) {
80
- return this.client.getCollectors().find(collector => collector.name === name);
81
- }
82
- }
83
- export default new ArmsRum();
84
- //# sourceMappingURL=shell.js.map
1
+ "use strict";import{isFunction,Shell,callMonitored}from"@arms/rum-core";import*as collectors from"./collector/index.js";import DefaultProcessor from"./processor/default-processor.js";import SessionProcessor from"./processor/session-processor.js";import Reporter from"./reporter/index.js";import{RNMonitorReporter}from"./reporter/monitor-reporter.js";import{VERSION}from"./utils/platform.js";import{RumSession}from"./utils/session.js";import{startTrackingViews,stopTrackingViews}from"./utils/view.js";const builtInCollectors=[...Object.values(collectors).filter(e=>isFunction(e))];export class ArmsRum extends Shell{version=VERSION;init(e){this.client.useCollectors(builtInCollectors.map(e=>callMonitored(()=>new e,void 0,[],"shell",`init ${e.name}`)).filter(Boolean)),this.client.useProcessors([new DefaultProcessor,new SessionProcessor]),this.client.useReporter(new Reporter);const o=e.endpoint?new RNMonitorReporter(e.endpoint):void 0;return this.client.init(e,new RumSession,void 0,o),this}setConfig(...e){const o=this.client.getContext();if(2===e.length){const s=o.getConfig();o.setConfig({...s,[e[0]]:e[1]})}else o.setConfig(e[0])}startTrackingViews(e){e&&startTrackingViews(e)}stopTrackingViews(){stopTrackingViews()}getCollector(e){return this.client.getCollectors().find(o=>o.name===e)}}export default new ArmsRum;
@@ -1,4 +1 @@
1
- "use strict";
2
-
3
- export {};
4
- //# sourceMappingURL=client.js.map
1
+ "use strict";export{};
@@ -1,33 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * 崩溃相关类型定义
5
- */
6
-
7
- /** 崩溃上下文同步事件名 */
8
- export const CRASH_CONTEXT_EVENT = 'crash_context_change';
9
-
10
- /** 崩溃上报确认事件名(reporter -> crash collector,用于 ack 后删除文件) */
11
- export const CRASH_REPORT_ACK_EVENT = 'crash_report_ack';
12
-
13
- /**
14
- * 挂在崩溃 RumEvent 上的瞬态字段名,携带 crash_id。
15
- * reporter 上报前提取用于 ack、并在序列化前剥离,不会发送到后端。
16
- */
17
- export const CRASH_ID_FIELD = '__rum_crash_id';
18
-
19
- /** 崩溃上报确认事件负载 */
20
-
21
- /**
22
- * 崩溃上下文快照(session / view 变更时同步到原生侧)。
23
- */
24
-
25
- /**
26
- * 原生崩溃栈帧数据结构。
27
- */
28
-
29
- /**
30
- * 原生崩溃数据结构(与原生侧 RumCrashReporter / CrashContextManager 写入的 JSON 对齐)。
31
- * 仅声明 JS 层会用到的字段,未列出的字段会通过 snapshots 透传给后端。
32
- */
33
- //# sourceMappingURL=crash.js.map
1
+ "use strict";export const CRASH_CONTEXT_EVENT="crash_context_change";export const CRASH_REPORT_ACK_EVENT="crash_report_ack";export const CRASH_ID_FIELD="__rum_crash_id";
@@ -1,2 +1 @@
1
- "use strict";
2
- //# sourceMappingURL=index.js.map
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";