日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
別再讓你的Web頁面在用戶瀏覽器端裸奔
  • 頁面在用戶那里運行,如果10%的用戶頁面出現(xiàn)問題而自己本地沒有辦法重現(xiàn)?
  • 如何先一步了解到前端出現(xiàn)的問題,而不是等用戶反饋?
  • 能不能像查看服務(wù)端日志一樣來定位前端頁面運行的問題?

前端在業(yè)務(wù)復(fù)雜度越來越高的情況下,本地即使做了充分的測試,依照caniuse做了很多兼容,依然無法讓人放心頁面能否正常運行或者運行得怎么樣。

創(chuàng)新互聯(lián)主營鶴城網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app開發(fā)定制,鶴城h5微信小程序定制開發(fā)搭建,鶴城網(wǎng)站營銷推廣歡迎鶴城等地區(qū)企業(yè)咨詢

當(dāng)一個前端頁面發(fā)布出去了之后,頁面所運行的設(shè)備、瀏覽器、網(wǎng)絡(luò)環(huán)境、用戶操作習(xí)慣等等因素都可能是造成頁面不正常的原因。

所以對前端頁面需要做一定的監(jiān)控,而最可行的前端監(jiān)控方式就是將頁面的日志選擇上報到監(jiān)控日志服務(wù)器中。

前端日志上報可以很簡單

對業(yè)務(wù)邏輯的執(zhí)行收集了日志數(shù)據(jù)之后可以參數(shù)的形式構(gòu)造一個url,再通過一個Image請求發(fā)送到到服務(wù)器就完成了日志的上報。

 
 
 
 
  1. (new Image).src = `/r.png?page=${location.href}¶m1=${param1}...`; 

這樣一行代碼就搞定了日志的上報,然鵝,在生產(chǎn)環(huán)境中,日志上報所延伸的問題要復(fù)雜很多。

日志上報帶來的問題

日志上報最終是為了服務(wù)業(yè)務(wù),監(jiān)控業(yè)務(wù)的運行狀態(tài),一般而言前端運行的場景中開發(fā)者最期望監(jiān)控的不外乎頁面&API請求是否正常響應(yīng)和頁面js邏輯是否正常執(zhí)行。

為了覆蓋這兩個監(jiān)控目標(biāo),需要通過很多類型的日志來覆蓋,還有一些特殊場景下,開發(fā)者還希望能與具體業(yè)務(wù)靈活結(jié)合,實現(xiàn)自定義上報。所以常見的日志類型如下

– 頁面&API請求是否正常響應(yīng)

– API調(diào)用日志 – API調(diào)用成功與否及其耗時

– 頁面性能日志 – 頁面連接耗時、首次渲染時間、資源加載耗時等

– 訪問統(tǒng)計日志 – PV/UV,短時間內(nèi)斷崖式的量變化很容易反應(yīng)問題

– 頁面js邏輯是否正常執(zhí)行

– 頁面穩(wěn)定性日志 – 頁面加載和頁面交互產(chǎn)生的js error信息

– 業(yè)務(wù)相關(guān)日志

– 自定義上報 – 某些業(yè)務(wù)邏輯的結(jié)果、速度、統(tǒng)計值等自定義內(nèi)容

隨著前端業(yè)務(wù)的壯大,日志監(jiān)控上報的量會快速增加,監(jiān)控的邏輯也會越來越復(fù)雜,而在生產(chǎn)環(huán)境中,前端監(jiān)控的最基本原則是日志獲取和上報本身不能拋出異?;蛘哂绊戫撁嫘阅堋?/p>

這么多的日志類型代表了日志獲取的邏輯復(fù)雜,同時各種各樣的瀏覽器和環(huán)境會讓這個問題變得更棘手,例如想用console.warn打印異常信息,但是可能會出現(xiàn)warn函數(shù)調(diào)用報錯;例如捕捉到了error但是error.message全是Script error.…

瀏覽器的兼容性,前端業(yè)務(wù)邏輯依賴,日志上報方式,日志上報效率,用戶操作習(xí)慣,網(wǎng)絡(luò)環(huán)境等因素都可能讓日志上報產(chǎn)生問題甚至影響業(yè)務(wù)。這些因素會給日志上報帶來可靠和性能兩方面的問題

日志上報的可靠性問題

瀏覽器兼容性

在不同端和瀏覽器中,因為兼容性的不同,日志獲取邏輯的和上報方法需要兼容多種方式來進行,例如fetch方法方法是否可用,頁面性能(performance)計算是否可以使用NT2標(biāo)準(zhǔn),這些問題可能會帶來上報邏輯本身報錯污染業(yè)務(wù)日志統(tǒng)計;

上報可靠性

日志采集sdk可能因為網(wǎng)絡(luò)原因無法加載,所以安全的方式是sdk注入的位置合理的靠后,那么頁面打開到sdk初始化這段時間就會產(chǎn)生漏報;

后端為了業(yè)務(wù)分離,通常會獨立設(shè)定一個日志采集服務(wù)器,這種情況下日志上報可能會遇到跨域問題;

用戶的頻繁操作和關(guān)閉頁面會可能造成很多已經(jīng)收集的數(shù)據(jù)漏報。

日志上報的性能問題

在一個復(fù)雜站點中,這些日志數(shù)據(jù)可能會非常多,上報可能會因為瀏覽器并發(fā)數(shù)量的限制阻塞業(yè)務(wù)的網(wǎng)絡(luò)請求,或者影響頁面性能。

更優(yōu)雅的上報姿勢

姿勢一 隔離業(yè)務(wù)

資源隔離

為了避免影響業(yè)務(wù),那么理所當(dāng)然,為了不占用業(yè)務(wù)計算資源,日志上報需要單獨設(shè)定后端服務(wù)。

同時也不能使用與業(yè)務(wù)相同的域名,這跟頁面盡量使用CDN引入資源的原理相似,瀏覽器會對同一個域名有一定的并發(fā)數(shù)限制。

而頁面性能、資源加載、初始化API、PV/UV、初始化js邏輯錯誤等日志都是頁面初始化的時候觸發(fā)上報,這種短時間大量的上報可能會造成網(wǎng)絡(luò)請求延時。例如chrome對同一個域名的最大并發(fā)連接數(shù)為6個,如果日志同時上報了6次以上,就會對同域名的業(yè)務(wù)造成影響;更壞的情況如頁面有一些錯誤、網(wǎng)絡(luò)連接質(zhì)量質(zhì)量不高會讓日志上報阻礙頁面渲染。

因此日志上報可以像使用CDN服務(wù)一樣,使用單獨域名和日志處理服務(wù)。

既然使用了不同的域名,那么跨域問題隨之而來,這需要前后端共同支持。服務(wù)器需要允許外部訪問Access-Control-Allow-Origin:*;前端在進行日志上報的時候要添加避免跨域標(biāo)識,如fetch方式:

 
 
 
 
  1. var url = 'https://arms-retcode.aliyuncs.com/r.png';  
  2. fetch(  
  3. `${url}?t=perf&page=qar.alibaba-inc.com&load=1168`,  
  4. {mode:'no-cors'}  

不同域名一個性能缺點是增加首次DNS解析時間,不過可以通過在頁面添加DNS預(yù)解析來避免。

 
 
 
 
  1.  

異常隔離

在資源隔離的基礎(chǔ)上,日志上報的異常處理也需要隔離,日志本身拋出的異常絕對不能和業(yè)務(wù)異常混在一起上報。

進行充分測試的前提下,最簡單粗暴的方式是在整個監(jiān)控sdk外面添加try...catch...,好處是永遠不會出現(xiàn)sdk本身錯誤上報,不過同時也讓開發(fā)者失去了發(fā)現(xiàn)sdk問題的途徑。所以兩者兼得的方式是必要的。

這里提供一個關(guān)鍵模塊埋點的方法,它對整個前端監(jiān)控sdk多個關(guān)鍵點上埋點并且收集的結(jié)果中只標(biāo)記是否成功。話不多說,直接上示例代碼:

 
 
 
 
  1. // 全局標(biāo)記匯總,初始化為36個點位均為1的數(shù)組  
  2. var N = 36;  
  3. var sdkStat = Array.from({length: N}, () => 1);  
  4.   
  5. /** 日志上報功能模塊  
  6. * 對應(yīng)模塊報錯設(shè)置對應(yīng)點位為0,多個點位為0可以幫助找到錯誤發(fā)生鏈路  
  7. */  
  8. try{/* sdk module 0*/}catch(){sdkStat[0] = 0;}  
  9. /* other modules */  
  10. try{/* sdk module 35*/}catch(){sdkStat[35] = 0;}  
  11.   
  12.  
  13. // 日志上報發(fā)送模塊  
  14. var statStr = parseInt(sdkStat.join(''),2).toString(36);  
  15. (new Image).src = `/r.png?¶m1=${param1}&sdkStat=${statStr}...`; 

姿勢二 壓縮請求響應(yīng)報文

壓縮之前重新審視一下(new Image).src的日志發(fā)送方式:

HTTP Request: 前端日志數(shù)據(jù)以多組key=value的字符串形式接在一個Image資源請求的url后面,前端發(fā)送Image請求。

HTTP Responce: 服務(wù)器返回響應(yīng)結(jié)果或者空圖片。

日志數(shù)據(jù)直接放到url中的好處是網(wǎng)絡(luò)傳輸效率高。然而url長度是有限制的,例如IE瀏覽器是2083個字符,同時服務(wù)器也會對url長度進行限制。

類似如下的js error信息就沒有辦法完整上報,

 
 
 
 
  1. $ is not defined@https://www.example.com.cn/catalog/?spm=a2o4k.customer.0.0.37c1379dmQwdrW&q=pediasure&searchclickposition=hint:3:231  
  2. ...  
  3. Tg@https://www.googletagmanager.com/gtm.js?id=GTM-KTVS7D9&l=shadowDatalayerKi7l:64:32  
  4. ... 

不僅僅是js error的錯誤棧深還因為urlencode對特殊字符和漢字的轉(zhuǎn)碼,這兩個因素會使url長度輕松突破限制。

另外業(yè)務(wù)邏輯實際上不關(guān)注而且也應(yīng)關(guān)注日志上報的響應(yīng)結(jié)果,所以這個請求的結(jié)果應(yīng)該盡可能省去。

針對報文壓縮有以下方式:

HTTP/2頭部壓縮

http請求中,每次請求都會傳輸一系列的請求頭來描述請求的資源及其特性,然而實際上每次請求都有很多相同的值,如Host:,user-agent:,Accept等。這些數(shù)據(jù)能夠占用到300-800byte的傳輸量,如果攜帶大的cookie,請求頭甚至可以占用1kb的空間,而實際真正需要上報的日志數(shù)據(jù)僅僅只有10~50byte的大小。在HTTP 1.x中,每次日志上報請求頭都攜帶了大量的重復(fù)數(shù)據(jù)導(dǎo)致性能浪費。

HTTP/2頭部壓縮采用Huffman Code壓縮請求頭,并用動態(tài)表更新每次請求不同的數(shù)據(jù)來把每次請求的頭部壓縮到很小。

HTTP/1.1效果

HTTP/2.0效果

頭部壓縮后每條日志請求的size都大大減小,響應(yīng)的速度也有提升。

壓縮日志的長度

最需要壓縮即js error的錯誤棧,錯誤棧當(dāng)中占位最多是錯誤定位的文件地址,而很多錯誤棧有很多相同的文件,壓縮空間就來源于stack中js文件的url重復(fù)。

一個典型的jserror stack經(jīng)常會出現(xiàn)這種形式如下:

 
 
 
 
  1. obj0.fn0 at (http://loooooooooonnnnnnnnnnng/loooooong/long.js 123:1)  
  2. obj1.fn1 at (http://loooooooooonnnnnnnnnnng/loooooong/long.js 234:1)  
  3. obj2.fn2 at (http://loooooooooonnnnnnnnnnng/laaaaaang/lang.js 345:1)  
  4. ... 

可考慮把文件url抽取出來單獨作為一個字典,那么上報內(nèi)容可縮減為

 
 
 
 
  1. files={'f1':'http://loooooooooonnnnnnnnnnng/loooooong/long.js','f2':'...'}  
  2. obj0.fn0 at (f1 123:1)  
  3. obj1.fn1 at (f1 234:1)  
  4. obj2.fn2 at (f2 345:1)  
  5. ... 

即可大大縮減日志長度。

省去響應(yīng)體

日志上報本身只關(guān)注日志有沒有上報,而對上報請求的返回內(nèi)容并不關(guān)注,甚至完全可以不需要返回內(nèi)容。所以使用HTTP HEAD的方式上報,并且返回的響應(yīng)體為空,避免響應(yīng)體傳輸資源損耗。

這時候只需要設(shè)置一個nginx服務(wù)器來記錄日志內(nèi)容并返回200狀態(tài)碼即可。

 
 
 
 
  1. fetch(`${url}?t=perf&page=lazada-home&load=1168`,  
  2. {mode:'no-cors',method:'HEAD'}  

姿勢三 合并上報

既然一個頁面上報的次數(shù)那么多,一個更容易想到的idea應(yīng)該是把日志合并上報來減小請求數(shù)量。

HTTP/2多路復(fù)用

用戶瀏覽器和日志服務(wù)器之間產(chǎn)生多次HTTP請求,而在HTTP/1.1 Keep-Alive下,日志上報會以串行的方式傳輸,會讓后面的日志上報延時。通過HTTP/2的多路復(fù)用來合并上報,節(jié)省網(wǎng)絡(luò)連接的開銷。

HTTP POST合并

POST請求因為request body可以有更大施展空間,在HTTP POST中只要一次包含多條日志的內(nèi)容,那么相對于一條日志一次HTTP HEAD請求的方式會更加經(jīng)濟。

在HTTP POST的基礎(chǔ)上,可以順便解決用戶關(guān)掉或者切換頁面造成的漏報問題。

以前常見的解決方式是監(jiān)聽頁面的unload或者beforeunload事件,并以通過同步的XMLHttpRequest請求或者構(gòu)造一個特定src的標(biāo)簽來延遲上報。

 
 
 
 
  1. window.addEventListener("unload", uploadLog, false);  
  2. function uploadLog() {  
  3. var xhr = new XMLHttpRequest();  
  4. xhr.open("POST", "/r.png", false); // false表示同步  
  5. xhr.send(logData);  

這種上報的缺點是會給下一個頁面的性能造成影響。更優(yōu)雅的方式是使用navigator.sendBeacon(),它能夠異步地發(fā)送日志數(shù)據(jù)。

 
 
 
 
  1. window.addEventListener("unload", uploadLog, false);   
  2.  
  3. function uploadLog() {  
  4. navigator.sendBeacon("/r.png", logData);  

合并前

合并后(navigator.sendBeacon)

理想情況下,合并n個日志上報耗費的總時間能達到原來的1/n

小結(jié)

前端業(yè)務(wù)場景和瀏覽器的兼容性千差萬別,所以日志上報要兼容多種方式;頁面生命周期、業(yè)務(wù)邏輯影響了日志是否可獲取和是否漏報,所以對應(yīng)的日志類型和上報時機要嚴(yán)格把握;前端業(yè)務(wù)邏輯快速迭代且場景多樣,所以日志上報要做到與業(yè)務(wù)解耦合同時可以自定義上報…

這些大大小小的坑促使我們把前端日志監(jiān)控沉淀為一個獨立且系統(tǒng)性的工程來做,在打磨這個工程的過程中我們同樣還在探索是否有更加高效、穩(wěn)定的日志上報方式。


當(dāng)前名稱:別再讓你的Web頁面在用戶瀏覽器端裸奔
本文網(wǎng)址:http://www.5511xx.com/article/ccodsdh.html