前端日志埋點優化


 

前一段時間查看前端日志監控的時候發現,有很多關鍵業務節點埋點及用戶行為軌跡數據丟失,而且丟失率達到16%這么高,梳理了一下工程里的前端埋點邏輯及方法,發現存在很大漏洞,做了一期優化,使得日志丟失率不足0.1%,使用了瀏覽器提供的發送保障的更簡潔的sendBeacon方法,以下是對sendBeacon方法的一些理解

 

用戶卸載網頁的時候,有時需要向服務器發一些數據。很自然的做法是在unload事件或beforeunload事件的監聽函數里面,使用XMLHttpRequest對象發送數據。但是,這樣做不是很可靠,因為XMLHttpRequest對象是異步發送,很可能在它即將發送的時候,頁面已經卸載了,從而導致發送取消或者發送失敗。 解決方法就是 AJAX 通信改成同步發送,即只有發送完成,頁面才能卸載。但是,很多瀏覽器已經不支持同步的 XMLHttpRequest 對象了(即open()方法的第三個參數為false)

 

window.addEventListener('unload', logData, false);

function logData() {
  var client = new XMLHttpRequest();
  // 第三個參數表示同步發送
  client.open('POST', '/log', false);
  client.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
  client.send(analyticsData);
}

 

上面代碼指定XMLHttpRequest同步發送,很多瀏覽器都已經不支持這種寫法。

而且將XMLHttpRequest同步發送,會延遲頁面的卸載及下一個頁面的載入,性能非常的差

 

同步通信有幾種變通的方法:

1、一種做法是新建一個<img>元素,數據放在src屬性,作為 URL 的查詢字符串,這時瀏覽器會等待圖片加載完成(服務器回應),再進行卸載。

使用new Image有可能遇到aborted,導致無法成功發送

2、另一種做法是創建一個循環,規定執行時間為幾秒鍾,在這幾秒鍾內把數據發出去,然后再卸載頁面。

 

這些做法的共同問題是,由於同步請求的阻塞,卸載的時間被硬生生拖長了,后面頁面的加載被推遲了,用戶體驗不好。

 

navigator.sendBeacon() 方法可用於通過HTTP將少量數據異步傳輸到Web服務器。

 

navigator.sendBeacon(url, data);

 

為了解決這個問題,瀏覽器來提供發送保障的更簡潔的sendBeacon方法。sendBeacon是異步的,不會影響當前頁到下一個頁面的跳轉速度,且不受同域限制。這個方法還是異步發出請求,但是請求與當前頁面脫離關聯,作為瀏覽器的任務,因此可以保證會把數據發出去,不拖延卸載流程。

 

window.addEventListener('unload', logData, false);

function logData() {
  navigator.sendBeacon('/log', analyticsData);
}

 

Navigator.sendBeacon方法接受兩個參數,第一個參數是目標服務器的 URL,第二個參數是所要發送的數據(可選),可以是任意類型(字符串、表單對象、二進制對象等等)。

 

sendBeacon 如果成功進入瀏覽器的發送隊列后,會返回true;如果受到隊列總數、數據大小的限制后,會返回false。返回ture后,只是表示進入了發送隊列,瀏覽器會盡力保證發送成功,但是否成功了,不會再有任何返回值。目前暫無具體的數據長度限制標准。

 

navigator.sendBeacon(url, data)

 

// HTML 代碼如下
// <body "analytics('start')" οnunlοad="analytics('end')">

function analytics(state) {
  if (!navigator.sendBeacon) return;

  var URL = 'http://example.com/analytics';
  var data = 'state=' + state + '&location=' + window.location;
  navigator.sendBeacon(URL, data);
}

 

 sendBeacon() 方法存在的意義:

使用 sendBeacon() 方法會使用戶代理在有機會時異步地向服務器發送數據,同時不會延遲頁面的卸載或影響下一導航的載入性能。這就解決了提交分析數據時的所有的問題:數據可靠,傳輸異步並且不會影響下一頁面的加載。此外,代碼實際上還要比其他技術簡單許多。

 

最新的瀏覽器兼容情況:

 

 

 

考慮到對目前瀏覽器的支持情況,需要做一下降級支持(如同步模式下的xhr,如果不是同域則要支持CORS):

 

navigator.sendBeacon || new Function('var xhr=new XMLHttpRequest();
xhr.open("POST",arguments[0],true);r.send(arguments[1]);');

example:
function SendBeacon(src)
     if (typeof(navigator.sendBeacon) == "function") {
          var b = new Blob([], {type: 'application/x-www-form-urlencoded'});
          return navigator.sendBeacon(src, b);
     }
     return false;
 
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM