Front-end monitoring solutions that you may not know

foreword

Most of the existing monitoring solutions are aimed at the server side, but very little monitoring is aimed at the front end, such as how much time is spent on the white screen of the online page, how the static resources are loaded, how long the interface request takes, and when it hangs up , Why hang up, these are not clear.

Therefore, we need a front-end page monitoring system to continuously monitor and warn the status of page performance, and use it to guide optimization when bottlenecks are found.

Front-end monitoring target

Divided into performance monitoring and exception monitoring

  • Ensure stability (exception monitoring) Error monitoring includes JavaScript code errors, Promsie errors, interface (XHR, fetch) errors, resource loading errors (script, link, etc.), etc. Most of these errors will cause page function abnormalities or even white screens.

  • Improve user experience (performance monitoring) Performance monitoring includes page loading time, interface response time, etc., which reflect the quality of user experience.

performance monitoring

page load process

Take a brief look, the process from entering the url to the completion of page loading is as follows:

First, we need to resolve the URL to the corresponding IP address through DNS (Domain Name Resolution System), and then establish a TCP network connection with the server determined by this IP address, and then we throw an HTTP request to the server, and the server finishes processing our After the request, put the target data in the HTTP response and return it to the client, and the browser that gets the response data can start a rendering process. After rendering, the page is presented to the user.

We can divide this process into the following processes:

  1. DNS resolution

  2. TCP connection

  3. HTTP request throws

  4. The server processes the request, and the HTTP response is returned

  5. The browser gets the response data, parses the response content, and displays the parsed results to the user

From the developer's perspective, observe the stages of page loading

It will return a PerformanceTiming object with the unit of milliseconds for the statistics of the whole process time from inputting the url to the user being able to use the page. Regarding performace, it has already been introduced in "A Brief Discussion on Performance from the Front-End Perspective", and I will emphasize it again below:

The performance time consumption of each stage can be obtained through the API: window.performance, and the corresponding specific methods are: performance.timing, performance.getEntriesByType ('resource'), performance.navigation, etc. As above, developers can obtain the performance indicators of each stage of the page through the timestamps of each stage in performance, the specific loading time of each static resource, and whether the page is redirected and the redirection time.

properties to trigger execution

  • navigationStart: In the same browser context, the timestamp of the unload of the previous webpage (not necessarily the same domain as the current page), if there is no previous webpage unload, it will be equal to the value of fetchStart

  • redirectStart: The time when the first HTTP redirect occurred. Only if there is a redirect and it is a redirect within the same domain name, otherwise the value is 0

  • unloadEventStart: The timestamp of the unload of the previous web page (same domain as the current page), if there is no previous web page unloaded or the previous web page is in a different domain from the current page, the value will be 0

  • redirectEnd: The time when the last HTTP redirect completed. Only if there is a redirect and it is a redirect within the same domain name, otherwise the value is 0

  • unloadEventEnd: Corresponding to unloadEventStart, returns the timestamp when the callback function bound to the unload event of the previous webpage is executed

  • fetchStart: when the browser is ready to fetch the document using an HTTP request, this happens before checking the local cache

  • domainLookupStart: DNS domain name query start time, if local cache (ie no DNS query) or persistent connection is used, it is equal to fetchStart value

  • domainLookupEnd: The time when the DNS domain name query is completed, if a local cache (ie no DNS query) or a persistent connection is used, it is equal to the value of fetchStart

  • connectStart: The time when HTTP (TCP) starts to establish a connection. If it is a persistent connection, it is equal to the fetchStart value. If an error occurs at the transport layer and the connection is re-established, the time when the newly established connection starts is displayed here

  • secureConnectionStart: The time when the HTTPS connection started, or 0 if it is not a secure connection

  • connectEnd: The time when HTTP (TCP) completes the establishment of the connection (completes the handshake). If it is a persistent connection, it is equal to the fetchStart value. If an error occurs at the transport layer and the connection is re-established, the newly established connection is displayed here. time

  • requestStart: The time when the HTTP request starts to read the real document (complete the connection establishment), including reading the cache from the local, and when the connection error reconnects, the time of the newly established connection is also displayed here

  • responseStart: The time when HTTP starts to receive the response (get the first byte), including reading from the local cache

  • responseEnd: The time when all HTTP responses are received (get to the last byte), including reading from the local cache

  • domLoading: The time to start parsing and rendering the DOM tree. At this time, Document.readyState changes to loading, and readystatechange related events will be thrown

  • domInteractive: When the DOM tree is finished parsing, Document.readyState becomes interactive, and readystatechange related events will be thrown

  • domContentLoadedEventStart: After the DOM parsing is completed, the time when the resource loading in the webpage starts, and the time when the DOMContentLoaded event occurs in the document

  • domContentLoadedEventEnd: After the DOM parsing is completed, the time when the resource loading in the webpage is completed (such as the JS script loading and execution is completed), and the end time of the DOMContentLoaded event of the document

  • domComplete: When the DOM tree parsing is completed and resources are ready, Document.readyState becomes complete, and readystatechange related events will be thrown

  • loadEventStart: The load event is sent to the document, that is, the time when the load callback function starts executing. If the load event is not bound, the value is 0

  • loadEventEnd: The time when the callback function of the load event finishes executing, if no load event is bound, the value is 0

Performance calculation at each stage (can be customized)

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;

// HTTP(TCP)建立连接完成握手的时间
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

Abnormal monitoring

  1. Javascript errors (js errors, promise errors)

  2. Listen for error errors (resource loading errors)

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 event

By listening to the error event, errors in js syntax and resource loading can be caught. According to event.target.src/href to determine whether it is a resource loading error.

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 );
}

Guess you like

Origin blog.csdn.net/baidu_38493460/article/details/129224675