UNPKG

zhou-statistic

Version:

性能、错误、访问等埋点监控上报

116 lines (114 loc) 3.67 kB
class StatisticSDK { constructor({ productID, statisticURL, }) { // SDK实例ID this.productID = productID this.Timing = performance.getEntriesByType("navigation")[0] this.statisticURL = statisticURL } send(query = {}) { query.productID = this.productID; if(typeof navigator.sendBeacon === 'function') { this.sendBeacon(query); } } // navigator.sendBeacon // 不会和主要业务代码抢占资源,而是在浏览器空闲时去做发送; // 并且在页面卸载时也能保证请求成功发送,不阻塞页面刷新和跳转; sendBeacon(data) { const form = new FormData(); Object.entries(data).map(([key, value]) => { form.append(key, value); }); navigator.sendBeacon(this.statisticURL, form); } event(key, val = {}) { this.send({ key, ...val }); } pv() { this.event('pv', { href: decodeURIComponent(location.href), }) } /** DNS查询耗时 :domainLookupEnd - domainLookupStart TCP链接耗时 :connectEnd - connectStart SSL安全连接耗时: connectEnd - secureConnectionStart request请求耗时 :responseEnd - responseStart 解析dom树耗时 : domComplete - domInteractive 首次渲染时间/白屏时间 :responseStart - startTime domready时间 :domContentLoadedEventEnd - startTime onload时间(总下载时间) :duration * */ // 页面首次渲染时间: FP(firstPaint)=domLoading-navigationStart FP() { const { responseStart, startTime } = this.Timing; this.event('FP', { fp: responseStart - startTime, label: '页面首次渲染时间' }); } // DOM加载完成: DCL(DOMContentEventLoad)=domContentLoadedEventEnd-navigationStart DCL() { const { domContentLoadedEventEnd, startTime } = this.Timing; this.event('DCL', { DCL: domContentLoadedEventEnd - startTime, label: 'DOM加载完成', }); } // 图片、样式等外链资源加载完成 (onload): L(Load)=loadEventEnd-navigationStart LOAD() { const { duration } = this.Timing; this.event('LOAD', { DCL: duration, label: '图片、样式等外链资源加载完成', }); } // 常见页面性能监控 initNormalPerformance() { this.FP(); this.DCL(); this.LOAD(); } // 所有性能数据 allPerformanceTiming() { const timing = {}; const Timing = this.Timing; for(let i in Timing) { timing[i] = Timing[i] } setTimeout(() => { this.event('timing', { label: 'timing', ...timing, }); }, 1e2); } error(err, etraInfo) { const { message, stack } = err; this.event('error', { message, stack, ...etraInfo}) } // TODO: 错误监控上报 initError() { window.addEventListener('error', e => { this.error(e); }); window.addEventListener('unhandledrejection', ({ reason }) => { this.error(new Error(reason), { type: 'unhandledrejection'}) }) } } // 用于vue挂载 export const statistic = (vm, options) => { const { global = true } = options const instance = new StatisticSDK(options); // 全局埋点(默认开启) if(global) { instance.initError(); } vm.prototype.$statistic = instance; } export default StatisticSDK;