我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!
背景
作为一个前端FE开发,当产品上线后,经常会遇到各种线上问题。但是我们会经常发现,问题不能很好的复现出来,这就对我们解决问题造成相当大的困扰。而导致不能很好复现的原因,可能是网络、系统、机型或者是用户行为。所以如何让我们在面对这些问题的时候,能有个清晰的思路是必要的。
问题来源
一般情况下,我们的处理的线上问题来源主要分为两种。
- 用户反馈
- 系统预警
错误分类
一般情况下,面对前端问题,我们会打开我们的控制台,去检查是否有错误。
- console
- network
当然,这只是我们去debugger问题的方式,错误的类型主要包含了:
- 前端代码异常
- 请求异常
- 静态资源异常
- Promise异常
- 跨域异常
- 页面崩溃异常
异常处理
面对这些异常,我们可以通过一下的方式去捕获这些异常。
Try...Catch
可以捕获同步运行的错误,但是对语法问题和异步错误无法捕获。
使用
try {}
catch(e) {}
语法异常使用Try...Catch
异步异常使用Try...Catch
window.onerror
window.onerror是一个全局变量,默认值为null。当JS运行时发生错误时,window会触发一个ErrorEvent接口的error事件,执行window.onerror()
使用
window.onerror = function(msg, source, lineno, colno, error) {
console.log('错误信息', msg)
console.log('出错文件名', source)
console.log('行号', lineno)
console.log('列号', colno)
console.log('Error对象', error)
}
但是,window.onerror也并不是万能的,面对JS的语法异常同样也是无法捕获的。同时在使用window.onerror的时候我们需要注意以下几个点
- window.onerroor函数只有在返回true的时候,异常才不会向上抛出。否则运行时还是会抛出异常信息
- onerror函数最好在所有JS脚本之前定义,否则可能存在部分异常无法捕获
window.addEventListen('error'|'unhandledrejection')
当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个 Event 接口的 error 事件,并执行该元素上的 onerror() 处理函数。这些 error 事件不会向上冒泡到 window ,不过(至少在 Firefox 中)能被单一的 window.addEventListener 捕获。
使用
window.addEventListen('error'|'unhandledrejection', e => {
console.log(e)
})
window.onerror 和 window.addEventListen('error')的区别
window.addEventListen('error')监听js运行时错误事件,会比window.onerror先触发,与onerror的功能大体类似,不过事件回调函数传参只有一个保存所有错误信息的参数,不能阻止默认事件处理函数的执行,但可以全局捕获资源加载异常的错误
上报错误
当我们能捕获这些异常的时候,怎么去使用这些异常才能更好的协助我们去更好的、快速的处理线上问题呢?
在这里我们以Sentry为例
集成上报平台
初始化Sentry
Sentry.init({
// 相关配置
beforeSend(event) {
// 在这里可根据业务情况发送特定信息
event.info = {
xx: 'xxx'
};
})
配置全局Sentry
可以使用全局配置配置项目相关信息
Sentry.setUser(object);
Sentry.tags(object);
Sentry.extra(object);
Sentry.level(object);
Sentry.fingerprint(object);
// 通过 setContext,设置 key 值,可自定义随事件传递的变量名
Sentry.setContext(key, context);
标准化异常捕获
标准化上报信息,如果是请求异常捕获,可以配置request id为tag,这样,就可以通过id快速查询到sentry的信息。
Sentry.captureMessage(sentryMessage, {
extra: {
url,
body: {
code,
message: errorMsg
}
},
tags: {
requestId: errorRes.response ? errorRes.response.requestId : ''
}
})
集成sourceMap
将SourceMap上传到Sentry,可快速定位到源码位置
const SentryCliPlugin = require('@sentry/webpack-plugin')
module.exports = {
configureWebpack: (config) => {
isLive && config.plugins.push(new SentryCliPlugin({ include: './dist' }))
},
}
代理调试
如果通过一系列操作,定位到问题归属在前端,后端数据正常。我们可以通过代理的方式在前端进行debugger调试。
工具
- whistle
- charles
whistle
whistle基于Node实现的跨平台web调试代理工具,类似的工具有Windows平台上的Fiddler,主要用于查看、修改HTTP、HTTPS、Websocket的请求、响应,也可以作为HTTP代理服务器使用,不同于Fiddler通过断点修改请求响应的方式,whistle采用的是类似配置系统hosts的方式,一切操作都可以通过配置实现,支持域名、路径、正则表达式、通配符、通配路径等多种匹配方式。
charles
Charles 是一个 HTTP 代理 / HTTP 监视器 / 反向代理,它使开发人员能够查看他们的机器和 Internet 之间的所有 HTTP 和 SSL / HTTPS 流量。这包括请求、响应和 HTTP 标头(其中包含 cookie 和缓存信息)。官方地址:www.charlesproxy.com/
使用
# 域名匹配
www.example.com
# 带端口的域名
www.example.com:6666
# 带协议的域名,支持:http、https、ws、wss、tunnel
http://www.example.com
# 路径匹配,同样支持带协议、端口
www.example.com/test
https:/www.exapmle.com/test
https:/www.exapmle.com:6666/test
# 正则匹配
/^https?://www.example.com/test/(.*)/ referer://http://www.test.com/$1
# 通配符匹配
^www.example.com/test/*** referer://http://www.test.com/$1
这样,我们可以将线上的地址代理到本地服务,然后通过线上数据去复现问题。去解决问题
结束语
2022.02.23
木更