本地缓存在localStorage中的监控对象
export default function monitorInit(timeout = 7 * 24 * 60 * 60) { let whiteScreen = new Date() - performance.timing.navigationStart; const monitor = { // 数据上传地址 // url: '', // 性能信息 performance: {}, // 资源信息 resources: {}, // 错误信息 errors: {}, // 用户信息 client: { // 屏幕宽度 screen: screen.width, // 屏幕高度 height: screen.height, // 浏览器平台 platform: navigator.platform, // 浏览器的用户代理信息 userAgent: navigator.userAgent, // 浏览器用户界面的语言 language: navigator.language }, cacheTime: new Date().getTime(), timeout: timeout // 手动添加错误 // addError(error) { // const obj = {}; // const { type, msg, url, row, col } = error; // if (type) obj.type = type; // if (msg) obj.msg = msg; // if (url) obj.url = url; // if (row) obj.row = row; // if (col) obj.col = col; // obj.time = new Date().getTime(); // monitor.errors.push(obj); // }, // 重置 monitor 对象 // reset() { // window.performance && window.performance.clearResourceTimings(); // monitor.performance = getPerformance(); // monitor.resources = getResources(); // monitor.errors = {}; // }, // 清空 error 信息 // clearError() { // monitor.errors = {}; // }, // 上传监控数据 // upload() { // 自定义上传 // axios.post({ // url: monitor.url, // data: { // performance, // resources, // errors, // user, // } // }) // }, // 设置数据上传地址 // setURL(url) { // monitor.url = url; // } }; const getMonitor = () => { isOverTime(); return JSON.parse(localStorage.getItem('monitor')); }; const isOverTime = () => { const data = JSON.parse(localStorage.getItem('monitor')); // 没有数据 一定超时 if (!data) { return true; } // 获取系统当前时间戳 const currentTime = new Date().getTime(); // 获取当前时间与存储时间的过去的秒数 const overTime = (currentTime - data.cacheTime) / 1000; // console.log(overTime); // 如果过去的秒数大于当前的超时时间,也返回null让其去服务端取数据 if (overTime > data.timeout) { localStorage.removeItem('monitor'); return true; } return false; }; // 获取性能信息 const getPerformance = () => { if (!window.performance) return; const timing = window.performance.timing; const performance = { // 重定向耗时 redirect: timing.redirectEnd - timing.redirectStart, // 白屏时间 whiteScreen: whiteScreen, // DOM 渲染耗时 dom: timing.domComplete - timing.domLoading, // 页面加载耗时 load: timing.loadEventEnd - timing.navigationStart, // 页面卸载耗时 unload: timing.unloadEventEnd - timing.unloadEventStart, // 请求耗时 request: timing.responseEnd - timing.requestStart, // 获取性能信息时当前时间 time: new Date().getTime() }; return performance; }; // 获取资源信息 const getResources = () => { if (!window.performance) return; const data = window.performance.getEntriesByType('resource'); const resource = { xmlhttprequest: [], css: [], other: [], script: [], img: [], link: [], fetch: [], // 获取资源信息时当前时间 time: new Date().getTime() }; data.forEach(item => { const arry = resource[item.initiatorType]; arry && arry.push({ // 资源的名称 name: item.name, // 资源加载耗时 duration: item.duration.toFixed(2), // 资源大小 size: item.transferSize, // 资源所用协议 protocol: item.nextHopProtocol }); }); return resource; }; window.onload = () => { // 在浏览器空闲时间获取性能及资源信息 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback let monitorObj = getMonitor() ? getMonitor() : monitor; if (window.requestIdleCallback) { window.requestIdleCallback(() => { monitorObj.performance = getPerformance(); // console.log('页面性能信息'); // console.log(monitor.performance); monitorObj.resources = getResources(); // console.log('页面资源信息'); // console.log(monitor.resources); localStorage.setItem('monitor', JSON.stringify(monitorObj)); }); } else { setTimeout(() => { monitor.performance = getPerformance(); // console.log('页面性能信息'); // console.log(monitor.performance); monitor.resources = getResources(); // console.log('页面资源信息'); // console.log(monitor.resources); localStorage.setItem('monitor', JSON.stringify(monitor)); }, 0); } }; // 捕获资源加载失败错误 js css img... addEventListener( 'error', e => { const target = e.target; if (target !== window) { let monitorObj = getMonitor() ? getMonitor() : monitor; let url = target.src || target.href; if (!monitorObj.errors[url]) { monitorObj.errors[url] = { type: target.localName, url: url, msg: (target.src || target.href) + ' is load error', // 错误发生的时间 time: new Date().getTime() }; localStorage.setItem('monitor', JSON.stringify(monitorObj)); // console.log('所有的错误信息'); // console.log(monitor.errors); } } }, true ); // 监听 js 错误 window.onerror = function(msg, url, row, col, error) { let monitorObj = getMonitor() ? getMonitor() : monitor; let key = `${url}:${row}`; if (!monitorObj.errors[key]) { monitorObj.errors[key] = { type: 'javascript', // 错误类型 row: row, // 发生错误时的代码行数 col: col, // 发生错误时的代码列数 msg: error && error.stack ? error.stack : msg, // 错误信息 url: url, // 错误文件 time: new Date().getTime() // 错误发生的时间 // console.log('所有的错误信息'); // console.log(monitor.errors); }; localStorage.setItem('monitor', JSON.stringify(monitorObj)); } }; // 监听 promise 错误 缺点是获取不到行数数据 addEventListener('unhandledrejection', e => { let monitorObj = getMonitor() ? getMonitor() : monitor; let msg = (e.reason && e.reason.msg) || e.reason || ''; if (!monitorObj.errors[msg]) { monitorObj.errors[msg] = { type: 'promise', msg: msg, // 错误发生的时间 time: new Date().getTime() }; // console.log('所有的错误信息'); // console.log(monitor.errors); localStorage.setItem('monitor', JSON.stringify(monitorObj)); } }); return monitor; }