-
Notifications
You must be signed in to change notification settings - Fork 52
reporter2
LYF edited this page Aug 18, 2016
·
4 revisions
调调前端异常监控
除了监控客户端的异常之外,还监控图片404
经过真机测试:
IE8下可以上报0,3
在IE9+及其他现代浏览器中能上报所有类型的异常
相比较 reporter 进一步进行了简化,删除了不必要的方法和逻辑。
删除script标签更健壮了。
/**
* 前端异常监控
*/
/**
* 0 代码错误
* 1 主动上报的错误
* 2 主动上报的warn
* 3 图片挂了
*/
(function(window) {
'use strict';
/**
* 1、减少传数量,在后台拿出UA即可
* 没必要在前端分析操作系统、浏览器、浏览器版本
*
* 2、减少传数量,在后台拿到refer,这样发生异常的url也不用传输了
*/
/*
原生ajax函数。用法与jquery ajax一致。
author:pod4g
修改时间:2016,02,20
版本:1.1
https://github.com/pod4g/qAjax
*/
// TODO: 作为上报组件的一个功能。简化成只支持JSONP即可
// 这样就支持IE8+以上的上报了。
function request(opts) {
var
data = opts.data || {}, // 请求参数
prop2prame = function(data) {
var ret = "", prop;
if (!data || typeof data !== 'object') {
return ret;
}
for (prop in data) {
ret += prop + '=' + data[prop] + '&';
}
return ret;
};
// 尽可能地缩短传输参数。
// 在IE8 下的URL地址总长度为:4076,超过该长度会自动忽略后面的内容;
// 在firefox 25下的URL地址总长度可以达到:7530,超过该长度会访问错误;
// 在chrome 29.0.1547.62 的最大总长度达到:7675,超过该长度会访问错误;
// var callbackParamValue = '_cb__' + Math.floor(Math.random() * 10000);
// var url = '//120.27.45.36:3003/error_reciver?' + prop2prame(data);
// var param = prop2prame(data);
// console.log(param);
// b=_cb__4553
// 原来key是c
// 导致和错误信息中的 c 即列号冲突
// 在server端拿到的c为["9","_cb__4553"]
// 导致insert到数据库中报语法错误
// param = param.concat('b').concat('=').concat(callbackParamValue);
// if ( url.indexOf('?') == -1 ) {
// param = '?' + param;
// } else {
// param = '&' + param;
// }
(function(src) {
var __script__ = document.createElement('script');
__script__.type = 'text/javascript';
__script__.src = src;
__script__.onerror = __script__.onload = function(e){
removeChild(__script__);
__script__ = undefined;
}
document.body.appendChild(__script__);
// 默认超时时间为9秒
setTimeout(function() {
removeChild(__script__);
}, 9000);
})( '//x.x.x.x:3003/error_reciver?' + prop2prame(data) );
}
function removeChild(node){
if(!node) return;
var f = document.createDocumentFragment();
f.appendChild(node);
f.removeChild(node);
}
function addEvent(obj, event, handler) {
if (obj.addEventListener) {
obj.addEventListener(event, handler);
} else if (obj.attachEvent) {
obj.attachEvent('on' + event, handler);
}
}
function isFunctionOrObject(obj) {
var type = typeof obj;
return type === 'function' || type === 'object';
}
function encode(str){
return encodeURIComponent( str || '' );
}
/**
* 传输的参数格式为:
* {
* t: 0,1,2,3 // type
* m: 'error info' // message
* f: 'xxx.js' // filename
* l: 119 // lineno
* c: 120 // colno
* }
*/
// hook console
(function() {
function errorHook(msg) {
var type = typeof msg,
err = {
"t": 1
};
if (type === 'string' || type === 'number') {
err.m = encode(msg);
} else if (type === 'object') {
err.m = encode(msg.message);
err.f = msg.filename || '';
err.l = msg.lineno || '';
err.c = msg.colno || '';
}
// console.log('触发主动上报error' + JSON.stringify(err));
request({ data: err });
}
function warnHook(msg) {
// console.log('触发主动上报warn' + JSON.stringify(warn));
// request({url:'//120.27.45.36:3003/error_reciver', data:JSON.stringify({type:'warn',message: msg})};
request({data: {
"t": 2,
"m": encode(msg)
}});
}
var console = window.console;
if (console) {
var oError = console.error,
oWarn = console.warn;
if (isFunctionOrObject(oError)) {
console.error = function(msg) {
try {
oError.call(console, msg);
// console.log('执行errorHook');
errorHook(msg);
} catch (e) { // 必须有参数,在IE8下会报 “缺少标识符” 错误
// errorHook(msg);
}
}
}
if (isFunctionOrObject(oWarn)) {
console.warn = function(msg) {
try {
oWarn.call(console, msg);
warnHook(msg);
} catch (e) { // 必须有参数,在IE8下会报 “缺少标识符” 错误
// warnHook(msg);
}
}
}
} else {
window.console = {
error: function(msg) {
errorHook(msg);
},
warn: function(msg) {
warnHook(msg);
}
}
}
}());
addEvent(window, 'error', function(e, sUrl, sLine) {
// e = e || event;
// alert(e);
// 代码错误 type: 0
// ie8-
var error;
if(
// ie8-
typeof e === 'string'
){
error = {
t: 0,
m: encode(e),
l: sLine
}
}
else // w3c
{
error = {
t: 0,
m: encode(e.message),
f: e.filename,
l: e.lineno,
c: e.colno
}
}
// console.log('应该上报一次,代码执行异常类型。信息:', JSON.stringify(error));
// e.preventDefault(); // 不报错
if(error){
request({ data: error });
}
});
addEvent(window, 'load', function() {
var imgs = document.getElementsByTagName('img'),
brokens = [],
img, i = 0;
while (img = imgs[i++]) {
if (!img.complete || (img.naturalWidth === 0 && img.naturalHeight === 0)) {
brokens.push(img.src);
}
}
// console.log('应该上报一次,图片挂了。信息:', JSON.stringify(brokens));
// 图片挂了 type: 3
if(brokens.length > 0 ){
request({ data: {
t:3,
m: encode(brokens.join(','))
}});
}
});
}(window));