網(wǎng)站監(jiān)控筆記(一) — Performance
What is website monitoring?
什么是網(wǎng)站監(jiān)控?其實(shí)我們主要是實(shí)時(shí)監(jiān)控網(wǎng)站性能,是否存在異常資源、請(qǐng)求、代碼出錯(cuò)?、頁面加載消耗時(shí)長(zhǎng)?等?一系列問題!如果出現(xiàn)這些問題,你能不能及時(shí)定位問題原因? 在之前的 《如何優(yōu)化祖?zhèn)鞔a》 這篇文章中我也有講到客戶流失率,感興趣的同學(xué)可以去看看。只不過是針對(duì)于網(wǎng)頁打開速度的,那如果你頁面請(qǐng)求資源都錯(cuò)誤了如 js、css、request 發(fā)生錯(cuò)誤了呢?不能及時(shí)定位問題,那豈不是GG了。主要是最近一直在考慮做一個(gè)性能監(jiān)控產(chǎn)品,老嚴(yán)也是特別在乎這一塊的內(nèi)容。
主要作用
測(cè)DNS污染檢測(cè) 網(wǎng)站打開速度檢測(cè) 網(wǎng)站資源出現(xiàn)異常 感知到業(yè)務(wù)出錯(cuò)的概率 發(fā)布后對(duì)性能有否存在影響 了解業(yè)務(wù)的穩(wěn)定性 對(duì)訪問用戶進(jìn)行分析
如何做?
網(wǎng)站性能監(jiān)控 監(jiān)控資源異常 借助輔助插件 后臺(tái)記錄日志 使用監(jiān)控平臺(tái) 捕捉異常代碼 資源阻塞處理
今天我們來講解一下 第一個(gè)性能監(jiān)控(主要是圍繞 js 中 performance api講解),因?yàn)殛P(guān)乎性能方面東西確實(shí)太多了
Go!

網(wǎng)站性能監(jiān)聽
什么是 performance ?
我們可以先了解一下 Performance [0],做網(wǎng)站監(jiān)控必備之一
MDN 這樣描述 Performance :
Performance接口可以獲取到當(dāng)前頁面中與性能相關(guān)的信息。它是 High Resolution Time API 的一部分,同時(shí)也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。
performance 屬性
先看看是個(gè)啥東西
console.log(window.performance)

可以看到輸出了 Performance 對(duì)象,里面包含了幾個(gè)屬性,分別是
memory ?預(yù)期跨瀏覽器支持不佳。

//?上下文內(nèi)可用堆的最大體積,以字節(jié)計(jì)算。
jsHeapSizeLimit
//?已分配的堆體積,以字節(jié)計(jì)算。
totalJSHeapSize
//?當(dāng)前 JS 堆活躍段(segment)的體積,以字節(jié)計(jì)算。
usedJSHeapSize
eventCounts 預(yù)期跨瀏覽器支持不佳。
timing
navigation
timeOrigin
onresourcetimingbufferfull
因?yàn)?memory 、與eventCounts 的支持性不是很好,所以我們先略過,感興趣的朋友可以去 MDN 瞧瞧
那我們接下來將這四個(gè)
timing
navigation
timeOrigin
onresourcetimingbufferfull
performance.timing
timing 是個(gè)啥玩意?
接著打印一下看看

大家也可以配合這張圖來看看,會(huì)更加深入的理解
performance .timing 對(duì)象包含延遲相關(guān)的性能信息。
因?yàn)闁|西太多,我們分離一些重要的信息出來講解
let?t?=?performance.timing;
頁面加載完成所耗時(shí)間?=?t.loadEventEnd?-?t.navigationStart;
解析?DOM樹?時(shí)間?=?t.domComplete?-?t.responseEnd;
資源加載完成時(shí)間?=?t.responseEnd?-?t.requestStart
TCP建立連接完成時(shí)間?=?t.connectEnd?-?t.connectStart
作用:可以監(jiān)聽這些數(shù)值,判斷網(wǎng)頁加載性能
雖然現(xiàn)在好像要廢棄了,但是現(xiàn)在還是可以用的
performance.navigation
還是來打印一下

第一個(gè)是 redirectCount 是重定向次數(shù)
第二個(gè)是 type 判斷是頁面是從哪里加載的
type
//0:網(wǎng)頁通過點(diǎn)擊鏈接、地址欄輸入、表單提交、腳本操作等方式加載
//1:網(wǎng)頁通過“重新加載”按鈕或者location.reload()方法加載
//2:網(wǎng)頁通過“前進(jìn)”或“后退”按鈕加載
//255:其他來源的加載
作用:可以用作統(tǒng)計(jì)網(wǎng)頁訪問方式及來源,以及是否重定向
performance.resourcetimingbufferfull
屬性是一個(gè)在resourcetimingbufferfull事件觸發(fā)時(shí)會(huì)被調(diào)用的 event handler 。它的值是一個(gè)手動(dòng)設(shè)置的回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)會(huì)在瀏覽器的資源時(shí)間性能緩沖區(qū)滿時(shí)執(zhí)行。
官方例子:
function?buffer_full(event)?{
??console.log("WARNING:?Resource?Timing?Buffer?is?FULL!");
??performance.setResourceTimingBufferSize(200);
}
function?init()?{
??//?Set?a?callback?if?the?resource?buffer?becomes?filled
??performance.onresourcetimingbufferfull?=?buffer_full;
}
"init()">
performance 方法
方法也是很多的,大家可以看看

我們也挑幾個(gè)出來遛一遛
performance.now()
返回當(dāng)前到頁面打開時(shí)刻的耗時(shí),精確到千分之一毫秒
performance.now()

作用:監(jiān)控頁面資源請(qǐng)求耗時(shí)
performance.getEntries()
對(duì)網(wǎng)頁發(fā)起的所有HTTP請(qǐng)求耗時(shí)信息統(tǒng)計(jì)后,以數(shù)組方式返回
performance.getEntries()

作用:監(jiān)控請(qǐng)求資源請(qǐng)求耗時(shí)
performance.mark()
建立測(cè)速標(biāo)記
performance.mark("mySetTimeout-start");
performance.measure()
用于計(jì)算標(biāo)記之間的時(shí)間戳
performance.measure(
?"mySetTimeout",
?"mySetTimeout-start",
?"mySetTimeout-end"
);
performance.clearMarks()
清除測(cè)速標(biāo)記
performance.clearMarks();
小demo
引用官網(wǎng)例子
//?以一個(gè)標(biāo)記開始。
performance.mark("mySetTimeout-start");
//?等待一些時(shí)間。
setTimeout(function()?{
??//?標(biāo)記時(shí)間的結(jié)束。
??performance.mark("mySetTimeout-end");
??//?測(cè)量?jī)蓚€(gè)不同的標(biāo)記。
??performance.measure(
????"mySetTimeout",
????"mySetTimeout-start",
????"mySetTimeout-end"
??);
??//?獲取所有的測(cè)量輸出。
??//?在這個(gè)例子中只有一個(gè)。
??var?measures?=?performance.getEntriesByName("mySetTimeout");
??var?measure?=?measures[0];
??console.log("setTimeout?milliseconds:",?measure.duration)
??//?清除存儲(chǔ)的標(biāo)記
??performance.clearMarks();
??performance.clearMeasures();
},?1000);
輸出
作用:可以計(jì)算某段代碼執(zhí)行速度
總結(jié)一下
我們?cè)谝陨系膶?duì) performance 的簡(jiǎn)單了解之后我們可以選擇自己需要監(jiān)控的數(shù)據(jù),如xxx資源加載太慢或是頁面加載速度進(jìn)行上報(bào),并記錄 log 上報(bào),進(jìn)行進(jìn)行日數(shù)據(jù)歸檔。下一篇將會(huì)講,如何監(jiān)聽網(wǎng)站資源異常。
實(shí)戰(zhàn)一波
我們將前面講到的所需的可以寫成一個(gè)監(jiān)控函數(shù)返回一個(gè)對(duì)象,然后執(zhí)行上報(bào)[1]
function?getPerformanceTiming()?{
????var?performance?=?window.performance;
????var?t?=?performance.timing;
????var?gather?=?{};
????//【重要】頁面加載完成的時(shí)間
????//【原因】這幾乎代表了用戶等待頁面可用的時(shí)間
????gather.loadPage?=?t.loadEventEnd?-?t.navigationStart;
????//【重要】解析?DOM?樹結(jié)構(gòu)的時(shí)間
????//【原因】反省下你的 DOM 樹嵌套是不是太多了!
????gather.domReady?=?t.domComplete?-?t.responseEnd;
????//【重要】重定向的時(shí)間
????//【原因】拒絕重定向!比如,http://example.com/?就不該寫成 http://example.com
????gather.redirect?=?t.redirectEnd?-?t.redirectStart;
????//【重要】DNS?查詢時(shí)間
????//【原因】DNS 預(yù)加載做了么?頁面內(nèi)是不是使用了太多不同的域名導(dǎo)致域名查詢的時(shí)間太長(zhǎng)?
????//?可使用 HTML5 Prefetch 預(yù)查詢 DNS ,見:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)????????????
????gather.lookupDomain?=?t.domainLookupEnd?-?t.domainLookupStart;
????//【重要】讀取頁面第一個(gè)字節(jié)的時(shí)間
????//【原因】這可以理解為用戶拿到你的資源占用的時(shí)間,加異地機(jī)房了么,加CDN 處理了么?加帶寬了么?加 CPU 運(yùn)算速度了么?
????//?TTFB?即?Time?To?First?Byte?的意思
????//?維基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
????gather.ttfb?=?t.responseStart?-?t.navigationStart;
????//【重要】?jī)?nèi)容加載完成的時(shí)間
????//【原因】頁面內(nèi)容經(jīng)過 gzip 壓縮了么,靜態(tài)資源 css/js 等壓縮了么?
????gather.request?=?t.responseEnd?-?t.requestStart;
????//【重要】執(zhí)行?onload?回調(diào)函數(shù)的時(shí)間
????//【原因】是否太多不必要的操作都放到 onload 回調(diào)函數(shù)里執(zhí)行了,考慮過延遲加載、按需加載的策略么?
????gather.loadEvent?=?t.loadEventEnd?-?t.loadEventStart;
????//?DNS?緩存時(shí)間
????gather.appcache?=?t.domainLookupStart?-?t.fetchStart;
????//?卸載頁面的時(shí)間
????gather.unloadEvent?=?t.unloadEventEnd?-?t.unloadEventStart;
????//?TCP?建立連接完成握手的時(shí)間
????gather.connect?=?t.connectEnd?-?t.connectStart;
????//?請(qǐng)求資源集合
????gather.requestResources?=?performance.getEntries()
????return?gather;
}

注解地址
[0] https://developer.mozilla.org/zh-cn/docs/web/api/performance
[1] https://blog.csdn.net/p312011150/article/details/93748456
最后
如有錯(cuò)誤,望各位不吝賜教。?
