前端异常监控 - BadJS
前端页面的问题我们是怎么发现的?
- 测试验证
- 同事提出
- 用户投诉
上报组件
前端页面错误怎么捕获?
// onerror
window.onerror = function(msg, url, row, col, error) {
// todo report
report({
msg: msg,
url: url,
row: row,
col: col
});
};
// onerror
window.onerror = function(msg, url, row, col, error) {
// get error stack
// Firefox and chrome support stack trace
var newMsg = error && error.stack ? _processStackMsg(error) : msg;
// todo report
report({
msg: newMsg,
url: url,
row: row,
col: col
});
};
// process error stack
var _processStackMsg = function(error) {
// error stack
var stack = error.stack.replace(/\n/gi, "")
.split(/\bat\b/).slice(0, 5).join("@").replace(/\?[^:]+/gi, "");
// error message
var msg = error.toString();
return stack.indexOf(msg) < 0 ? (msg + "@" + stack) : stack;
};
什么是 Script error ?
出现 “Script error” 的场景和条件:
1、通过 window.onerror 注册监听脚本错误事件
2、浏览器:Firefox、Chrome、Safari、IE7+(*)
3、页面内使用了 script 标签引入,非同域的资源, 且发生脚本错误。
举例:
http://ke.qq.com/index.html 里引用了
http://7.url.cn/index.js
本质上是出于安全考虑。因为 script 标签引入文件内容的时候是忽略文件本身的MIME声明,且是允许跨域请求的。这里如果不屏蔽掉跨域情况下的错误信息,很可能会给黑客提供一个攻击通道。
http://www.webryan.net/2012/12/something-about-window-onerror-script-error/
// http://trac.webkit.org/browser/trunk/Source/WebCore/dom/ScriptExecutionContext.cpp#L347
bool ScriptExecutionContext::sanitizeScriptError(
String& errorMessage,
int& lineNumber,
int& columnNumber,
String& sourceURL,
CachedScript* cachedScript
)
{
URL targetURL = completeURL(sourceURL);
if (securityOrigin()->canRequest(targetURL) ||
(cachedScript &&
cachedScript->passesAccessControlCheck(*securityOrigin())
)
)
return false;
errorMessage = "Script error.";
sourceURL = String();
lineNumber = 0;
columnNumber = 0;
return true;
}
怎么解决 Script error ?
在脚本文件的 HTTP response header 中设置 CORS
比如: Access-Control-Allow-Origin: http://ke.qq.com
在页面的 script 标签中设置 crossorigin 属性
比如: <script src="http://7.url.cn/index.js" crossorigin></script>
CORS header 和 crossorigin 取值问题
anonymous(默认)
CORS 不等于 origin, 不能带 cookie
CORS header 和 crossorigin 取值问题
use-credentials
CORS 不能设置为 *,能带 cookie
CORS 不等于 origin,js 直接不加载
Access-Control-Allow-Credentials: true
通过 XHR 获取脚本资源, 通过 script 标签 innerText 插入到页面
会丢失错误的行号列号和文件名等信息
资源加载切换到主域
会失去使用 CDN 的优势, 适合在排查问题的时候灰度一部分用户使用
使用 try catch
- 每个方法都包裹上 try catch
- 对主要入口方法进行try catch
只需要对异步模块和业务主入口添加 try catch
- setTimeout 和 setInterval
- 事件绑定
- ajax callback
- define 和 require
- 业务主入口
组件内捕获到异常怎么处理
- 直接吃掉
- 向上抛
还有
- 合并上报(延迟)
- 日志级别(1-debug 2-info 4-error 8-fail)
- 抽样上报
- new Image VS XHR
- 200 VS 204
- ignore
项目中怎么接入
<!-- 2.56 KB -->
<script src="/dist/bj-report.min.js"></script>
<!-- 或者 4.48 KB -->
<script src="/dist/bj-report-tryjs.min.js"></script>
BJ_REPORT.init({
id: 1 // 填写在管理后台申请的上报 id
});
BJ_REPORT.spyAll();
上报后台
- nodejs
- ZeroMQ
- mongodb
- mysql
管理后台
邮件报表
最佳实践
- 上报组件在业务代码前加载执行
- 监控页面所有请求
- 监控业务关键点
接下来要做的
- sourcemap 支持
- 项目文档完善
- https 支持
- 简化部署
- ...
Q&A
Thanks
前端异常监控 - BadJS
By loskael
前端异常监控 - BadJS
前端异常监控
- 24,227