前端性能监控
跨域处理
/**
* @author ruoshui
* @date 2020年4月4日21:19:05
* @version:0.1
*/
var frontEndMoniter ={}
;(function (moniter) {
/**
* 日志信息
* @type {{navigator: {appVersion: string, cookieEnabled: string, appName: string, addonsDesc: string, userAgent: string, appCodeName: string, platform: string}, screen: {availWidth: string, pixelDepth: string, addonsDesc: string, width: string, colorDepth: string, availHeight: string, height: string}, url: string}}
* @private
*/
var _logInfo ={
url: window.location.href, // 当前的连接地址
// 用户导航信息
navigator:{
appCodeName:"", // 浏览器的代码名
appName:"", // 浏览器的名称
appVersion:"", // 浏览器的平台和版本信息
cookieEnabled:"", // 指明浏览器中是否启用 cookie 的布尔值
platform:"", // 运行浏览器的操作系统平台
userAgent:"", // 由客户机发送服务器的user-agent 头部的值,
addonsDesc:""// 补充信息
},
// 客户端显示屏幕的信息
screen:{
availHeight:"", // 屏幕的高度(不包括Windows任务栏)
availWidth:"", // 屏幕的宽度(不包括Windows任务栏)
colorDepth:"", // 目标设备或缓冲器上的调色板的比特深度
height:"", // 屏幕的总高度
pixelDepth:"", // 屏幕的颜色分辨率(每象素的位数)
width:"", // 屏幕的总宽度,
addonsDesc:""// 补充信息
}
}
/**
* 性能信息
* @type {{timing: {redirect: number, request: number, loadEvent: number, unloadEvent: number, addonsDesc: string, lookupDomain: number, dnscache: number, loadPage: number, ttfb: number, domReady: number, connect: number}}}
* @private
*/
var _performanceInfo = {
timing:{
loadPage:0, // 页面加载完成的时间
domReady:0, // 解析 DOM 树结构的时间
redirect:0, // 重定向的时间
lookupDomain:0, // DNS 查询时间
ttfb:0,// Time To First Byte 的意思
request:0,// 内容加载完成的时间
loadEvent:0, // 执行 onload 回调函数的时间
dnscache:0, //DNS 缓存时间
unloadEvent:0, // 卸载页面的时间
connect: 0, //TCP 建立连接完成握手的时间
addonsDesc:""// 自定义补充信息
}
}
/**
* js 错误信息
* @private
*/
var _jsErrorInfo = {
message:'',
source:'',
lineno:'',
colno:'',
error:''
}
/**
* 初始化基本信息
*/
function initBaseInfo() {
if(window.navigator){
// 复制导航信息
_extend(_logInfo.navigator,window.navigator)
}
else{
console.error("当前浏览器不支持 navigator")
_logInfo.navigator["addonsDesc"] = "当前浏览器不支持 navigator"
}
if(window.screen){
// 复制屏幕信息
_extend(_logInfo.screen,window.screen)
}
else{
console.error("当前浏览器不支持 screen")
_logInfo.navigator["addonsDesc"] = "当前浏览器不支持 screen"
}
}
/**
* init 初始化性能信息
*/
function initPerformanceInfo() {
var performance = window.performance ||window.msPerformance ||window.webkitPerformance
if (!performance) {
// 当前浏览器不支持
console.log('你的浏览器不支持 performance 接口');
_performanceInfo.timing.addonsDesc = '你的浏览器不支持 performance 接口';
return;
}
var t = performance.timing;
var times = {};
//【重要】页面加载完成的时间
//【原因】这几乎代表了用户等待页面可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart;
//【重要】解析 DOM 树结构的时间
//【原因】反省下你的 DOM 树嵌套是不是太多了!
times.domReady = t.domComplete - t.responseEnd;
//【重要】重定向的时间
//【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
times.redirect = t.redirectEnd - t.redirectStart;
//【重要】DNS 查询时间
//【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
// 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
//【重要】读取页面第一个字节的时间
//【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
// TTFB 即 Time To First Byte 的意思
// 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
times.ttfb = t.responseStart - t.navigationStart;
//【重要】内容加载完成的时间
//【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
times.request = t.responseEnd - t.requestStart;
//【重要】执行 onload 回调函数的时间
//【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.loadEvent = t.loadEventEnd - t.loadEventStart;
// DNS 缓存时间
times.dnscache = t.domainLookupStart - t.fetchStart;
// 卸载页面的时间
times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
// 深度复制
_extend(_performanceInfo.timing,times)
}
/**
* 监控js 报错
* @param message
* @param source
* @param lineno
* @param colno
* @param error
*/
window.onerror = function(message, source, lineno, colno, error) {
_jsErrorInfo.message = message;
_jsErrorInfo.source =source;
_jsErrorInfo.lineno = lineno;
_jsErrorInfo.colno = colno;
_jsErrorInfo.error = error;
// 上报错误
reportError("http://localhost:8080/api/v1/log/info",_jsErrorInfo)
}
/**
* 上报错误信息
* @param info
*/
function reportError(url,info) {
var image = new Image();
// 允许跨域新特性
image.crossOrigin="anonymous"
image.onabort = image.onload = image.onerror
// 上报错误
image.src = url +"?logInfo=" + encodeURIComponent(JSON.stringify(info));
}
/**
* 扩展对象属性
* @param target
* @param source
* @private
*/
function _extend(target,source){
if(target && source){
for(var key in target){
target[key] = source[key]
}
}
}
window.onload = function () {
// 初始化信息
initBaseInfo();
// 初始化性能
initPerformanceInfo();
reportError("http://localhost:8080/api/v1/log/info",_logInfo)
// 性能指标
reportError("http://localhost:8080/api/v1/log/info",_performanceInfo)
}
})(frontEndMoniter)