UNPKG

@zjsix/vue-monitor

Version:

A simple monitoring plugin for Vue.js applications, providing error tracking, performance monitoring and user behavior analysis

126 lines (121 loc) 4.33 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /** * 格式化日期 * @param date Date | string | undefined,不传默认当前时间 * @param format 格式字符串,不传默认 "YYYY-MM-DD HH:mm:ss" * @returns 格式化后的日期字符串 */ function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { const d = (new Date()); if (isNaN(d.getTime())) { throw new Error('Invalid date provided'); } const pad = (n) => String(n).padStart(2, '0'); const map = { YYYY: d.getFullYear().toString(), MM: pad(d.getMonth() + 1), DD: pad(d.getDate()), HH: pad(d.getHours()), mm: pad(d.getMinutes()), ss: pad(d.getSeconds()) }; return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (key) => map[key]); } class VueMonitor { constructor(options) { this.breadcrumbs = []; this.reportUrl = options.reportUrl; this.projectName = options.projectName; this.projectVersion = options.projectVersion; this.maxBreadcrumbs = options.maxBreadcrumbs || 20; } initVue(Vue, isVue3 = false) { const handler = (err, vm, info) => { this.reportError({ message: err.message, stack: err.stack, info, url: window.location.href, timestamp: formatDate() }); }; if (isVue3) { Vue.config.errorHandler = handler; } else { Vue.config.errorHandler = handler; } } initGlobalError() { window.onerror = (message, source, lineno, colno, error) => { this.reportError({ message: (message === null || message === void 0 ? void 0 : message.toString()) || 'unknown error', stack: error === null || error === void 0 ? void 0 : error.stack, url: window.location.href, timestamp: formatDate() }); }; window.onunhandledrejection = (event) => { var _a, _b; this.reportError({ message: ((_a = event.reason) === null || _a === void 0 ? void 0 : _a.toString()) || 'unhandled promise rejection', stack: (_b = event.reason) === null || _b === void 0 ? void 0 : _b.stack, url: window.location.href, timestamp: formatDate() }); }; } /** 初始化用户行为埋点 */ initBehavior() { document.addEventListener('click', e => { const target = e.target; this.addBreadcrumb({ type: 'click', target: target.tagName + (target.id ? `#${target.id}` : '') + (target.className ? `.${target.className}` : ''), timestamp: formatDate() }); }); document.addEventListener('input', e => { const target = e.target; this.addBreadcrumb({ type: 'input', target: target.tagName + (target.id ? `#${target.id}` : '') + (target.className ? `.${target.className}` : ''), value: target.value, timestamp: formatDate() }); }); } /** 添加面包屑 */ addBreadcrumb(breadcrumb) { this.breadcrumbs.push(breadcrumb); if (this.breadcrumbs.length > this.maxBreadcrumbs) this.breadcrumbs.shift(); } /** 上报错误 */ reportError(error) { fetch(this.reportUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ projectName: this.projectName, projectVersion: this.projectVersion, error, breadcrumbs: this.breadcrumbs }), keepalive: true, }).catch(err => { console.warn('上报错误失败:', err); }); } } var index = { install(app, options) { const monitor = new VueMonitor(options); monitor.initGlobalError(); monitor.initBehavior(); // vue3有config vue2没有 monitor.initVue(app, !!app.config); app.config.globalProperties.$monitor = monitor; } }; exports.VueMonitor = VueMonitor; exports.default = index; //# sourceMappingURL=vue-monitor.js.map