叫别人做网站要注意什么,编写网站策划书,企业微信公众号怎么开通,青田县建设局官方网站前言
现有的大部分监控方案都是针对服务端的#xff0c;而针对前端的监控很少#xff0c;诸如线上页面的白屏时间是多少、静态资源的加载情况如何、接口请求耗时好久、什么时候挂掉了、为什么挂掉#xff0c;这些都不清楚。
因而#xff0c;我们需要一个前端的页面监控系…前言
现有的大部分监控方案都是针对服务端的而针对前端的监控很少诸如线上页面的白屏时间是多少、静态资源的加载情况如何、接口请求耗时好久、什么时候挂掉了、为什么挂掉这些都不清楚。
因而我们需要一个前端的页面监控系统持续监控和预警页面性能的状况并且在发现瓶颈时用于指导优化工作。
前端监控目标
分为性能监控及异常监控 保证稳定性异常监控 错误监控包括 JavaScript 代码错误Promsie 错误接口XHRfetch错误资源加载错误scriptlink 等等这些错误大多会导致页面功能异常甚至白屏。 提升用户体验性能监控 性能监控包括页面的加载时间接口响应时间等侧面反应了用户体验的好坏。
性能监控
页面加载过程
简单看一下从输入 url 到页面加载完成的过程如下
首先需要通过 DNS域名解析系统将 URL 解析为对应的 IP 地址然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接随后我们向服务端抛出 HTTP 请求服务端处理完我们的请求之后把目标数据放在 HTTP 响应里返回给客户端拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕页面便呈现给了用户。 我们可以将这个过程分为如下的过程 DNS 解析 TCP 连接 HTTP 请求抛出 服务端处理请求HTTP 响应返回 浏览器拿到响应数据解析响应内容把解析的结果展示给用户
从开发者角度观察页面加载各阶段
从输入 url 到用户可以使用页面的全过程时间统计会返回一个 PerformanceTiming 对象单位均为毫秒。 关于 performace已经在《从前端角度浅谈性能》中进行过介绍下面再强调一下
各阶段的性能耗时可以通过 APIwindow.performance 来获取对应的具体方法有performance.timing、performance.getEntriesByType (‘resource’)、performance.navigation 等。 如上开发者可以通过 performance 中各阶段的时间戳分别获取到 页面各阶段的性能指标具体的个静态资源的加载耗时、及 页面是否重定向和重定向耗时。 要触发执行的属性 navigationStart: 在同一个浏览器上下文中前一个网页与当前页面不一定同域unload 的时间戳如果无前一个网页 unload 则与 fetchStart 值相等 redirectStart: 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算否则值为 0 unloadEventStart: 前一个网页与当前页面同域unload 的时间戳如果无前一个网页 unload 或者前一个网页与当前页面不同域则值为 0 redirectEnd: 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内的重定向才算否则值为 0 unloadEventEnd: 和 unloadEventStart 相对应返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳 fetchStart: 浏览器准备好使用 HTTP 请求抓取文档的时间这发生在检查本地缓存之前 domainLookupStart:DNS 域名查询开始的时间如果使用了本地缓存即无 DNS 查询或持久连接则与 fetchStart 值相等 domainLookupEnd:DNS 域名查询完成的时间如果使用了本地缓存即无 DNS 查询或持久连接则与 fetchStart 值相等 connectStart:HTTPTCP 开始建立连接的时间如果是持久连接则与 fetchStart 值相等如果在传输层发生了错误且重新建立连接则这里显示的是新建立的连接开始的时间 secureConnectionStart:HTTPS 连接开始的时间如果不是安全连接则值为 0 connectEnd:HTTPTCP 完成建立连接的时间完成握手如果是持久连接则与 fetchStart 值相等如果在传输层发生了错误且重新建立连接则这里显示的是新建立的连接完成的时间 requestStart:HTTP 请求读取真实文档开始的时间完成建立连接包括从本地读取缓存连接错误重连时这里显示的也是新建立连接的时间 responseStart:HTTP 开始接收响应的时间获取到第一个字节包括从本地读取缓存 responseEnd:HTTP 响应全部接收完成的时间获取到最后一个字节包括从本地读取缓存 domLoading: 开始解析渲染 DOM 树的时间此时 Document.readyState 变为 loading并将抛出 readystatechange 相关事件 domInteractive: 完成解析 DOM 树的时间Document.readyState 变为 interactive并将抛出 readystatechange 相关事件 domContentLoadedEventStart:DOM 解析完成后网页内资源加载开始的时间文档发生 DOMContentLoaded 事件的时间 domContentLoadedEventEnd:DOM 解析完成后网页内资源加载完成的时间如 JS 脚本加载执行完毕文档的 DOMContentLoaded 事件的结束时间 domComplete:DOM 树解析完成且资源也准备就绪的时间Document.readyState 变为 complete并将抛出 readystatechange 相关事件 loadEventStart:load 事件发送给文档也即 load 回调函数开始执行的时间如果没有绑定 load 事件值为 0 loadEventEnd:load 事件的回调函数执行完毕的时间如果没有绑定 load 事件值为 0
各个阶段性能计算可以自定义
const { timing, navigation } window.performance
const loadPageInfo {};// 页面加载类型区分第一次load还是reload, 0初次加载、1重加载
loadPageInfo.loadType navigation.type;// 页面加载完成的时间 - 几乎代表了用户等待页面白屏的时间
loadPageInfo.loadPage timing.loadEventEnd - timing.navigationStart;// 重定向的时间
loadPageInfo.redirect timing.redirectEnd - timing.redirectStart;// 卸载页面的时间
loadPageInfo.unloadEvent timing.unloadEventEnd - timing.unloadEventStart;// 查询 DNS 本地缓存的时间
loadPageInfo.appCache timing.domainLookupStart - timing.fetchStart;// 【重要】DNS 查询时间
// 页面内是不是使用了太多不同的域名导致域名查询的时间太长推荐 DNS 预加载。
// 可使用 HTML5 Prefetch 预查询 DNS
loadPageInfo.lookupDomain timing.domainLookupEnd - timing.domainLookupStart;// HTTPTCP建立连接完成握手的时间
loadPageInfo.connect timing.connectEnd - timing.connectStart;// 【重要】HTTP请求及获取 文档内容的时间
loadPageInfo.request timing.responseEnd - timing.responseStart;// 【重要】前一个页面 unload 到 HTTP获取到 页面第一个字节的时间
// 【原因】这可以理解为用户拿到你的资源占用的时间推荐 加异地机房加 CDN 处理加宽带加 CPU 运算速度
// TTFB 即 Time To First Byt
loadPageInfo.ttfb timing.responseStart - timing.navigationStart;// 解析 DOM 树结构的时间
loadPageInfo.domReady timing.domComplete - timing.responseEnd;// 【重要】执行 onload 回调函数的时间
// 【原因】是否太多不必要的操作都放在 onload 回调函数里执行了推荐 延迟加载、按需加载的策略
loadPageInfo.loadEvent timing.loadEventEnd - timing.loadE异常监控 Javascript 错误js 错误、promise 错误 监听 error 错误资源加载错误
console.error
// 重写console.error可以捕获更全面的报错信息
var oldError console.error;console.error function(tempErrorMsg){
var errorMsg ( arguments[0] arguments[0].message ) || tempErrorMsg;
var lineNumber 0;
var columnNumber 0;
var errorStack arguments[0] arguments[0].stack;
if( !errorStack ){
saveJSError( console_error, errorMsg, , lineNumber, columnNumber, CustomizeError: errorMsg );
}else{
saveJSError( console_error, errorMsg, , lineNumber, columnNumber, errorStack );
}return oldError.apply( console, arguments )error 事件
通过对 error 事件的监听可以捕捉到 js 语法 及 资源加载 的错误。根据 event.target.src/href 来判断是否为资源加载错误。
window.addEventListener( error, function(e){
var errorMsg e.error e.error.message,
errorStack e.error e.error.stack,
pageUrl e.filename,
lineNumber e.lineno,
columnNumber e.colno;saveJSError( on_error, errorMsg, pageUrl, lineNumber, columnNumber, errorStack );
} );Promise
// 捕获未处理的Promise错误
window.onunhandledrejection function(e){
var errorMsg ;
var errorStack ;
if( typeof e.reason object ){
errorMsg e.reason.message;
errorStack e.reason.stack;
}else{
errorMsg e.reason;
errorStack ;}saveJSError( on_error, errorMsg, , 0, 0, UncaughtInPromiseError: errorStack );
}