技术调研:因不能使用已经成熟的其他插件,如FunDebug(收费),所以需要自己写一个。
实现要求: 将线上的(主要指前端)错误收集起来,动态在本地创建一个文件夹,每天一个文件(以时间命名),只保留7天内的文件
项目技术:Vue.config.errorHandler(项目是vue)
注意:ActiveXObject可以在本地创建文件,但是IE特有的,所以我选择通过node来做
实现:
import moment from 'moment'; import axios from 'axios'; let errorType = ''; const errorHandler = (error, vm, info) => { let { message, // 异常信息 name, // 异常名称 script, // 异常脚本 line, // 异常行号 column, // 异常列号 stack // 异常堆栈信息 script, line, column可以从这里面匹配到 } = error; console.log('抛出全局异常'); let now = moment().locale('zh-cn').format('YYYY-MM-DD HH:mm:ss'); let data = `${now} ${stack}type:${errorType}`; console.log(error, 'error'); axios.post('/error/errordata', data) .then(res => { console.log(res.data, '请求成功'); }) .catch(error => { console.log(error); }); }; let GlobalError = { install: (Vue, type) => { errorType = type; Vue.config.errorHandler = errorHandler; Vue.mixin({ beforeCreate() { const methods = this.$options.methods || {}; Object.keys(methods).forEach(key => { let fn = methods[key]; this.$options.methods[key] = function (...args) { let ret = fn.apply(this, args); if (ret && typeof ret.then === 'function' && typeof ret.catch === 'function') { return ret.catch(errorHandler); } else { // 默认错误处理 return ret; } }; }); } }); Vue.prototype.$throw = errorHandler; } }; export default GlobalError;
node
let h = require("http");
let fs = require('fs');
const url = require('url');
let path = require('path');
let moment = require('moment');
h.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('bug统计');
let parsed_url = url.parse(req.url);
let errorname = '';
if (parsed_url.pathname === '/error/errordata') { //匹配路由
// 定义了一个post变量,用于暂存请求体的信息
let postData = '';
let date = '';
req.on('data', chunk => { //在on函数中获取请求体
postData += chunk; //请求数据过大时会自动进行多次请求
})
req.on('end', () => { //请求结束
res.writeHead(201, { 'content-type': 'text/plain' });
res.end(postData);
let last7 = moment().subtract(7, 'days').format('YYYY-MM-DD');
date = postData.slice(0, 10);
errorname = postData.split("type:")[1] + 'Error';
// date = "2020-06-24";
let newpath = `/Users/xxxxx/Desktop/${errorname}/`;
// let newpath = path.join(__dirname, `../${errorname}/`)
fs.exists(newpath, exists => {
// fs.exists测试某个路径下的文件是否存在。回调函数包含一个参数exists,true则文件存在,否则是false。
if (!exists) {
// fs.mkdir mode:目录权限(读写权限) 默认0777
fs.mkdir(newpath, 0777, err => {
if (err) {
console.log(err, '创建文件夹错误');
} else {
fs.writeFile(newpath + `${date}.txt`, `${postData}`, null, err => {
if (err) {
console.error(err, '写入错误');
} else {
console.log('写入成功');
}
});
}
});
}
else {
fs.exists(newpath + `${date}.txt`, exists =>{
if (exists) {
fs.appendFile(newpath + `${date}.txt`, `
${postData}`, 'utf-8', err => {
if (err) {
console.log(err, '追加错误');
return false;
}
console.log('追加成功!!!');
});
}
else {
fs.writeFile(newpath + `${date}.txt`, `${postData}`, null, err => {
if (err) {
console.error(err, '写入错误');
} else {
console.log('写入成功');
}
});
}
})
}
fs.readdir(newpath, (err, files) => {
if (err) {
return console.log('目录不存在')
}
files.forEach(item => {
let time = item.slice(0, 10);
// let isBefore = false;
let isBefore = moment(time).isBefore(last7);
if (isBefore) {
fs.unlink(newpath + item, err => {
if (err) {
console.log(err, '删除错误');
return false;
}
console.log('删除文件成功');
});
}
});
})
});
})
}
}).listen(8888);
console.log("服务器开启啦~~");
实现之后:
