-
Notifications
You must be signed in to change notification settings - Fork 52
reporter
LYF edited this page Aug 10, 2016
·
6 revisions
调调前端异常监控
除了监控客户端的异常之外,还监控图片404
经过真机测试:
IE8下可以上报0,3
在IE9+及其他现代浏览器中能上报所有类型的异常
/**
* 前端异常监控
*/
/**
* 0 代码错误
* 1 主动上报的错误
* 2 主动上报的warn
* 3 图片挂了
*/
/**
* 前端异常监控
*/
/**
* 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 || {}, // 请求参数
type = function(arg) {
var t = typeof arg,
s;
if (t === 'object') {
if (arg === null) {
return 'null';
} else {
s = Object.prototype.toString.call(arg);
return s.slice(8, -1).toLowerCase();
}
} else {
return t;
}
},
prop2prame = function(data) {
var ret = "",
prop;
if (!data || type(data) !== 'object') {
return ret;
}
for (prop in data) {
var val = data[prop];
if (type(val) === "array") {
for (var i = 0, l = val.length; i < l; i++) {
ret += prop + "=" + val[i] + "&";
}
} else {
ret += prop + "=" + val + "&";
}
}
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 = opts.url;
var param = prop2prame(data);
// 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;
}
var doJSONP = function(src) {
var __script__ = document.createElement('script');
__script__.type = 'text/javascript';
__script__.src = src;
window[callbackParamValue] = function(text) {
// 执行完毕之后,抹除JSONP标记
window[callbackParamValue] = undefined;
document.body.removeChild(__script__);
}
document.body.appendChild(__script__);
var timeout = opts.timeout;
if (timeout > 0) {
setTimeout(function() {
document.body.removeChild(__script__);
}, timeout)
}
}
doJSONP(opts.url + param);
}
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;
var 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({
url: '//120.27.45.36:3003/error_reciver',
data: err
});
}
function warnHook(msg) {
var warn = {
"t": 2,
"m": encode(msg)
}
// console.log('触发主动上报warn' + JSON.stringify(warn));
// request({url:'//120.27.45.36:3003/error_reciver', data:JSON.stringify({type:'warn',message: msg})};
request({
url: '//120.27.45.36:3003/error_reciver',
data: warn
});
}
var console = window.console;
if (console) {
var oError = console.error;
var 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({
url: '//120.27.45.36:3003/error_reciver',
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 ){
var error = {
t:3,
m: encode(brokens.join(','))
};
request({
url: '//120.27.45.36:3003/error_reciver',
data: error
});
}
});
}(window));