React 错误处理和日志记录的思考与设计
Posted c.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React 错误处理和日志记录的思考与设计相关的知识,希望对你有一定的参考价值。
文章目录
React 错误处理和日志记录的思考与设计
在平时的工作,js报错是比较常见的一个情景,当出现错误的时候,用户上报问题我们往往需要去定位问题的原因,但是因为错误存在于用户的客户端,所以我们没法很好的拿到错误的信息,所以如果当我们前端js出现异常的时候能及时上报的话,那我们的问题就比较好解决了。
其实讲到上面的需求,我们可能就知道我们想要的其实就是一个前端的异常监控平台,现在市面上有很多这样的平台:前端异常监控平台对比,网上比较多推荐的是:sentry,它对异常数据的收集和分析更加完善,如果公司有条件私有化部署的话比较推荐使用。
我们先不考虑使用现成的平台,因为我们想要的功能比较简单,而且部署一套监控平台公司不一定允许,所以可以考虑在自己项目中进行处理,不引用第三方的平台。当然有条件我还是建议不要自己造轮子了。
那这里就会涉及到几个方面的处理:
- 前端需要采集哪些异常数据?
- 前端怎么统一捕获异常?,因为我们不想对现有代码做太多的侵入性的
try..catch
的捕获 - 如何上报数据?
- 接收到异常上报之后如何处理以及如何通知开发人员?
前端需要采集哪些异常数据?
前端异常其实无非两种:
- call后端API接口异常
- 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
但是错误边界有很多场景是无法捕获到异常的:
- 自身的错误
- 异步的错误
- 事件中的错误
- 服务端渲染的错误
所以总结来说:仅处理渲染子组件期间的同步错误
所以除此之外还可以通过监听onerror
事件来捕获异常,可以参考:搭建前端监控,如何采集异常数据?
window.addEventListener('error', function(event) ... )
如何上报数据?
这个应该很好解决,只要我们在前端把我们的异常信息都封装好,然后通过API把数据上报到后端服务即可。
主要的难度其实在于前端异常数据的组装,以下有一些比较重要的信息需要一并记录,方便我们以后更好查阅。
接口异常
对于接口异常来说有以下几项:
- code:http 状态码
- url:接口请求地址
- method:接口请求方法
- params:接口请求参数
- error:接口报错信息
- user:请求用户
前端异常
而对于前端异常来说有以下几项
- url:当前访问URL
- error:具体错误堆栈信息
- user: 当前操作用户
存在的问题
同时在组装和上报数据的时候又存在几个问题:
- 如果一次操作有很多个重复的错误,所以可能会出现多次重复请求的情况
- 如果上报的接口无法访问,就会丢失掉当前的上报信息。
- 对于第一个问题,可以考虑对请求接口做缓存,一段时间内同样的请求参数不做多次请求。
- 对于第二个问题,首先上报的接口可能需要去掉全局的错误拦截器,还有对于用户未登录造成的错误也不应该拦截,因为用户未登录的时候其实上报接口也是不可用的。对于上报接口出现暂时无法访问的情况下,是否可以考虑缓存到浏览器? 提供一个按钮供用户待服务正常后上报? 还是对于这种比较极端的情况可以忽略?
处理上报异常和通知
对于处理上报异常和通知可以采取如下方式
- 后端把请求日志打印出来,如果后端做了ELK之类的日志收集服务,可以利用这个功能查询日志。
- 后端采用MongoDB存储数据
- 设置数据设置ttl过期,保留一天的数据,防止数据过多
- 设置定时任务抽取错误日志,把数据写入excel或者其他方式,然后通过email发送给开发人员
参考
React Error Handling and Logging Best Practices
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捕获错误 getDerivedStateFromError()和componentDidCatch()
React Logging and Error Handling Best Practices
React Error and Performance Monitoring
Catching Errors in React with Error Boundaries
以上是关于React 错误处理和日志记录的思考与设计的主要内容,如果未能解决你的问题,请参考以下文章