[前端生存指南]如何做前端sentry性能监控中的错误和数据采集

750 阅读5分钟

随着 “大前端” 近两年愈演愈烈(juan),需要我们掌握的技能也越来越多,延伸而来的就是各种前端性能和异常监控框架。

市面上有很多种开源的框架,如 Sentry、Rollbar 等,大厂也会自己建立一套完整的监控体系,有时候还会配合后端的ELK系统一起使用,无论用什么框架,最关键的一步就是:前期的 数据采集和错误捕获, 这里为大家简单分享下一些主流的方式。

1、代码异常捕获 try-catch

try {
    // Some code that may throw an error
} catch (error) {
    //发送错误信息
    console.log(error);
    //sendError(error)
}

相信大家在一些关键的同步请求的时候,会用上try-catch,避免因为报错,导致整个功能弹出,这也是常规用来捕捉错误日志的方法。

在前端中使用try-catch语句可以帮助开发人员及时发现和解决错误,提高应用程序的健壮性和稳定性。同时,使用第三方错误监控工具可以自动化地收集和汇总错误信息,减少手动调试和排查错误的工作量。

2、页面监控window.onerror

 /** 
   * @param {String} errorMessage  错误信息 
   * @param {String} scriptURI   出错的文件 
   * @param {Long}  lineNumber   出错代码的行号 
   * @param {Long}  columnNumber  出错代码的列号 
   * @param {Object} errorObj    错误的详细信息,Anything 
   */ 
  window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) { 
    console.log("错误信息:" , errorMessage); 
    console.log("出错文件:" , scriptURI); 
    console.log("出错行号:" , lineNumber); 
    console.log("出错列号:" , columnNumber); 
    console.log("错误详情:" , errorObj); 
  } 

这种错误监听,可以获取同步和异步的方法,也是比较实用,且常规的一种错误监听的方法,此外,还能提供详尽的数据位置,地址等

3、异常捕获(addEventListener)

window.addEventListener("error")

// 监听 JavaScript 异常
window.addEventListener('error', function(event) {
    // 收集错误信息
    const error = {
        message: event.message,
        filename: event.filename,
        lineno: event.lineno,
        colno: event.colno,
        error: event.error,
    };
    //发送错误信息
});

//图片加载错误监听
image.addEventlistener("error",e => (
    e.preventDefault();
    //发送错误信息
    console.log(e);
}
// 监听 JavaScript 文件的加载状态
const script = document.createElement('script');

script.addEventListener('load', function(event) {
  // JavaScript 文件加载完成
  console.log('JavaScript file loaded');
});

script.addEventListener('error', function(event) {
  // JavaScript 文件加载失败
  console.error('JavaScript file failed to load');
});

script.src = 'path/to/javascript/file.js';
document.head.appendChild(script);

// 监听 CSS 文件的加载状态
const link = document.createElement('link');

link.addEventListener('load', function(event) {
  // CSS 文件加载完成
  console.log('CSS file loaded');
});

link.addEventListener('error', function(event) {
  // CSS 文件加载失败
  console.error('CSS file failed to load');
});

link.rel = 'stylesheet';
link.href = 'path/to/css/file.css';
document.head.appendChild(link);

也可以用另外一个省代码的写法

// 监听处理js/css
window .addEventListener("error", function (e) {
    var typeName = e.target.localName;
    var sourceUrl = "";
    if(typeName === "link"){
        sourceUrl = e.target.href;
    }else if(typeName === 'script'){
        sourceUrl = e.target.src;
    }
    //发送错误信息
});

使用 addEventListener 来监听 JavaScript 和 CSS 文件的加载状态可以帮助开发者及时发现和解决加载问题,提高应用程序的稳定性和可靠性,从而提升用户体验和满意度。

window.addEventListener("unhandledrejection")

window.addEventListener("unhandledrejection", function(event) {
  // 阻止默认行为,防止 Promise 异常被浏览器捕获并输出到控制台
  event.preventDefault();

  // 收集 Promise 异常信息
  const error = {
    message: event.reason.message,
    stack: event.reason.stack,
  };

  // 将异常信息发送到服务器或其他地方进行分析和报告
  sendErrorData(error);
});

在上面的代码中,我们使用 window.addEventListener("unhandledrejection") 方法来监听未处理的 Promise 异常,并收集异常信息。当 Promise 被拒绝时,会触发 unhandledrejection 事件,并将异常信息作为事件参数传递给回调函数。然后我们将异常信息发送到服务器或其他地方进行分析和报告。

需要注意的是,当 Promise 对象被拒绝时,浏览器会默认输出异常信息到控制台。为了防止 Promise 异常被浏览器捕获并输出到控制台,我们需要在回调函数中调用 event.preventDefault() 方法,阻止默认行为的发生。

使用 window.addEventListener("unhandledrejection") 方法来监听 JavaScript Promise 的拒绝状态可以帮助开发者及时发现和解决异常问题,提高应用程序的稳定性和可靠性,从而提升用户体验和满意度。

4、性能监听(Performance)

可以使用 Performance API 来做监听

// 初始化 Performance API
const perf = window.performance;

// 创建一个新的性能条目
const entry = perf.mark('start');

// 在某个时间点开始执行某段代码
const startTime = performance.now();

// 在某个时间点结束执行某段代码
const endTime = performance.now();

// 收集性能数据
const data = {
  duration: endTime - startTime,
  // 其他性能指标,如占用 CPU 时间、内存使用等等
};

// 将性能数据发送到服务器或其他地方进行分析和报告

Performance API 是浏览器提供的一组 API,用于监测前端应用程序的性能指标,帮助开发者发现性能问题并进行优化。Performance API 提供了多个方法和属性,可以监测页面加载时间、资源加载时间、代码执行时间、内存使用情况、帧率等等性能指标。

以下是 Performance API 中常用的一些方法和属性:

  • performance.mark(name):创建一个新的性能条目,并在当前时间点标记该条目。
  • performance.measure(name, startMarkName,endMarkName):在两个标记点之间测量性能,并创建一个新的性能条目。
  • performance.getEntries():返回所有的性能条目。
  • performance.getEntriesByName(name):返回指定名称的性能条目。
  • performance.now():返回当前时间点的时间戳,精度为毫秒。
  • performance.timing:返回页面加载时间的性能指标,包括 DNS 查询时间、TCP 连接时间、请求时间、响应时间等等。

5、框架层面的错误捕获

VUE: Vue.config.errorHandler

Vue.config.errorHandler 是 Vue.js 提供的一个全局错误处理器,用于捕获 Vue.js 应用程序中的未处理异常。以下是一个例子,演示如何使用 Vue.config.errorHandler 捕获 Vue.js 应用程序中的未处理异常:

Vue.config.errorHandler = function(err, vm, info) {
 // 收集异常信息
 const errorData = {
   message: err.message,
   stack: err.stack,
   info: info,
 };

 // 将异常信息发送到服务器或其他地方进行分析和报告
 sendError(errorData)
};

React: ErrorBoundary

React 的 ErrorBoundary 是 React 提供的一个组件,用于捕获 React 应用程序中的未处理异常。以下是一个例子,演示如何使用 ErrorBoundary 捕获 React 应用程序中的未处理异常:

class MyErrorBoundary extends React.Component {
 constructor(props) {
   super(props);
   this.state = { hasError: false };
 }

 static getDerivedStateFromError(error) {
   return { hasError: true };
 }

 componentDidCatch(error, info) {
   // 收集异常信息
   const errorData = {
     message: error.message,
     stack: error.stack,
     info: info,
   };

   // 将异常信息发送到服务器或其他地方进行分析和报告
   sendError(errorData);
 }

 render() {
   if (this.state.hasError) {
     return <h1>出错了!</h1>;
   }

   return this.props.children;
 }
}

我们使用 ErrorBoundary 组件来捕获 React 应用程序中的未处理异常,并收集异常信息。当 React 应用程序发生未处理异常时,会触发 componentDidCatch 事件,并将异常信息作为事件参数传递给回调函数。然后我们将异常信息发送到服务器或其他地方进行分析和报告。