React 错误处理和日志记录的思考与设计

Posted c.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React 错误处理和日志记录的思考与设计相关的知识,希望对你有一定的参考价值。

文章目录

React 错误处理和日志记录的思考与设计

在平时的工作,js报错是比较常见的一个情景,当出现错误的时候,用户上报问题我们往往需要去定位问题的原因,但是因为错误存在于用户的客户端,所以我们没法很好的拿到错误的信息,所以如果当我们前端js出现异常的时候能及时上报的话,那我们的问题就比较好解决了。

其实讲到上面的需求,我们可能就知道我们想要的其实就是一个前端的异常监控平台,现在市面上有很多这样的平台:前端异常监控平台对比,网上比较多推荐的是:sentry,它对异常数据的收集和分析更加完善,如果公司有条件私有化部署的话比较推荐使用。

我们先不考虑使用现成的平台,因为我们想要的功能比较简单,而且部署一套监控平台公司不一定允许,所以可以考虑在自己项目中进行处理,不引用第三方的平台。当然有条件我还是建议不要自己造轮子了。

那这里就会涉及到几个方面的处理:

  1. 前端需要采集哪些异常数据?
  2. 前端怎么统一捕获异常?,因为我们不想对现有代码做太多的侵入性的try..catch的捕获
  3. 如何上报数据?
  4. 接收到异常上报之后如何处理以及如何通知开发人员?

前端需要采集哪些异常数据?

前端异常其实无非两种:

  1. call后端API接口异常
  2. js代码异常

前端怎么统一捕获异常?

接口异常

对于第一种call后端API接口异常一般都是在请求时候触发的,而我们现在一般都是使用axios或者 umi-request去请求后台的。

如果你用 Promise 的写法,则用 .catch 捕获

request(url, 
    method: 'GET'
).catch((err) => 
    // err 就是捕获到的错误对象
    handleError(err);
);

如果你用 async/await 的写法,则用 try..catch.. 捕获:

async () => 
  try 
    await request(url, 
         method: 'GET'
    )
   catch (err) 
    //进行异常采集
    handleError(err);
  
;

当然我们不建议这种方式,因为埋点的地方太多了,很多冗余代码,对现有代码的侵入性也很强。

我们一般都是使用拦截器中捕获异常来捕获异常。

比如在umi-request中我们可以能会这么做,定义一个错误拦截器来捕获异常

export const errorHandler = function (error: ResponseError<ErrorResponse>) 
  //进行异常采集
  handleError(error);
  throw error;
;

export const request: RequestConfig = 
  errorHandler,
;

前端异常

对于React来说,可以使用React的Error Boundary来处理渲染子组件期间的同步错误,错误边界是一种 React 组件,这种组件可以捕获发生在其子组件树任何位置的 javascript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。错误边界在渲染期间、生命周期方法和整个组件树的构造函数中捕获错误。

具体如何使用可以参考官网:Error Boundaries

还可以参考:HOW TO HANDLE ERRORS EFFICIENTLY IN REACT

但是错误边界有很多场景是无法捕获到异常的:

  1. 自身的错误
  2. 异步的错误
  3. 事件中的错误
  4. 服务端渲染的错误

所以总结来说:仅处理渲染子组件期间的同步错误

所以除此之外还可以通过监听onerror事件来捕获异常,可以参考:搭建前端监控,如何采集异常数据?

window.addEventListener('error', function(event)  ... )

如何上报数据?

这个应该很好解决,只要我们在前端把我们的异常信息都封装好,然后通过API把数据上报到后端服务即可。

主要的难度其实在于前端异常数据的组装,以下有一些比较重要的信息需要一并记录,方便我们以后更好查阅。

接口异常

对于接口异常来说有以下几项:

  1. code:http 状态码
  2. url:接口请求地址
  3. method:接口请求方法
  4. params:接口请求参数
  5. error:接口报错信息
  6. user:请求用户

前端异常

而对于前端异常来说有以下几项

  1. url:当前访问URL
  2. error:具体错误堆栈信息
  3. user: 当前操作用户

存在的问题

同时在组装和上报数据的时候又存在几个问题:

  1. 如果一次操作有很多个重复的错误,所以可能会出现多次重复请求的情况
  2. 如果上报的接口无法访问,就会丢失掉当前的上报信息。
  • 对于第一个问题,可以考虑对请求接口做缓存,一段时间内同样的请求参数不做多次请求。或者做防抖,限流或者并发控制都可以。
  • 对于第二个问题,首先上报的接口可能需要去掉全局的错误拦截器,还有对于用户未登录造成的错误也不应该拦截,因为用户未登录的时候其实上报接口也是不可用的。对于上报接口出现暂时无法访问的情况下,是否可以考虑缓存到浏览器? 提供一个按钮供用户待服务正常后上报? 还是对于这种比较极端的情况可以忽略?

处理上报异常和通知

对于处理上报异常和通知可以采取如下方式

  1. 后端把请求日志打印出来,如果后端做了ELK之类的日志收集服务,可以利用这个功能查询日志。
  2. 后端采用MongoDB存储数据
  3. 设置数据设置ttl过期,保留一天的数据,防止数据过多
  4. 设置定时任务抽取错误日志,把数据写入excel或者其他方式,然后通过email发送给开发人员

参考

利用window.onerror收集js代码异常

前端异常监控平台对比

前端监控的搭建步骤,别再一头雾水了!

React16 中的异常处理(前端监控实现)

搭建前端监控,如何采集异常数据?

React Error Handling and Logging Best Practices

Error Boundaries

How do I set up custom error handling with React?

HOW TO HANDLE ERRORS EFFICIENTLY IN REACT

Logging and error management best practices in SSR apps

Client-side error logging in React web application

React中的错误边界(Error Boundary)

React之错误边界(ErrorBoundary)

React捕获错误 getDerivedStateFromError()和componentDidCatch()

SENTRY FOR REACT NATIVE

Sentry的应用接入与部署运维

React Logging and Error Handling Best Practices

React Error and Performance Monitoring

面试官:说说你在React项目是如何捕获错误的?

Catching Errors in React with Error Boundaries

以上是关于React 错误处理和日志记录的思考与设计的主要内容,如果未能解决你的问题,请参考以下文章

React 错误处理和日志记录的思考与设计

前端错误监控的简单设计与实现

前端错误监控的简单设计与实现

实时海量日志分析系统的架构设计实现以及思考

错误处理(包括日志记录)

实时海量日志分析系统的架构设计实现以及思考