@arms/rum-uniapp 0.1.3 → 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.
- package/README.md +128 -9
- package/dist/uniapp-sdk.js +1 -1
- package/es/collector/action/index.d.ts +14 -0
- package/es/collector/action/index.js +2 -61
- package/es/collector/exception/index.d.ts +37 -2
- package/es/collector/exception/index.js +49 -4
- package/es/collector/resource/api.d.ts +1 -1
- package/es/collector/resource/api.js +6 -4
- package/es/collector/view/pv.js +1 -1
- package/es/configManager.d.ts +13 -0
- package/es/configManager.js +5 -0
- package/es/reporter/index.js +2 -2
- package/es/reporter/monitor-reporter.d.ts +11 -0
- package/es/reporter/monitor-reporter.js +5 -0
- package/es/shell.d.ts +4 -2
- package/es/shell.js +8 -10
- package/es/utils/api.d.ts +1 -1
- package/es/utils/api.js +1 -1
- package/es/utils/mixin.d.ts +2 -2
- package/es/utils/mixin.js +9 -2
- package/es/utils/platform.d.ts +4 -2
- package/es/utils/platform.js +1 -1
- package/es/utils/session.d.ts +3 -1
- package/es/utils/session.js +2 -2
- package/es/utils/view.js +3 -4
- package/lib/collector/action/index.d.ts +14 -0
- package/lib/collector/action/index.js +2 -62
- package/lib/collector/exception/index.d.ts +37 -2
- package/lib/collector/exception/index.js +48 -4
- package/lib/collector/resource/api.d.ts +1 -1
- package/lib/collector/resource/api.js +6 -4
- package/lib/collector/view/pv.js +1 -1
- package/lib/configManager.d.ts +13 -0
- package/lib/configManager.js +5 -0
- package/lib/reporter/index.js +1 -1
- package/lib/reporter/monitor-reporter.d.ts +11 -0
- package/lib/reporter/monitor-reporter.js +5 -0
- package/lib/shell.d.ts +4 -2
- package/lib/shell.js +5 -7
- package/lib/utils/api.d.ts +1 -1
- package/lib/utils/api.js +1 -1
- package/lib/utils/mixin.d.ts +2 -2
- package/lib/utils/mixin.js +9 -2
- package/lib/utils/platform.d.ts +4 -2
- package/lib/utils/platform.js +1 -1
- package/lib/utils/session.d.ts +3 -1
- package/lib/utils/session.js +1 -1
- package/lib/utils/view.js +2 -3
- package/package.json +2 -2
|
@@ -1,61 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// // import { addPageListener, removePageListener } from "../../utils/hackPage";
|
|
4
|
-
//
|
|
5
|
-
// export default class ActionCollector implements ICollector {
|
|
6
|
-
// name = 'action-collector';
|
|
7
|
-
// private DELAY_TIME = 300;
|
|
8
|
-
// ctx: IContext;
|
|
9
|
-
// sendEvent: (payload: RumEvent) => void;
|
|
10
|
-
// events = ['tap'];
|
|
11
|
-
// lastEvent: RumActionEvent;
|
|
12
|
-
// timer: any;
|
|
13
|
-
//
|
|
14
|
-
// setup(ctx: IContext, sendEvent: (payload: RumEvent) => void) {
|
|
15
|
-
// const {collectors = {}} = ctx.getConfig();
|
|
16
|
-
// if (collectors.action === false) {
|
|
17
|
-
// return;
|
|
18
|
-
// }
|
|
19
|
-
// this.ctx = ctx;
|
|
20
|
-
// this.sendEvent = sendEvent;
|
|
21
|
-
// // addPageListener('*', this.onEvent)
|
|
22
|
-
// }
|
|
23
|
-
//
|
|
24
|
-
// onEvent = (e) => {
|
|
25
|
-
// if (e && this.events.includes(e.type) && e.target) {
|
|
26
|
-
// const {target, currentTarget, type} = e;
|
|
27
|
-
// const {dataset, id} = target;
|
|
28
|
-
// if (!id) return;
|
|
29
|
-
// if (currentTarget && id !== currentTarget.id) return;
|
|
30
|
-
// const view = getCurView(this.ctx);
|
|
31
|
-
// const event: RumActionEvent = {
|
|
32
|
-
// event_type: RumEventType.ACTION,
|
|
33
|
-
// type,
|
|
34
|
-
// name: id,
|
|
35
|
-
// snapshots: Object.keys(dataset).length ? JSON.stringify(dataset) : undefined,
|
|
36
|
-
// times: 1,
|
|
37
|
-
// view
|
|
38
|
-
// }
|
|
39
|
-
// clearTimeout(this.timer);
|
|
40
|
-
// if (this.lastEvent) {
|
|
41
|
-
// if (this.lastEvent.name !== event.name) {
|
|
42
|
-
// this.sendAction();
|
|
43
|
-
// } else {
|
|
44
|
-
// this.lastEvent.times += 1;
|
|
45
|
-
// }
|
|
46
|
-
// } else {
|
|
47
|
-
// this.lastEvent = event;
|
|
48
|
-
// }
|
|
49
|
-
// this.timer = setTimeout(this.sendAction, this.DELAY_TIME);
|
|
50
|
-
// }
|
|
51
|
-
// }
|
|
52
|
-
//
|
|
53
|
-
// sendAction = () => {
|
|
54
|
-
// this.sendEvent(this.lastEvent);
|
|
55
|
-
// this.lastEvent = null;
|
|
56
|
-
// }
|
|
57
|
-
//
|
|
58
|
-
// destroy() {
|
|
59
|
-
// // removePageListener('*', this.onEvent);
|
|
60
|
-
// }
|
|
61
|
-
// }
|
|
1
|
+
import{RumEventType}from"@arms/rum-core";import{addEventListener,removeEventListener}from"../../utils/mixin";import{getCurView}from"../../utils/view";var ActionCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="action-collector",this.DELAY_TIME=300,this.ctx=void 0,this.sendEvent=void 0,this.events=["tap","click"],this.lastEvent=void 0,this.timer=void 0,this.onEvent=function(b,c){if(c&&a.events.includes(c.type)){// 优先取 currentTarget(事件绑定元素),缺失时回退 target(实际触发元素)
|
|
2
|
+
var d=c.currentTarget||c.target||{},e=d.id,f=d.dataset;if(!e&&c.target&&(e=c.target.id,f=c.target.dataset),!!e){var g=getCurView(a.ctx),h={event_type:RumEventType.ACTION,type:c.type,name:e,snapshots:f?JSON.stringify({dataset:f}).substring(0,1e3):void 0,times:1,view:g};clearTimeout(a.timer),a.lastEvent?a.lastEvent.name===h.name?a.lastEvent.times+=1:(a.sendAction(),a.lastEvent=h):a.lastEvent=h,a.timer=setTimeout(a.sendAction,a.DELAY_TIME)}}},this.sendAction=function(){a.lastEvent&&(a.sendEvent(a.lastEvent),a.lastEvent=null)}}var b=a.prototype;return b.setup=function(a,b){var c=a.getConfig(),d=c.collectors,e=void 0===d?{}:d;!1===e.action||(this.ctx=a,this.sendEvent=b,addEventListener("action",this.onEvent))},b.destroy=function(){removeEventListener("action",this.onEvent)},a}();export{ActionCollector as default};
|
|
@@ -3,13 +3,48 @@ export default class ExceptionCollector implements ICollector {
|
|
|
3
3
|
name: string;
|
|
4
4
|
ctx: IContext;
|
|
5
5
|
sendEvent: (payload: RumEvent) => void;
|
|
6
|
+
private recentErrors;
|
|
7
|
+
private timerWrappers;
|
|
6
8
|
setup(ctx: IContext, sendEvent: (payload: RumEvent) => void): void;
|
|
7
9
|
hackOrigin(): void;
|
|
10
|
+
/**
|
|
11
|
+
* 仅在支持 addEventListener 的宿主(H5 window)上注册全局事件,
|
|
12
|
+
* App / 小程序环境安全跳过而非抛错中断后续注册
|
|
13
|
+
*/
|
|
14
|
+
safeAddEventListener(type: string, handler: Function): void;
|
|
15
|
+
/**
|
|
16
|
+
* App 端(plus 存在)补充引擎级异常通道。
|
|
17
|
+
* uni-app App 端的 App.onError 仅由 Vue errorHandler 触发,异步回调(timers、
|
|
18
|
+
* 原生回调等 Vue 管理范围外)中的未捕获异常由引擎异常处理器进入原生
|
|
19
|
+
* reportJSException 后终结,不回流 uni.onError / global error 事件:
|
|
20
|
+
* 1. 劫持 reportJSException(runtime 注入的全局函数):引擎级未捕获异常的收口,
|
|
21
|
+
* 原生按全局名调用时可被截获(机会性通道,取决于 runtime 调用方式),原函数照常执行
|
|
22
|
+
* 2. 包装 setTimeout / setInterval / setImmediate:确定性捕获 timers 回调异常,
|
|
23
|
+
* 上报后原样 rethrow 保持引擎原有行为
|
|
24
|
+
* 3. plus.globalEvent 的 error / unhandledrejection:防御式注册,若端上派发则自动生效
|
|
25
|
+
*/
|
|
26
|
+
hackAppRuntime(): void;
|
|
27
|
+
/**
|
|
28
|
+
* reportJSException 收口处理:参数形态无公开契约(观察为函数名 + 异常文本,
|
|
29
|
+
* 部分实现含 instanceId / errCode),逐参数解析:Error 对象优先,字符串拼接后
|
|
30
|
+
* 经 getErrorByStack 解析;字符串解析失败遵循既定的丢弃策略
|
|
31
|
+
*/
|
|
32
|
+
reportJSExceptionHandler: (...args: any[]) => void;
|
|
33
|
+
/**
|
|
34
|
+
* 包装 timers 全局函数:回调异常确定性捕获(App 端异步异常主场景),
|
|
35
|
+
* 上报后原样 rethrow,保持引擎对异常的原有处理路径
|
|
36
|
+
*/
|
|
37
|
+
wrapTimers(): void;
|
|
38
|
+
/**
|
|
39
|
+
* App 端多通道去重:timers 包装与 reportJSException 收口会对同一异常各触发
|
|
40
|
+
* 一次,窗口内 name+message 相同视为重复;环形清理 + 数量上限防泄漏
|
|
41
|
+
*/
|
|
42
|
+
isDuplicated(name: string, message: string): boolean;
|
|
8
43
|
vueError: (_: any, error: Error) => void;
|
|
9
|
-
uniError: (error:
|
|
44
|
+
uniError: (error: string) => void;
|
|
10
45
|
onError: (error: Error) => void;
|
|
11
46
|
onUnhandledRejection: (e: PromiseRejectionEvent) => void;
|
|
12
|
-
errorHandle: (event: any, source?: string) => void;
|
|
47
|
+
errorHandle: (event: any, source?: string, dedupe?: boolean) => void;
|
|
13
48
|
/**
|
|
14
49
|
* 根据stack获取Error信息
|
|
15
50
|
* TODO: 增加基于Stack解析filename和lineNumber的能力
|
|
@@ -1,8 +1,53 @@
|
|
|
1
|
-
import{interceptFunction,isFunction,isString,restoreFunction,RumEventType}from"@arms/rum-core";import{addEventListener}from"../../utils/mixin";import{sdk}from"../../utils/platform"
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import{interceptFunction,isFunction,isString,logger,restoreFunction,RumEventType}from"@arms/rum-core";import{addEventListener}from"../../utils/mixin";import{global2,sdk}from"../../utils/platform";// App 端 HTML5+ 运行时注入的全局对象,其余端(H5 / 小程序)不存在
|
|
2
|
+
// App 端多通道去重窗口:同一异常可能先被 timers 包装捕获并 rethrow,
|
|
3
|
+
// 随后又被 reportJSException 收口捕获,5s 内 name+message 相同视为同一事件
|
|
4
|
+
var DEDUPE_WINDOW=5e3,DEDUPE_MAX=50,ExceptionCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="exception-collector",this.ctx=void 0,this.sendEvent=void 0,this.recentErrors=[],this.timerWrappers=[],this.reportJSExceptionHandler=function(){for(var b,c,d=[],e=0;e<arguments.length;e++)c=0>e||arguments.length<=e?void 0:arguments[e],c instanceof Error?!b&&(b=c):c&&c.message?!b&&(b=c):isString(c)&&c&&d.push(c);return b?void a.errorHandle(b,"reportJSException",!0):void(!d.length||a.errorHandle(d.join("\n"),"reportJSException",!0))},this.vueError=function(b,c){a.errorHandle(c,"Vue.onError")},this.uniError=function(b){a.errorHandle(b,"uni.onError")},this.onError=function(b){a.errorHandle(b,"onError")},this.onUnhandledRejection=function(b){if(b){var c=b.reason;if(c){var d=c.errMsg;// 对 Uniapp 内置错误进行解析
|
|
5
|
+
if(d&&isString(d)){c=new Error(d),c.name="",c.stack="";for(var e,f=["navigateTo","redirectTo","appLaunch","switchTab","getLocation","onLocationChange"],g=0,h=f;g<h.length;g++)if(e=h[g],d.startsWith(e)){c.name=e;break}c.name||(c.name=d.split(":")[0])}a.errorHandle(c,"onUnhandledRejection")}}},this.errorHandle=function(b,c,d){void 0===c&&(c=""),void 0===d&&(d=!1);var e,f,g,h,i,j;if(b instanceof Object){if(e=b.name,f=b.message,g=b.filename||b.fileName,h=b.stack,i=b.lineno||b.lineNumber,j=b.colno||b.columnNumber,b.error instanceof Error){var k=b.error;e=k.name,f=k.message,h=k.stack}// 兜底:wx.onError 回调入参为 { message, stack } 对象(无 name 字段),
|
|
6
|
+
// 尝试从堆栈反解,仍失败则用 'Error' 兜底,避免异常被静默丢弃
|
|
7
|
+
if(!e&&isString(f)){var l=a.getErrorByStack(h||f);l&&l.name&&l.message&&(e=l.name,f=l.message),e=e||"Error",h=h||f}}else if("string"==typeof b){h=b;var m=a.getErrorByStack(b);m&&(e=m.name,f=m.message)}!e||!f||d&&a.isDuplicated(e,f)||a.sendEvent({event_type:RumEventType.EXCEPTION,source:c,type:"error",name:e,message:f,file:g,stack:h,line:i,column:j,times:1})}}var b=a.prototype;return b.setup=function(a,b){this.ctx=a,this.sendEvent=b,this.hackOrigin()},b.hackOrigin=function(){var a=this,b=this.ctx.getConfig(),c=b.collectors,d=void 0===c?{}:c;if(!1!==d.jsError){// 各注册点独立防护:原先共用一个 try 块,App 端(Weex JS 引擎)global 无
|
|
8
|
+
// addEventListener 抛 TypeError,导致 unhandledrejection 与 uni.onError
|
|
9
|
+
// 注册被整体跳过(Vue 同步异常经 mixin 通道不受影响,与其余通道全静默的现象一致)
|
|
10
|
+
try{addEventListener("onError",this.vueError)}catch(a){logger.warn("exception-collector","add vue onError listener failed",a)}if(this.safeAddEventListener("error",this.onError),this.safeAddEventListener("unhandledrejection",this.onUnhandledRejection),isFunction(sdk.onError))try{sdk.onError(this.uniError)}catch(a){logger.warn("exception-collector","uni.onError register failed",a)}// 无 window 级 unhandledrejection 的端(小程序等)退回 uni API 通道;
|
|
11
|
+
// H5 端已有 window 事件,跳过避免双通道重复上报
|
|
12
|
+
if(!isFunction(global2.addEventListener)&&isFunction(sdk.onUnhandledRejection))try{sdk.onUnhandledRejection(this.onUnhandledRejection)}catch(a){logger.warn("exception-collector","uni.onUnhandledRejection register failed",a)}this.hackAppRuntime()}!1!==d.consoleError&&interceptFunction(console,"error",function(b){a.errorHandle(b,"console.error")})}/**
|
|
13
|
+
* 仅在支持 addEventListener 的宿主(H5 window)上注册全局事件,
|
|
14
|
+
* App / 小程序环境安全跳过而非抛错中断后续注册
|
|
15
|
+
*/,b.safeAddEventListener=function(a,b){try{isFunction(global2.addEventListener)&&global2.addEventListener(a,b)}catch(b){logger.warn("exception-collector","add "+a+" listener failed",b)}}/**
|
|
16
|
+
* App 端(plus 存在)补充引擎级异常通道。
|
|
17
|
+
* uni-app App 端的 App.onError 仅由 Vue errorHandler 触发,异步回调(timers、
|
|
18
|
+
* 原生回调等 Vue 管理范围外)中的未捕获异常由引擎异常处理器进入原生
|
|
19
|
+
* reportJSException 后终结,不回流 uni.onError / global error 事件:
|
|
20
|
+
* 1. 劫持 reportJSException(runtime 注入的全局函数):引擎级未捕获异常的收口,
|
|
21
|
+
* 原生按全局名调用时可被截获(机会性通道,取决于 runtime 调用方式),原函数照常执行
|
|
22
|
+
* 2. 包装 setTimeout / setInterval / setImmediate:确定性捕获 timers 回调异常,
|
|
23
|
+
* 上报后原样 rethrow 保持引擎原有行为
|
|
24
|
+
* 3. plus.globalEvent 的 error / unhandledrejection:防御式注册,若端上派发则自动生效
|
|
25
|
+
*/,b.hackAppRuntime=function(){var a,b=this;try{// 无 plus(H5 / 小程序)时整体跳过,App 专属通道不注入
|
|
26
|
+
if("undefined"==typeof plus||!plus)return;plus.globalEvent&&(a=plus.globalEvent)}catch(a){return}if(interceptFunction(global2,"reportJSException",this.reportJSExceptionHandler),this.wrapTimers(),a&&isFunction(a.addEventListener))try{a.addEventListener("error",function(a){try{b.errorHandle(a,"plus.globalEvent",!0)}catch(a){logger.warn("exception-collector","plus.globalEvent error failed",a)}}),a.addEventListener("unhandledrejection",function(a){if(a&&a.reason)try{b.errorHandle(a.reason,"plus.globalEvent",!0)}catch(a){logger.warn("exception-collector","plus.globalEvent unhandledrejection failed",a)}})}catch(a){logger.warn("exception-collector","plus.globalEvent register failed",a)}}/**
|
|
27
|
+
* reportJSException 收口处理:参数形态无公开契约(观察为函数名 + 异常文本,
|
|
28
|
+
* 部分实现含 instanceId / errCode),逐参数解析:Error 对象优先,字符串拼接后
|
|
29
|
+
* 经 getErrorByStack 解析;字符串解析失败遵循既定的丢弃策略
|
|
30
|
+
*/,b.wrapTimers=/**
|
|
31
|
+
* 包装 timers 全局函数:回调异常确定性捕获(App 端异步异常主场景),
|
|
32
|
+
* 上报后原样 rethrow,保持引擎对异常的原有处理路径
|
|
33
|
+
*/function(){for(var a,b=this,c=this,d=["setTimeout","setInterval","setImmediate"],e=function a(){var e,g=d[f];try{e=global2[g]}catch(a){return 0;// continue
|
|
34
|
+
}if(!isFunction(e)||e.__armsTimerWrapped)return 0;// continue
|
|
35
|
+
var h=function a(){for(var b=arguments.length,d=Array(b),f=0;f<b;f++)d[f]=arguments[f];var h=d[0];if(!isFunction(h))return e.apply(this,d);var i=function a(){try{return h.apply(this,arguments)}catch(a){try{c.errorHandle(a,g,!0)}catch(a){logger.warn("exception-collector","report timer error failed",a)}throw a}};return i.__armsOriginalCallback=h,d[0]=i,e.apply(this,d)};try{Object.defineProperty(h,"name",{value:g,configurable:!0})}catch(a){// 部分引擎 name 不可写,不影响包装
|
|
36
|
+
}h.toString=function(){return e.toString()},h.__armsTimerWrapped=!0;try{global2[g]=h,b.timerWrappers.push({name:g,original:e})}catch(a){logger.warn("exception-collector","wrap "+g+" failed",a)}},f=0;f<d.length;f++)a=e(),0===a}/**
|
|
37
|
+
* App 端多通道去重:timers 包装与 reportJSException 收口会对同一异常各触发
|
|
38
|
+
* 一次,窗口内 name+message 相同视为重复;环形清理 + 数量上限防泄漏
|
|
39
|
+
*/,b.isDuplicated=function c(a,b){for(var d=Date.now(),e=this.recentErrors;e.length&&d-e[0].time>DEDUPE_WINDOW;)e.shift();for(var f=a+"|"+b,g=0;g<e.length;g++)if(e[g].key===f)return!0;return e.push({key:f,time:d}),e.length>DEDUPE_MAX&&e.shift(),!1},b.getErrorByStack=/**
|
|
4
40
|
* 根据stack获取Error信息
|
|
5
41
|
* TODO: 增加基于Stack解析filename和lineNumber的能力
|
|
6
42
|
* @param stack
|
|
7
43
|
* @returns
|
|
8
|
-
*/function(a){void 0===a&&(a="");var
|
|
44
|
+
*/function b(a){void 0===a&&(a="");var c=a.split("\n");if(!(2>c.length)){// 优先直接扫描 'Name: message' 错误头部行,不依赖其与首帧的位置关系
|
|
45
|
+
// (V8 位于首行、微信 iOS/JSC 位于第三行,一次实现覆盖双端);类名前缀可选,兼容纯 'Error: msg'
|
|
46
|
+
for(var d,e=function b(a){var c=a.trim();return c.startsWith("at ")||/@.+:\d+:\d+/.test(c)||/@(\[native code\])?$/.test(c)},f=/^\s*([\w$]*(?:Error|Exception))\s*:\s*(.+)$/,g=0;g<c.length;g++)if(d=f.exec(c[g]),d)return{name:d[1],message:d[2]};// 后备:按 '首帧上一行即头部行' 的位置关系解析(覆盖自定义错误名等非 Error/Exception 后缀场景)
|
|
47
|
+
for(var h=1;h<c.length;h++)if(e(c[h])){var j=c[h-1];// 上一行也是堆栈帧(如 Safari 扩展的纯帧堆栈),说明无头部行,交由上层兜底
|
|
48
|
+
if(e(j))return;var k=j.indexOf(": ");return-1===k?{name:"",message:j}:{name:j.substring(0,k),message:j.substring(k+2)}}}// 兼容多引擎堆栈帧格式(参考 Sentry chrome/gecko StackLineParser):
|
|
49
|
+
// 1. V8/Chrome:'at fn (url:line:col)' / 'at url:line:col'
|
|
50
|
+
// 2. JavaScriptCore/Gecko(App 端/iOS):'fn@url:line:col' / '@url:line:col'
|
|
51
|
+
// 3. 无行列号帧:'forEach@[native code]' / '_onNativeTimer@'
|
|
52
|
+
},b.destroy=function a(){restoreFunction(console,"error"),restoreFunction(global2,"reportJSException");for(var b=0;b<this.timerWrappers.length;b++){var c=this.timerWrappers[b],d=c.name,e=c.original;try{global2[d]&&global2[d].__armsTimerWrapped&&(global2[d]=e)}catch(a){// 还原失败静默忽略
|
|
53
|
+
}}this.timerWrappers=[],this.recentErrors=[]},a}();export{ExceptionCollector as default};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ICollector, IContext, ITracingHeaders, RumEvent } from '@arms/rum-core';
|
|
2
|
-
import { IApiAttr, Options } from
|
|
2
|
+
import { IApiAttr, Options } from '../../utils/api';
|
|
3
3
|
export default class ApiCollector implements ICollector {
|
|
4
4
|
name: string;
|
|
5
5
|
ctx: IContext;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import _extends from"@babel/runtime/helpers/extends";import _asyncToGenerator from"@babel/runtime/helpers/asyncToGenerator";import _regeneratorRuntime from"@babel/runtime/regenerator";import{find,generateGUID,generateSpanId,generateTraceId,isFunction,makeTracingHeaders,matchList,parseTracingOptions,performDraw,RumEventType,urlMatch,ONE_DAY}from"@arms/rum-core";import{sdk,appName}from"../../utils/platform";import{getPathByURL,isEndpoint}from"../../utils/url";import{getCurrentTime,getStringSize}from"../../utils/base";import{getCurView}from"../../utils/view";import{reviseApiAttr}from"../../utils/api";var ApiCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="api-collector",this.ctx=void 0,this.sendEvent=void 0,this.sendApi=/*#__PURE__*/function(){var b=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function e(b,c,d){var f,g,h,i,j,k,l,m,n,o,p;return _regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(f=a.ctx.getConfig(),g=f.evaluateApi,h=c.statusCode,i=c.status,j=c.errMsg,k=c.errorMessage,l=c.message,!isFunction(g)){e.next=4;break}return e.prev=1,0===b.success&&(m=new Error("request error")),e.next=2,g(d,c,m);case 2:n=e.sent,b=_extends({},b,reviseApiAttr(n)),e.next=4;break;case 3:e.prev=3,p=e["catch"](1);case 4:if(o=_extends({event_type:RumEventType.RESOURCE,type:"api",status_code:i||h,message:k||j||l,duration:getCurrentTime()-b.timestamp,times:1},b),!(o.duration>ONE_DAY)){e.next=5;break}return e.abrupt("return");case 5:a.sendEvent(o);case 6:case"end":return e.stop()}},e,null,[[1,3]])}));return function(){return b.apply(this,arguments)}}()}var b=a.prototype;return b.setup=// origin = {
|
|
1
|
+
import _extends from"@babel/runtime/helpers/extends";import _asyncToGenerator from"@babel/runtime/helpers/asyncToGenerator";import _regeneratorRuntime from"@babel/runtime/regenerator";import{find,generateGUID,generateSpanId,generateTraceId,isFunction,makeTracingHeaders,matchList,parseTracingOptions,performDraw,RumEventType,urlMatch,ONE_DAY,logger}from"@arms/rum-core";import{sdk,appName}from"../../utils/platform";import{getPathByURL,isEndpoint}from"../../utils/url";import{getCurrentTime,getStringSize}from"../../utils/base";import{getCurView}from"../../utils/view";import{reviseApiAttr}from"../../utils/api";var ApiCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="api-collector",this.ctx=void 0,this.sendEvent=void 0,this.sendApi=/*#__PURE__*/function(){var b=_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function e(b,c,d){var f,g,h,i,j,k,l,m,n,o,p;return _regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(f=a.ctx.getConfig(),g=f.evaluateApi,h=c.statusCode,i=c.status,j=c.errMsg,k=c.errorMessage,l=c.message,!isFunction(g)){e.next=4;break}return e.prev=1,0===b.success&&(m=new Error("request error")),e.next=2,g(d,c,m);case 2:n=e.sent,b=_extends({},b,reviseApiAttr(n)),e.next=4;break;case 3:e.prev=3,p=e["catch"](1),logger.error("api-collector","evaluateApi failed",p);case 4:if(o=_extends({event_type:RumEventType.RESOURCE,type:"api",status_code:i||h,message:k||j||l,duration:getCurrentTime()-b.timestamp,times:1},b),!(o.duration>ONE_DAY)){e.next=5;break}return e.abrupt("return");case 5:a.sendEvent(o);case 6:case"end":return e.stop()}},e,null,[[1,3]])}));return function(){return b.apply(this,arguments)}}()}var b=a.prototype;return b.setup=// origin = {
|
|
2
2
|
// request: sdk.request
|
|
3
3
|
// }
|
|
4
4
|
function(a,b){var c=a.getConfig(),d=c.collectors,e=void 0===d?{}:d;!1===e.api||(// Object.keys(this.origin).forEach((key) => this.hackRequest(key));
|
|
5
|
-
this.ctx=a,this.sendEvent=b,this.interceptorRequest())},b.interceptorRequest=function(){if(isFunction(sdk.addInterceptor)){var a=this;sdk.addInterceptor("request",{
|
|
5
|
+
this.ctx=a,this.sendEvent=b,this.interceptorRequest())},b.interceptorRequest=function(){if(isFunction(sdk.addInterceptor)){var a=this;sdk.addInterceptor("request",{// 用 logger.wrap 包装拦截回调:采集异常自动上报,同时隔离故障,避免影响业务请求
|
|
6
|
+
invoke:logger.wrap(function(b){a.rebuildRequestOptions(b)},"api-collector","intercept request failed")})}},b.injectTracing=function(a,b){var c,d=this.ctx.getConfig(),e=d.tracing,f=d.pid,g=d.version,h=void 0===g?"1.0.0":g,i=parseTracingOptions(e),j=i.enable,k=i.sample,l=i.propagatorTypes,m=i.allowedUrls,n=i.tracestate,o=i.baggage;if(j){var p=find(m,function(b){return matchList([b.match],a.url)});if(p){var q=p.propagatorTypes;0===q.length&&(q=l);// skywalking
|
|
6
7
|
var r=!1;q.includes("sw8")&&(q=["sw8"],r=!0);var s=r?generateGUID():generateTraceId(),t=r?generateGUID():generateSpanId(),u=performDraw(k),v=this.ctx.session.getUserId(),w=this.ctx.session.getSessionId(),x=void 0===n||n?"rum=v2&uniapp&"+f+"&"+w+"&"+v:void 0,y=void 0!==o&&o?"rum=v2,appType=uniapp,pid="+f+",sid="+w+",uid="+v:void 0,z=makeTracingHeaders(s,t,u,q,{tracestate:x,baggage:y,appId:f,appVersion:h,viewName:null===(c=a.view)||void 0===c?void 0:c.name,host:appName});u&&(a.trace_id=s,a.trace_data=JSON.stringify({spanId:t,sample:k,sampled:u,header:z})),b(z)}}}// hackRequest(key) {
|
|
7
8
|
// const self = this;
|
|
8
9
|
// if (!isFunction(sdk[key])) return;
|
|
@@ -25,8 +26,9 @@ var r=!1;q.includes("sw8")&&(q=["sw8"],r=!0);var s=r?generateGUID():generateTrac
|
|
|
25
26
|
if(isEndpoint(this.ctx,c)||urlMatch(c))return a;// const newOptions = {
|
|
26
27
|
// ...options,
|
|
27
28
|
// };
|
|
28
|
-
var i={view:getCurView(this.ctx),timestamp:h,url:c,name:this.getResourceName(c),method:a.method||"GET"};return this.injectTracing(i,function(b){a.header=_extends({},g,b)}),a.success=function(){i.success=1;for(var a=arguments.length,b=Array(a),c=0;c<a;c++)b[c]=arguments[c];d&&d.apply(this,b)},a.fail=function(){i.success=0;for(var a=arguments.length,b=Array(a),c=0;c<a;c++)b[c]=arguments[c];e&&e.apply(this,b)},a.complete=function(){for(var c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];var g=_extends({},d[0]);try{
|
|
29
|
-
|
|
29
|
+
var i={view:getCurView(this.ctx),timestamp:h,url:c,name:this.getResourceName(c),method:a.method||"GET"};return this.injectTracing(i,function(b){a.header=_extends({},g,b)}),a.success=function(){i.success=1;for(var a=arguments.length,b=Array(a),c=0;c<a;c++)b[c]=arguments[c];d&&d.apply(this,b)},a.fail=function(){i.success=0;for(var a=arguments.length,b=Array(a),c=0;c<a;c++)b[c]=arguments[c];e&&e.apply(this,b)},a.complete=function(){for(var c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];var g=_extends({},d[0]);try{// 对齐 Browser 端 getResourceSuccessByCode:有 HTTP 状态码时按 [200, 300) 判定,
|
|
30
|
+
// 无状态码时保留原网络回调结果(success=1/fail=0)作为兜底
|
|
31
|
+
var h=g.statusCode;if(h){var j=+h;i.success=200<=j&&300>j?1:0}i.size=getStringSize(JSON.stringify(g)),b.sendApi(i,g,a)}catch(a){logger.error("api-collector","process response failed",a)}f&&f.apply(this,d)},a},b.getResourceName=function(a){var b,c=this.ctx.getConfig(),d=c.parseResourceName;return b=isFunction(d)?d(a):getPathByURL(a),b}// /**
|
|
30
32
|
// * 解析小程序的性能数据
|
|
31
33
|
// * 参考:https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html
|
|
32
34
|
// * https://opendocs.alipay.com/mini/api/owycmh?pathHash=c91640f8
|
package/es/collector/view/pv.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import _extends from"@babel/runtime/helpers/extends";import{isFunction,RumEventType}from"@arms/rum-core";import{getCurView}from"../../utils/view";import{sdk}from"../../utils/platform";var KEYS=["navigateTo","redirectTo","switchTab"],PvCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="pv-collector",this.ctx=void 0,this.sendEvent=void 0,this.timer=void 0,this.sendPv=function(){var b=getCurView(a.ctx);b&&clearInterval(a.timer),b&&"_noReport"in b&&(delete b._noReport,a.sendEvent(_extends({event_type:RumEventType.VIEW,type:"pv",loading_type:"initial_load"},b)))}}var b=a.prototype;return b.setup=function(a,b){var c=this;this.ctx=a,this.sendEvent=b,setTimeout(this.sendPv,100),this.timer=setInterval(function(){c.sendPv()},100),isFunction(sdk.addInterceptor)&&KEYS.forEach(function(a){sdk.addInterceptor(a,{success:c.sendPv})})},b.destroy=function(){},a}();export{PvCollector as default};
|
|
1
|
+
import _extends from"@babel/runtime/helpers/extends";import{isFunction,logger,RumEventType}from"@arms/rum-core";import{getCurView}from"../../utils/view";import{sdk}from"../../utils/platform";var KEYS=["navigateTo","redirectTo","switchTab"],PvCollector=/*#__PURE__*/function(){function a(){var a=this;this.name="pv-collector",this.ctx=void 0,this.sendEvent=void 0,this.timer=void 0,this.sendPv=logger.wrap(function(){var b=getCurView(a.ctx);b&&clearInterval(a.timer),b&&"_noReport"in b&&(delete b._noReport,a.sendEvent(_extends({event_type:RumEventType.VIEW,type:"pv",loading_type:"initial_load"},b)))},"pv-collector","sendPv failed")}var b=a.prototype;return b.setup=function(a,b){var c=this;this.ctx=a,this.sendEvent=b,setTimeout(this.sendPv,100),this.timer=setInterval(function(){c.sendPv()},100),isFunction(sdk.addInterceptor)&&KEYS.forEach(function(a){sdk.addInterceptor(a,{success:c.sendPv})})},b.destroy=function(){},a}();export{PvCollector as default};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ConfigManager, IContext, IConfiguration, ICacheConfiguration } from '@arms/rum-core';
|
|
2
|
+
import { IUniConfig } from './types/client';
|
|
3
|
+
export default class UniConfigManager extends ConfigManager {
|
|
4
|
+
private version;
|
|
5
|
+
fetchRemoteCfg(config: IConfiguration): Promise<unknown>;
|
|
6
|
+
private getV1Config;
|
|
7
|
+
private getV2Config;
|
|
8
|
+
getCacheConfig(): (ICacheConfiguration & Record<"pid", unknown>) | (ICacheConfiguration & Record<"endpoint", unknown>);
|
|
9
|
+
setCacheConfig(remoteCfg: ICacheConfiguration): void;
|
|
10
|
+
getRemoteConfigUrl(): string;
|
|
11
|
+
parseConfig(json: any): Partial<IUniConfig>;
|
|
12
|
+
}
|
|
13
|
+
export declare function checkEnable(ctx: IContext, key: string, def?: boolean): boolean;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import _inheritsLoose from"@babel/runtime/helpers/inheritsLoose";import{ConfigManager,getUrlParams,parseRule2Match,isBoolean,isObject,logger}from"@arms/rum-core";import{sdk,getStorageSync,setStorageSync}from"./utils/platform";import{getURL}from"./utils/url";var LOCAL_STORE_CONFIG_KEY="arms_rum2_local_config";function parseV2Config(a){var b,c={};c.enable=null===(b=a.enable)||void 0===b||b;// 处理 Session 配置
|
|
2
|
+
var d=a.session;if(d){var e,f,g={};g.sampling=null!==(e=d.sampling)&&void 0!==e?e:100,g.storage=null!==(f=d.storage)&&void 0!==f?f:"auto",c.sessionConfig=g}// 处理上报配置
|
|
3
|
+
var h=a.report;if(h){var i={};i.flushTime=h.flush_interval,i.maxEventCount=h.max_batch_count,c.reportConfig=i}// 处理链路追踪
|
|
4
|
+
var j=a.tracing;if(j){var k,l={};l.enable=null===(k=j.enable)||void 0===k||k;var m=[];(j.rules||[]).forEach(function(a){var b={enable:a.enable,tracestate:a.tracestate,baggage:a.baggage,propagatorTypes:a.protocols,sampling:a.sampling};return"{location.origin}"===a.match?void(l=Object.assign({},l,b)):void(b.match=parseRule2Match(a),m.push(b))}),l.allowedUrls=m,c.tracing=l}// 处理采集器
|
|
5
|
+
var n=a.collectors;if(n&&Array.isArray(n)&&0<n.length){var o={};n.forEach(function(a){var b=a.name;if(b){var c=Object.assign({},a),d=a.filters;0<(null===d||void 0===d?void 0:d.length)&&(c.filters=c.filters.map(function(a){return parseRule2Match(a)})),o[b]=c}}),c.collectors=Object.assign({},c.collectors,o)}return c}var UniConfigManager=/*#__PURE__*/function(a){function b(){for(var b,c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];return b=a.call.apply(a,[this].concat(d))||this,b.version="v2",b}_inheritsLoose(b,a);var c=b.prototype;return c.fetchRemoteCfg=function(){var a=this.getRemoteConfigUrl();return a?a.includes(".rum.aliyuncs.com")?(this.version="v1",this.getV1Config(a)):this.getV2Config(a):void 0},c.getV1Config=function(a){return new Promise(function(b,c){sdk.request({url:a,method:"GET",success:function(a){b(a)},fail:function(a){c(a)}})})},c.getV2Config=function(a){var b=getUrlParams(a),c={instanceId:"",agentType:"rum_web_sdk",attributes:b,instanceConfigs:[{configType:"rum_web_config",version:1}],capabilities:2};return new Promise(function(b,d){sdk.request({url:a,method:"POST",data:JSON.stringify(c),header:{"Content-Type":"application/json","x-log-apiversion":"0.6.0"},success:function(a){b(a)},fail:function(a){d(a)}})})},c.getCacheConfig=function(){var a=getStorageSync(LOCAL_STORE_CONFIG_KEY);if(a){var b=this.currentConfig;try{var c=JSON.parse(a);if("pid"in c&&c.pid===b.pid||"endpoint"in c&&c.endpoint)return c.content=this.parseConfig(c.content),c}catch(a){logger.warn("configManager","Failed to read cache config",a)}}},c.setCacheConfig=function(a){var b=this.currentConfig,c=Object.assign({},a,{pid:b.pid,endpoint:b.endpoint});setStorageSync(LOCAL_STORE_CONFIG_KEY,JSON.stringify(c))},c.getRemoteConfigUrl=function(){var a=this.currentConfig,b=a.pid,c=a.remoteConfig,d=a.endpoint,e=c||{},f=e.url,g=e.region;if(f)return f;if(b){var h=b.split("@");return!h||2>h.length?void 0:"https://"+h[0]+"-sdk.rum.aliyuncs.com/config/"+(g||"cn-hangzhou")+"/"+h[1]+"?t="+Date.now()}var i=getURL(d),j=getUrlParams(d);return i.protocol+"://"+i.hostname+"/agentconfig?workspace="+j.workspace+"&service="+j.service_id},c.parseConfig=function(a){try{var b=a.data||a,c=b.instanceConfigs[0].config;return"v2"===this.version?parseV2Config(JSON.parse(c)):a}catch(b){return a}},b}(ConfigManager);export{UniConfigManager as default};export function checkEnable(a,b,c){var d;void 0===c&&(c=!0);var e=a.getConfig();if(!1===e.enable)return!1;var f=null===(d=e.collectors)||void 0===d?void 0:d[b];return isBoolean(f)?f:isObject(f)&&"enable"in f?f.enable:c}
|
package/es/reporter/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import _inheritsLoose from"@babel/runtime/helpers/inheritsLoose";import{isFunction,Reporter}from"@arms/rum-core";import{sdk,fixAttrs}from"../utils/platform";/**
|
|
1
|
+
import _inheritsLoose from"@babel/runtime/helpers/inheritsLoose";import{isFunction,logger,Reporter}from"@arms/rum-core";import{sdk,fixAttrs}from"../utils/platform";/**
|
|
2
2
|
* uni-app reporter
|
|
3
|
-
*/var UniReporter=/*#__PURE__*/function(a){function b(){for(var b,c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];return b=a.call.apply(a,[this].concat(d))||this,b.name="uni-reporter",b}_inheritsLoose(b,a);var c=b.prototype;return c.init=function(){var a=this;isFunction(sdk.onAppHide)&&sdk.onAppHide(function(){a.flushEventQueue()})},c.request=function(a,b){var c=a.getConfig();fixAttrs(b).then(function(a){sdk.request({url:c.endpoint,method:"POST",header:{"Content-Type":"text/plain"},dataType:"text",data:JSON.stringify(a)})})["catch"](function(a){
|
|
3
|
+
*/var UniReporter=/*#__PURE__*/function(a){function b(){for(var b,c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];return b=a.call.apply(a,[this].concat(d))||this,b.name="uni-reporter",b}_inheritsLoose(b,a);var c=b.prototype;return c.init=function(){var a=this;isFunction(sdk.onAppHide)&&sdk.onAppHide(function(){a.flushEventQueue()})},c.request=function(a,b){var c=a.getConfig();fixAttrs(b).then(function(a){sdk.request({url:c.endpoint,method:"POST",header:{"Content-Type":"text/plain"},dataType:"text",data:JSON.stringify(a)})})["catch"](function(a){logger.warn("uni-reporter","request failed",a)})},b}(Reporter);export default UniReporter;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IMonitorReporter, MonitorEventBundle } from '@arms/rum-core';
|
|
2
|
+
/**
|
|
3
|
+
* uni-app 自监控上报器
|
|
4
|
+
* 将 Telemetry 采集的自监控数据编码为 protobuf,通过 uni.request 上报
|
|
5
|
+
*/
|
|
6
|
+
export declare class UniMonitorReporter implements IMonitorReporter {
|
|
7
|
+
private endpoint;
|
|
8
|
+
constructor(endpoint: string);
|
|
9
|
+
send(data: MonitorEventBundle[]): void;
|
|
10
|
+
private buildMonitorEndpoint;
|
|
11
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{convertBundlesToLogGroup,logger}from"@arms/rum-core";import{sdk}from"../utils/platform";import{getURL}from"../utils/url";/**
|
|
2
|
+
* uni-app 自监控上报器
|
|
3
|
+
* 将 Telemetry 采集的自监控数据编码为 protobuf,通过 uni.request 上报
|
|
4
|
+
*/export var UniMonitorReporter=/*#__PURE__*/function(){function a(a){this.endpoint=void 0,this.endpoint=this.buildMonitorEndpoint(a)}var b=a.prototype;return b.send=function(a){if(a&&0!==a.length)try{var b=convertBundlesToLogGroup(a);sdk.request({url:this.endpoint,method:"POST",header:{"Content-Type":"application/x-protobuf","x-log-apiversion":"0.6.0","x-log-compresstype":"","x-log-date":new Date().toUTCString()},// uni.request 支持发送 ArrayBuffer 二进制数据
|
|
5
|
+
data:b.buffer})}catch(a){logger.warn("monitor-reporter","Monitor data send failed",a)}},b.buildMonitorEndpoint=function(a){try{var b=getURL(a);return b.protocol+"://"+b.host+"/rum/monitor"}catch(b){return a}},a}();
|
package/es/shell.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Shell } from '@arms/rum-core';
|
|
2
|
-
import { IUniConfig, Vue } from
|
|
2
|
+
import { IUniConfig, Vue } from './types/client';
|
|
3
3
|
/**
|
|
4
4
|
* 对外导出 shell 层, 所有 shell 层模型的 API 设计约定:
|
|
5
5
|
* 1. API 命名空间按照 variables / functions / events 来组织
|
|
@@ -8,10 +8,12 @@ import { IUniConfig, Vue } from "./types/client";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class ArmsRum extends Shell {
|
|
10
10
|
version: string;
|
|
11
|
+
private configManager;
|
|
11
12
|
/**
|
|
12
13
|
* 初始化
|
|
13
14
|
*/
|
|
14
|
-
init(config: IUniConfig):
|
|
15
|
+
init(config: IUniConfig): Promise<Shell>;
|
|
16
|
+
getConfig(): import("@arms/rum-core").IConfiguration;
|
|
15
17
|
/**
|
|
16
18
|
* set config
|
|
17
19
|
*/
|
package/es/shell.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ExceptionCollector from"./collector/exception";import ApiCollector from"./collector/resource/api"
|
|
3
|
-
import
|
|
4
|
-
import{VERSION}from"./utils/platform";import{RumSession}from"./utils/session";import{mixin}from"./utils/mixin";import{getCurViews}from"./utils/view";/**
|
|
1
|
+
import _inheritsLoose from"@babel/runtime/helpers/inheritsLoose";import{isFunction,logger,Shell,Telemetry}from"@arms/rum-core";import PvCollector from"./collector/view/pv";// import PerfCollector from './collector/view/perf';
|
|
2
|
+
import ExceptionCollector from"./collector/exception";import ApiCollector from"./collector/resource/api";import ActionCollector from"./collector/action";import DefaultProcessor from"./processor/default-processor";import SessionProcessor from"./processor/session-processor";import Reporter from"./reporter";import{UniMonitorReporter}from"./reporter/monitor-reporter";// import { getNetType } from "./utils/network";
|
|
3
|
+
import{sdk,VERSION}from"./utils/platform";import{RumSession}from"./utils/session";import{mixin}from"./utils/mixin";import{getCurViews}from"./utils/view";import UniConfigManager from"./configManager";/**
|
|
5
4
|
* 对外导出 shell 层, 所有 shell 层模型的 API 设计约定:
|
|
6
5
|
* 1. API 命名空间按照 variables / functions / events 来组织
|
|
7
6
|
* 2. 事件(events)的命名格式为:on[Will|Did]VerbNoun?,参考 https://code.visualstudio.com/api/references/vscode-api#events
|
|
8
7
|
* 3. 基于 Disposable 模式,对于事件的绑定、快捷键的绑定函数,返回值则是解绑函数
|
|
9
|
-
*/export var ArmsRum=/*#__PURE__*/function(a){function b(){for(var b,c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];return b=a.call.apply(a,[this].concat(d))||this,b.version=VERSION,b}_inheritsLoose(b,a);var c=b.prototype;return c.init=/**
|
|
8
|
+
*/export var ArmsRum=/*#__PURE__*/function(a){function b(){for(var b,c=arguments.length,d=Array(c),e=0;e<c;e++)d[e]=arguments[e];return b=a.call.apply(a,[this].concat(d))||this,b.version=VERSION,b.configManager=void 0,b}_inheritsLoose(b,a);var c=b.prototype;return c.init=/**
|
|
10
9
|
* 初始化
|
|
11
|
-
*/function(a){a.vue&&
|
|
12
|
-
new ExceptionCollector,new ApiCollector
|
|
13
|
-
]),this.client.useProcessors([new DefaultProcessor,new SessionProcessor]),this.client.useReporter(new Reporter),this.client.init(a,new RumSession);// 监听网络类型变化
|
|
10
|
+
*/function(a){var b=this;return this.configManager=new UniConfigManager,Promise.resolve().then(function(){return b.configManager.init(a)})["catch"](function(a){logger.warn("shell","configManager init error",a)}).then(function(){var a=b.configManager.getConfig();if(!1===a.enable)return b;a.vue&&b.setVue(a.vue),b.client.useCollectors([new PvCollector,// new PerfCollector(),
|
|
11
|
+
new ExceptionCollector,new ApiCollector,new ActionCollector]),b.client.useProcessors([new DefaultProcessor,new SessionProcessor]),b.client.useReporter(new Reporter),b.client.init(a,new RumSession,b.configManager,new UniMonitorReporter(a.endpoint));// 监听网络类型变化
|
|
14
12
|
// getNetType(this.updateNetType);
|
|
15
|
-
var b
|
|
13
|
+
var c=b.client.getContext();return c.getViews=getCurViews,isFunction(sdk.onAppHide)&&sdk.onAppHide(function(){var a;null===(a=Telemetry.get())||void 0===a?void 0:a.flush()}),b})},c.getConfig=function(){var a;return null===(a=this.configManager)||void 0===a?void 0:a.getConfig()}/**
|
|
16
14
|
* set config
|
|
17
|
-
*/,c.setConfig=function(){var a=this.
|
|
15
|
+
*/,c.setConfig=function(){var a=this.configManager;if(a)if(2===arguments.length){var b,c=a.getConfig();a.setConfig(Object.assign({},c,(b={},b[0>=arguments.length?void 0:arguments[0]]=1>=arguments.length?void 0:arguments[1],b)))}else a.setConfig(0>=arguments.length?void 0:arguments[0])},c.setVue=function(a){this.setConfig("vue",a),mixin(a)},b}(Shell);export default new ArmsRum;
|
package/es/utils/api.d.ts
CHANGED
package/es/utils/api.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isNumber,isObject,isString}from"@arms/rum-core";export function reviseApiAttr(a){if(a&&isObject(a)){var b={};return isString(a.name)&&(b.name=a.name.substring(0,1e3)),isString(a.message)&&(b.message=a.message.substring(0,1e3)),
|
|
1
|
+
import{isNumber,isObject,isString}from"@arms/rum-core";export function reviseApiAttr(a){if(a&&isObject(a)){var b={};return isString(a.name)&&(b.name=a.name.substring(0,1e3)),isString(a.message)&&(b.message=a.message.substring(0,1e3)),isNumber(a.success)&&-1<=a.success&&1>=a.success&&(b.success=a.success),isNumber(a.duration)&&0<=a.duration&&(b.duration=a.duration),isString(a.status_code)&&(b.status_code=a.status_code.substring(0,100)),isNumber(a.status_code)&&(b.status_code=a.status_code),isString(a.snapshots)&&(b.snapshots=a.snapshots.substring(0,5e3)),b}}
|
package/es/utils/mixin.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Vue } from
|
|
1
|
+
import type { Vue } from '../types/client';
|
|
2
2
|
type Callback = (that: any, ev: any) => void;
|
|
3
3
|
/** Vue 2 传入构造函数;Vue 3 传入 createApp() 的 app 实例 */
|
|
4
|
-
export type VueRuntimeKind =
|
|
4
|
+
export type VueRuntimeKind = 'vue2' | 'vue3';
|
|
5
5
|
/** 根据运行时形态区分:Vue 2 为函数(构造函数),Vue 3 app 为对象 */
|
|
6
6
|
export declare function getVueRuntimeKind(vue: unknown): VueRuntimeKind | null;
|
|
7
7
|
export declare function mixin(vue: Vue): void;
|
package/es/utils/mixin.js
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
var vueCache;/** Vue 2 传入构造函数;Vue 3 传入 createApp() 的 app 实例 *//** 根据运行时形态区分:Vue 2 为函数(构造函数),Vue 3 app 为对象 */export function getVueRuntimeKind(a){if(null==a)return null;return"function"==typeof a.mixin?"function"==typeof a?"vue2":"object"==typeof a?"vue3":null:null}/** 会合并进 Vue.mixin 的生命周期键(与 listeners 中需单独处理的键分开) */var MIXIN_HOOK_KEYS=["onLaunch","onLoad","onShow","beforeCreate","mounted"],listeners={onError:[]};MIXIN_HOOK_KEYS.forEach(function(a){listeners[a]=[]});function invokeListeners(a,b,c){var d=listeners[a];if(null!==d&&void 0!==d&&d.length)for(var e=0;e<d.length;e++)try{d[e](b,c)}catch(b){
|
|
2
|
-
|
|
1
|
+
import{logger}from"@arms/rum-core";var vueCache;/** Vue 2 传入构造函数;Vue 3 传入 createApp() 的 app 实例 *//** 根据运行时形态区分:Vue 2 为函数(构造函数),Vue 3 app 为对象 */export function getVueRuntimeKind(a){if(null==a)return null;return"function"==typeof a.mixin?"function"==typeof a?"vue2":"object"==typeof a?"vue3":null:null}/** 会合并进 Vue.mixin 的生命周期键(与 listeners 中需单独处理的键分开) */var MIXIN_HOOK_KEYS=["onLaunch","onLoad","onShow","beforeCreate","mounted"],listeners={onError:[]};MIXIN_HOOK_KEYS.forEach(function(a){listeners[a]=[]});function invokeListeners(a,b,c){var d=listeners[a];if(null!==d&&void 0!==d&&d.length)for(var e=0;e<d.length;e++)try{d[e](b,c)}catch(b){logger.warn("vue-mixin","vue listener failed",b,{hook:a})}}/** tap/click 事件源:识别 uni-app 事件对象(有 type 且带 currentTarget/target) */var ACTION_EVENT_TYPES=["tap","click"];function isActionEvent(a){return!!a&&"object"==typeof a&&-1!==ACTION_EVENT_TYPES.indexOf(a.type)&&(null!=a.currentTarget||null!=a.target)}/**
|
|
2
|
+
* 拦截组件 methods,为 tap/click 建立事件源。
|
|
3
|
+
* $options.methods 为组件定义共享对象,包装一次即可(__armsActionWrapped 去重);
|
|
4
|
+
* 包装函数在被事件触发时派发 'action',再执行原方法,保持原行为与返回值。
|
|
5
|
+
*/function wrapInstanceMethods(a){// 无 'action' 监听(采集器未启用)时不包装,零开销
|
|
6
|
+
if(listeners.action&&listeners.action.length){var b=a&&a.$options&&a.$options.methods;if(b)for(var c=Object.keys(b),d=function a(){var d=c[e],f=b[d];if("function"!=typeof f||f.__armsActionWrapped)return 1;// continue
|
|
7
|
+
var g=function a(){var b=arguments[0];return isActionEvent(b)&&invokeListeners("action",this,b),f.apply(this,arguments)};g.__armsActionWrapped=!0,b[d]=g},e=0;e<c.length;e++)d()}}function createMixinOptions(a){function d(a,b,c){invokeListeners("onError",this,{error:a,instance:b,info:c})}// Vue 2.5+ / Vue 3:后代组件错误走 onErrorCaptured,再转给 onError 监听(不用 config.errorHandler)
|
|
8
|
+
for(var e={},f=function a(){var b=MIXIN_HOOK_KEYS[g];e[b]=function(a){invokeListeners(b,this,a)}},g=0;g<MIXIN_HOOK_KEYS.length;g++)f();// beforeCreate 早于 Vue initMethods,此时拦截 methods 可让绑定到实例的即为包装版本
|
|
9
|
+
var b=e.beforeCreate;return e.beforeCreate=function(a){b.call(this,a),wrapInstanceMethods(this)},"vue2"===a?Object.defineProperty(vueCache.config,"errorHandler",{get:function a(){var e=this;return function(f,a,b){d(f,a,b),e.__errorHandler&&e.__errorHandler(f,a,b)}},set:function b(a){this.__errorHandler=a}}):Object.defineProperty(vueCache.config,"onErrorCaptured",{get:function a(){var e=this;return function(f,a,b){d(f,a,b),e.__onErrorCaptured&&e.__onErrorCaptured(f,a,b)}},set:function b(a){this.__onErrorCaptured=a}}),e}export function mixin(a){if(!vueCache){vueCache=a;var b=getVueRuntimeKind(a);if(b)try{a.mixin(createMixinOptions(b))}catch(a){logger.error("vue-mixin","vue.mixin failed",a)}}}export function addEventListener(a,b){a in listeners||(listeners[a]=[]),listeners[a].push(b)}export function removeEventListener(a,b){if(a in listeners&&b){var c=listeners[a],d=c.indexOf(b);return c.splice(d,1),!0}return!1}
|
package/es/utils/platform.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RumEventBundle } from
|
|
1
|
+
import { RumEventBundle } from '@arms/rum-core';
|
|
2
2
|
export declare const global2: any;
|
|
3
3
|
export declare const VERSION: string;
|
|
4
4
|
interface CommonOption {
|
|
@@ -14,7 +14,9 @@ interface SDK {
|
|
|
14
14
|
setStorageSync: (key: any, data?: string) => void;
|
|
15
15
|
onError: (listener: Function) => void;
|
|
16
16
|
onPageNotFound: (listener: Function) => void;
|
|
17
|
-
|
|
17
|
+
onUnhandledRejection?: (listener: Function) => void;
|
|
18
|
+
offError?: (listener: Function) => void;
|
|
19
|
+
offUnhandledRejection?: (listener: Function) => void;
|
|
18
20
|
navigateTo: (options: any) => void;
|
|
19
21
|
redirectTo: (options: any) => void;
|
|
20
22
|
switchTab: (options: any) => void;
|
package/es/utils/platform.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import _extends from"@babel/runtime/helpers/extends";import _asyncToGenerator from"@babel/runtime/helpers/asyncToGenerator";import _regeneratorRuntime from"@babel/runtime/regenerator";import{AppType}from"@arms/rum-core";export var global2=global||window;export var VERSION='npm-0.1.
|
|
1
|
+
import _extends from"@babel/runtime/helpers/extends";import _asyncToGenerator from"@babel/runtime/helpers/asyncToGenerator";import _regeneratorRuntime from"@babel/runtime/regenerator";import{AppType}from"@arms/rum-core";export var global2=global||window;export var VERSION='npm-0.1.5';export var sdk=uni;export var appName="uniapp";// export {
|
|
2
2
|
// // sdk: global.uni,
|
|
3
3
|
// appName: 'uniapp',
|
|
4
4
|
// }
|
package/es/utils/session.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IContext, IRumSession, RumEvent, SessionConfig } from
|
|
1
|
+
import { IContext, IRumSession, RumEvent, SessionConfig } from '@arms/rum-core';
|
|
2
2
|
interface SessionInfo {
|
|
3
3
|
sessionId: string;
|
|
4
4
|
sampled: boolean;
|
|
@@ -8,6 +8,8 @@ interface SessionInfo {
|
|
|
8
8
|
}
|
|
9
9
|
export declare class RumSession implements IRumSession {
|
|
10
10
|
ctx: IContext;
|
|
11
|
+
appType: string;
|
|
12
|
+
sdkVersion: string;
|
|
11
13
|
sessionConfig: SessionConfig;
|
|
12
14
|
init(ctx: IContext): void;
|
|
13
15
|
getSessionId(): string;
|
package/es/utils/session.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{generateEventId,generateGUID,generateSpanId,isNumber,ONE_DAY,ONE_HOUR,ONE_MINUTE,performDraw}from"@arms/rum-core";import{getCurrentTime}from"./base";import{getCurView}from"./view";import{getStorageSync,setStorageSync}from"./platform";// 存储userID的键名
|
|
1
|
+
import{generateEventId,generateGUID,generateSpanId,isNumber,ONE_DAY,ONE_HOUR,ONE_MINUTE,performDraw}from"@arms/rum-core";import{getCurrentTime}from"./base";import{getCurView}from"./view";import{getStorageSync,setStorageSync,VERSION}from"./platform";// 存储userID的键名
|
|
2
2
|
var USER_ID="_arms_uid",RUM_SESSION="_arms_session";// 存储session
|
|
3
|
-
export var RumSession=/*#__PURE__*/function(){function a(){this.ctx=void 0,this.sessionConfig=void 0}var b=a.prototype;return b.init=function(a){var b;this.ctx=a,this.sessionConfig=this.fixSessionConfig(null===(b=a.
|
|
3
|
+
export var RumSession=/*#__PURE__*/function(){function a(){this.ctx=void 0,this.appType="uniapp",this.sdkVersion=VERSION,this.sessionConfig=void 0}var b=a.prototype;return b.init=function(a){var b;this.ctx=a,this.sessionConfig=this.fixSessionConfig(null===(b=a.getConfig())||void 0===b?void 0:b.sessionConfig)},b.getSessionId=function(){return this.getSessionInfo().sessionId},b.getSampled=function(){return this.getSessionInfo().sampled},b.checkSession=function(a){var b=this.sessionConfig,c=b.overtime,d=b.maxDuration,e=getCurrentTime();return!(a.startTime+d<e||a.lastTime+c<e)},b.updateSession=function(){var a=this.getSessionInfo();if(!a.isNew){var b=a.startTime,c=getCurrentTime(),d=a.sampled?1:0;setStorageSync(RUM_SESSION,a.sessionId+"-"+d+"-"+b+"-"+c)}},b.getSessionInfo=function(){var a=(getStorageSync(RUM_SESSION)||"").split("-"),b=a[0],c=a[1],d=a[2],e=a[3],f={sessionId:b,sampled:"0"!==c,startTime:parseInt(d||"")||0,lastTime:parseInt(e||"")||0};return this.checkSession(f)||(f=this.resetSession()),f},b.getEventId=function(){return generateEventId(this.getSessionId())},b.getViewId=function(){return this.getUUID()},b.getUserId=function(){var a=getStorageSync(USER_ID);return a&&0===a.indexOf("user_")&&(a=""),a||(a="uid_"+generateSpanId(16,36),setStorageSync(USER_ID,a)),a},b.resetSession=function(){var a=this.sessionConfig.sampling,b=this.getUUID(),c=getCurrentTime(),d=performDraw(a),e=b+"-"+(d?1:0)+"-"+c+"-"+c;return setStorageSync(RUM_SESSION,e),{sessionId:b,sampled:d,startTime:c,lastTime:c,isNew:!0}},b.getUUID=function(){return generateGUID().replace(/-/g,"")},b.fixSessionConfig=function(a){void 0===a&&(a={});var b=a,c=b.sampleRate,d=b.sampling,e=b.maxDuration,f=b.overtime;// 优先使用 sampling(0-100),若未配置则从旧字段 sampleRate(0-1)迁移
|
|
4
4
|
return(!isNumber(d)||0>d||100<d)&&(isNumber(c)&&0<=c&&1>=c?d=100*c:d=100),(!isNumber(e)||e<4*ONE_HOUR||e>ONE_DAY)&&(e=ONE_DAY),(!isNumber(f)||f>ONE_HOUR||f<10*ONE_MINUTE)&&(f=30*ONE_MINUTE),{sampling:d,maxDuration:e,overtime:f}},b.getBaseEvent=function(){return{timestamp:getCurrentTime(),session_id:this.getSessionId(),event_id:this.getEventId(),view:this.ctx?getCurView(this.ctx):void 0,times:1}},a}();
|
package/es/utils/view.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import{isFunction}from"@arms/rum-core";var PAGE_KEY="__rum_view";/**
|
|
1
|
+
import{isFunction,logger}from"@arms/rum-core";var PAGE_KEY="__rum_view";/**
|
|
2
2
|
* 获取当前 page
|
|
3
3
|
* @returns
|
|
4
|
-
*/export function getCurrentPage(){if("function"==typeof getCurrentPages)try{var a=getCurrentPages()||[];return a[a.length-1]}catch(a){
|
|
5
|
-
}}/**
|
|
4
|
+
*/export function getCurrentPage(){if("function"==typeof getCurrentPages)try{var a=getCurrentPages()||[];return a[a.length-1]}catch(a){logger.warn("view","getCurrentPage failed",a)}}/**
|
|
6
5
|
* 获取当前 view
|
|
7
6
|
* @param ctx
|
|
8
7
|
* @returns
|
|
@@ -10,4 +9,4 @@ import{isFunction}from"@arms/rum-core";var PAGE_KEY="__rum_view";/**
|
|
|
10
9
|
* 获取当前 view
|
|
11
10
|
* @param ctx
|
|
12
11
|
* @returns
|
|
13
|
-
*/export function getCurViews(){var a=[];if("function"==typeof getCurrentPages)try{(getCurrentPages()||[]).forEach(function(b){PAGE_KEY in b&&a.push(b[PAGE_KEY])})}catch(a){}return a}
|
|
12
|
+
*/export function getCurViews(){var a=[];if("function"==typeof getCurrentPages)try{(getCurrentPages()||[]).forEach(function(b){PAGE_KEY in b&&a.push(b[PAGE_KEY])})}catch(a){logger.warn("view","getCurViews failed",a)}return a}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ICollector, IContext, RumActionEvent, RumEvent } from '@arms/rum-core';
|
|
2
|
+
export default class ActionCollector implements ICollector {
|
|
3
|
+
name: string;
|
|
4
|
+
private DELAY_TIME;
|
|
5
|
+
ctx: IContext;
|
|
6
|
+
sendEvent: (payload: RumEvent) => void;
|
|
7
|
+
events: string[];
|
|
8
|
+
lastEvent: RumActionEvent;
|
|
9
|
+
timer: any;
|
|
10
|
+
setup(ctx: IContext, sendEvent: (payload: RumEvent) => void): void;
|
|
11
|
+
onEvent: (_that: any, e: any) => void;
|
|
12
|
+
sendAction: () => void;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
}
|
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// // import { addPageListener, removePageListener } from "../../utils/hackPage";
|
|
4
|
-
//
|
|
5
|
-
// export default class ActionCollector implements ICollector {
|
|
6
|
-
// name = 'action-collector';
|
|
7
|
-
// private DELAY_TIME = 300;
|
|
8
|
-
// ctx: IContext;
|
|
9
|
-
// sendEvent: (payload: RumEvent) => void;
|
|
10
|
-
// events = ['tap'];
|
|
11
|
-
// lastEvent: RumActionEvent;
|
|
12
|
-
// timer: any;
|
|
13
|
-
//
|
|
14
|
-
// setup(ctx: IContext, sendEvent: (payload: RumEvent) => void) {
|
|
15
|
-
// const {collectors = {}} = ctx.getConfig();
|
|
16
|
-
// if (collectors.action === false) {
|
|
17
|
-
// return;
|
|
18
|
-
// }
|
|
19
|
-
// this.ctx = ctx;
|
|
20
|
-
// this.sendEvent = sendEvent;
|
|
21
|
-
// // addPageListener('*', this.onEvent)
|
|
22
|
-
// }
|
|
23
|
-
//
|
|
24
|
-
// onEvent = (e) => {
|
|
25
|
-
// if (e && this.events.includes(e.type) && e.target) {
|
|
26
|
-
// const {target, currentTarget, type} = e;
|
|
27
|
-
// const {dataset, id} = target;
|
|
28
|
-
// if (!id) return;
|
|
29
|
-
// if (currentTarget && id !== currentTarget.id) return;
|
|
30
|
-
// const view = getCurView(this.ctx);
|
|
31
|
-
// const event: RumActionEvent = {
|
|
32
|
-
// event_type: RumEventType.ACTION,
|
|
33
|
-
// type,
|
|
34
|
-
// name: id,
|
|
35
|
-
// snapshots: Object.keys(dataset).length ? JSON.stringify(dataset) : undefined,
|
|
36
|
-
// times: 1,
|
|
37
|
-
// view
|
|
38
|
-
// }
|
|
39
|
-
// clearTimeout(this.timer);
|
|
40
|
-
// if (this.lastEvent) {
|
|
41
|
-
// if (this.lastEvent.name !== event.name) {
|
|
42
|
-
// this.sendAction();
|
|
43
|
-
// } else {
|
|
44
|
-
// this.lastEvent.times += 1;
|
|
45
|
-
// }
|
|
46
|
-
// } else {
|
|
47
|
-
// this.lastEvent = event;
|
|
48
|
-
// }
|
|
49
|
-
// this.timer = setTimeout(this.sendAction, this.DELAY_TIME);
|
|
50
|
-
// }
|
|
51
|
-
// }
|
|
52
|
-
//
|
|
53
|
-
// sendAction = () => {
|
|
54
|
-
// this.sendEvent(this.lastEvent);
|
|
55
|
-
// this.lastEvent = null;
|
|
56
|
-
// }
|
|
57
|
-
//
|
|
58
|
-
// destroy() {
|
|
59
|
-
// // removePageListener('*', this.onEvent);
|
|
60
|
-
// }
|
|
61
|
-
// }
|
|
62
|
-
"use strict";
|
|
1
|
+
"use strict";exports.__esModule=!0,exports["default"]=void 0;var _rumCore=require("@arms/rum-core"),_mixin=require("../../utils/mixin"),_view=require("../../utils/view"),ActionCollector=exports["default"]=/*#__PURE__*/function(){function a(){var a=this;this.name="action-collector",this.DELAY_TIME=300,this.ctx=void 0,this.sendEvent=void 0,this.events=["tap","click"],this.lastEvent=void 0,this.timer=void 0,this.onEvent=function(b,c){if(c&&a.events.includes(c.type)){// 优先取 currentTarget(事件绑定元素),缺失时回退 target(实际触发元素)
|
|
2
|
+
var d=c.currentTarget||c.target||{},e=d.id,f=d.dataset;if(!e&&c.target&&(e=c.target.id,f=c.target.dataset),!!e){var g=(0,_view.getCurView)(a.ctx),h={event_type:_rumCore.RumEventType.ACTION,type:c.type,name:e,snapshots:f?JSON.stringify({dataset:f}).substring(0,1e3):void 0,times:1,view:g};clearTimeout(a.timer),a.lastEvent?a.lastEvent.name===h.name?a.lastEvent.times+=1:(a.sendAction(),a.lastEvent=h):a.lastEvent=h,a.timer=setTimeout(a.sendAction,a.DELAY_TIME)}}},this.sendAction=function(){a.lastEvent&&(a.sendEvent(a.lastEvent),a.lastEvent=null)}}var b=a.prototype;return b.setup=function(a,b){var c=a.getConfig(),d=c.collectors,e=void 0===d?{}:d;!1===e.action||(this.ctx=a,this.sendEvent=b,(0,_mixin.addEventListener)("action",this.onEvent))},b.destroy=function(){(0,_mixin.removeEventListener)("action",this.onEvent)},a}();
|