@lx-frontend/taro-plugin-monitor
Version:
taro 小程序监控插件,收集生命周期、事件、错误等数据
325 lines (316 loc) • 11.4 kB
JavaScript
import { Events } from '@tarojs/shared';
import { generateHttpEvent, generateApiCallEvent, generateBaseEvent } from '@lx-frontend/multi-track-shared';
export * from '@lx-frontend/multi-track-shared';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
// ===========================================以上不同类型事件数据生成辅佐函数======================================================
// 监控 event,订阅与触发
var monitorEvent = new Events();
var triggerEvent = function (trackingEvent) {
monitorEvent.trigger('all', trackingEvent);
};
// 监控 event,订阅与触发
var networkProps = ['request', 'downloadFile', 'uploadFile'];
/**
* 处理 API 事件
* @param prop 事件类型
* @param apiBaseInfo 基础信息
* @param otherOptions 其他选项
* @param res 响应
* @param apiState
*/
var handleApiEvent = function (prop, apiBaseInfo, otherOptions, res, apiState) {
if (otherOptions === void 0) { otherOptions = {}; }
try {
if (networkProps.includes(prop)) {
// 上报网络请求事件
triggerEvent(generateHttpEvent({
eventLevel: 'info',
httpBaseInfo: apiBaseInfo,
otherOptions: otherOptions,
response: res,
}));
}
else {
// 上报 API 事件
triggerEvent(generateApiCallEvent({
eventLevel: 'info',
apiBaseInfo: apiBaseInfo,
apiName: prop,
apiArgs: otherOptions,
apiStatus: apiState,
apiResponse: res,
}));
}
}
catch (_error) {
console.error('handleApiEvent', _error);
}
};
/**
* wx 对象 和 taro 对象构造监控函数
* @param target
* @param prop
* @param originalMethod
*/
var creatorMonitorHandler = function (target, prop, originalMethod) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var options = args[0], restArgs = args.slice(1);
// 传统 API 和网络 API 有不同数据结构
var eventType = networkProps.includes(prop) ? 'http' : 'api';
var apiBaseInfo = generateBaseEvent(eventType, 'info');
var _a = options || {}, success = _a.success, fail = _a.fail, complete = _a.complete, otherOptions = __rest(_a, ["success", "fail", "complete"]);
// 处理有 success 和 fail 、complete 的情况
if (typeof options === 'object' && (success || fail || complete)) {
var obj = Object.assign({}, options);
if (typeof success === 'function') {
obj.success = function () {
var _a;
var callbackArgs = [];
for (var _i = 0; _i < arguments.length; _i++) {
callbackArgs[_i] = arguments[_i];
}
handleApiEvent(prop, apiBaseInfo, otherOptions, callbackArgs === null || callbackArgs === void 0 ? void 0 : callbackArgs[0], 'success');
(_a = success.apply) === null || _a === void 0 ? void 0 : _a.call(success, target, callbackArgs);
};
}
if (typeof fail === 'function') {
obj.fail = function () {
var _a;
var callbackArgs = [];
for (var _i = 0; _i < arguments.length; _i++) {
callbackArgs[_i] = arguments[_i];
}
handleApiEvent(prop, apiBaseInfo, otherOptions, callbackArgs === null || callbackArgs === void 0 ? void 0 : callbackArgs[0], 'fail');
(_a = fail.apply) === null || _a === void 0 ? void 0 : _a.call(fail, target, callbackArgs);
};
}
if (typeof complete === 'function') {
obj.complete = function () {
var _a;
var callbackArgs = [];
for (var _i = 0; _i < arguments.length; _i++) {
callbackArgs[_i] = arguments[_i];
}
handleApiEvent(prop, apiBaseInfo, otherOptions, callbackArgs === null || callbackArgs === void 0 ? void 0 : callbackArgs[0], 'complete');
(_a = complete.apply) === null || _a === void 0 ? void 0 : _a.call(complete, target, callbackArgs);
};
}
return originalMethod.apply(target, __spreadArray([obj], restArgs, true));
}
else {
// 传统 wx.xxx() 或者 await wx.xxx(options) 的情况
// 传统 Taro.xxx() 或者 await Taro.xxx(options) 的情况
var maybePromiseOrRes = originalMethod.apply(target, args);
if (maybePromiseOrRes === null || maybePromiseOrRes === void 0 ? void 0 : maybePromiseOrRes.then) {
return maybePromiseOrRes
.then(function (res) {
handleApiEvent(prop, apiBaseInfo, otherOptions, res, 'success');
return res;
})
.catch(function (err) {
handleApiEvent(prop, apiBaseInfo, otherOptions, err, 'fail');
throw err;
});
}
else {
handleApiEvent(prop, apiBaseInfo, args, {}, 'success');
return maybePromiseOrRes;
}
}
};
};
// 有限控制劫持 API
var allowProxyApi = new Set([
'addPhoneContact',
'authorize',
'canvasGetImageData',
'canvasPutImageData',
'canvasToTempFilePath',
'checkSession',
'chooseAddress',
'chooseImage',
'chooseInvoiceTitle',
'chooseLocation',
'chooseVideo',
'clearStorage',
'closeBLEConnection',
'closeBluetoothAdapter',
'closeSocket',
'compressImage',
'connectSocket',
'createBLEConnection',
'request',
'downloadFile',
'exitMiniProgram',
'getAvailableAudioSources',
'getBLEDeviceCharacteristics',
'getBLEDeviceServices',
'getBatteryInfo',
'getBeacons',
'getBluetoothAdapterState',
'getBluetoothDevices',
'getClipboardData',
'getConnectedBluetoothDevices',
'getConnectedWifi',
'getExtConfig',
'getFileInfo',
'getImageInfo',
'getLocation',
'getNetworkType',
'getSavedFileInfo',
'getSavedFileList',
'getScreenBrightness',
'getSetting',
'getStorage',
'getStorageInfo',
'getSystemInfo',
'getUserInfo',
'getWifiList',
'hideHomeButton',
'hideShareMenu',
'hideTabBar',
'hideTabBarRedDot',
'loadFontFace',
'login',
'makePhoneCall',
'navigateBack',
'navigateBackMiniProgram',
'navigateTo',
'navigateToBookshelf',
'navigateToMiniProgram',
'notifyBLECharacteristicValueChange',
'hideKeyboard',
'hideLoading',
'hideNavigationBarLoading',
'hideToast',
'openBluetoothAdapter',
'openDocument',
'openLocation',
'openSetting',
'pageScrollTo',
'previewImage',
'queryBookshelf',
'reLaunch',
'readBLECharacteristicValue',
'redirectTo',
'removeSavedFile',
'removeStorage',
'removeTabBarBadge',
'requestSubscribeMessage',
'saveFile',
'saveImageToPhotosAlbum',
'saveVideoToPhotosAlbum',
'scanCode',
'sendSocketMessage',
'setBackgroundColor',
'setBackgroundTextStyle',
'setClipboardData',
'setEnableDebug',
'setInnerAudioOption',
'setKeepScreenOn',
'setNavigationBarColor',
'setNavigationBarTitle',
'setScreenBrightness',
'setStorage',
'setTabBarBadge',
'setTabBarItem',
'setTabBarStyle',
'showActionSheet',
'showFavoriteGuide',
'showLoading',
'showModal',
'showShareMenu',
'showTabBar',
'showTabBarRedDot',
'showToast',
'startBeaconDiscovery',
'startBluetoothDevicesDiscovery',
'startDeviceMotionListening',
'startPullDownRefresh',
'stopBeaconDiscovery',
'stopBluetoothDevicesDiscovery',
'stopCompass',
'startCompass',
'startAccelerometer',
'stopAccelerometer',
'showNavigationBarLoading',
'stopDeviceMotionListening',
'stopPullDownRefresh',
'switchTab',
'uploadFile',
'vibrateLong',
'vibrateShort',
'writeBLECharacteristicValue',
]);
/**
* 监控 taro 对象
* 注意,只能采用 taro['xxx'] = function() {} 的方式,才能劫持到。
* @param target
*/
var monitorTaroCalls = function (target) {
Object.keys(target).forEach(function (prop) {
if (!allowProxyApi.has(prop))
return;
var originalMethod = target[prop];
if (typeof originalMethod === 'function') {
target[prop] = creatorMonitorHandler(target, prop, originalMethod);
}
});
};
/**
* 监控微信对象
* 注意,只能通过 proxy 处理后,才能劫持到。
* @param target
*/
var monitorWxCalls = function (target) {
return new Proxy(target, {
get: function (target, prop, receiver) {
var originalMethod = Reflect.get(target, prop, receiver);
if (typeof originalMethod === 'function' && allowProxyApi.has(prop)) {
return creatorMonitorHandler(target, prop, originalMethod);
}
return originalMethod;
},
});
};
export { creatorMonitorHandler, handleApiEvent, monitorEvent, monitorTaroCalls, monitorWxCalls, triggerEvent };
//# sourceMappingURL=helper.js.map