前端專案埋點
一、前端監控是監控什麼?
一是監控使用者的行為,比如說頁面的入口來源、點選量、瀏覽量、頁面停留時長等。通過對使用者的行為資料進行分析,可以對我們的產品進行鍼對性的優化。比如說使用者在哪個頁面停留時間較長,我們便可以在這個頁面進行我們的廣告投放等;
二是監控頁面的效能,比如說頁面的白屏時長,首屏時長、介面請求快慢等。由於每個使用者的手機型號、網路情況等的不同,我們開發時是沒法明確知道頁面的效能如何的,所以需要統計這些資料,對我們的頁面進行相應的優化。頁面載入時長越慢可能流失的使用者就越多,沒有人願意去長時間等待一個卡頓的頁面。
三是監控頁面的異常,比如說弱網情況下某些檔案載入失敗、某些特定情況下才會出現的業務bug、頁面的相容bug、記憶體洩漏等,這些在測試階段可能沒辦法都檢測出來,所以需要對我們頁面的錯誤進行監控,這點是很重要的。
二、怎麼進行前端監控?
對我們的頁面進行監控,那麼我們就需要在我們的頁面裡進行埋點。什麼是埋點呢?
埋點,它的學名是事件追蹤(
Event Tracking
),主要是針對特定使用者行為或業務過程進行捕獲、處理和傳送的相關技術及實施過程。埋點是資料領域的一個專業術語,也是網際網路領域的一個俗稱。埋點是產品資料分析的基礎,一般用於推薦系統的反饋、使用者行為的監控和分析、新功能或者運營活動效果的統計分析等。
簡言之,就是需要在我們的頁面里加上特定的程式碼進行資料的收集,然後提交給後臺去進行分析。
那麼埋點有哪些方案呢?
三、埋點方案
手動埋點
手動埋點也叫程式碼埋點,也就是在我們的程式碼里加上特定的程式碼上傳資料給到後端或者說呼叫相應SDK的函式,常見的網站分析工具有很多,國內一般常用的有神策等,國外常用的有Google Analytics
埋點資料傳送可以通過介面上報,也可以通過img/iframe/script
上報。一般採用img
標籤的src
屬性進行傳送,如下:
let baseURL = 'https://www......' let queryStr = Object.entries(query).map(([key, value]) => `${key}=${value}`).join('&') let img = new Image(); img.src = `${baseURL}?${queryStr}`
採用img
的src
屬性發送的原因有下:
- 沒有跨域的限制,像srcipt標籤、img標籤都可以直接傳送跨域的GET請求,不用做特殊處理。
- 相容性好,不需要插入DOM,影響頁面效能。
後端一般會返回一張1px * 1px大小的GIF圖片。同樣大小,不同格式的圖片中GIF的大小是最小的。
視覺化埋點
視覺化埋點即以業務程式碼為輸入,通過視覺化系統配置埋點,最後以耦合的形式輸出業務程式碼和埋點程式碼,但是視覺化系統的埋點控制元件有限,並不能充分滿足埋點需求。
視覺化埋點的流程通常為:
輸入頁面的url => 頁面載入完成後 => 配置視覺化的工具 => 點選建立事件(click) => 進入元素選擇模式 => 用滑鼠點選頁面上的某個元素(例如button、a這些element)=> 就可以在彈出的對話方塊裡面 => 設定這個事件的名稱(比如叫TEST),選上報資料屬性(properties)=> 儲存配置 => 使用者訪問點選按鈕 => 資料上報
無埋點
無埋點則是前端自動採集全部事件,上報埋點資料,由後端來過濾和計算出有用的資料。優點是前端只要一次載入埋點指令碼,不會出現漏埋、錯埋等情況。缺點是流量和採集的資料過於龐大,伺服器效能壓力大。
四、錯誤監控
頁面的使用者行為監控及頁面效能監控可能不是必須的,但是錯誤監控是所有的頁面必須的。那麼怎麼對頁面進行錯誤監控呢?
一般資源載入錯誤和js執行錯誤用window.onerror
來進行捕獲處理:
window.onerror = async function(message, source, lineno, colno, error) {
// 同源策略下,不同url上報是有問題的
if (message !== 'Script error.' && !source) {
return true
}
const data = {
occr_time: dayjs(Date.now()).format(`YYYY-MM-DDTHH:mm:ss.SSS`),
platform: 'H5',
type: 'H5Error',
name: navigator.userAgent,
url: location.href,
code: error.code,
desc: message,
extend_msg: `source:${source}:${lineno}:${colno}`
... // 需要上傳的資訊
}
// 然後通過圖片或者介面上傳給到後臺
...
}
當Promise
被reject
且沒有reject
處理器的時候,會觸發unhandledrejection
事件:
window.addEventListener(
"unhandledrejection",
function(){
const data = {
occr_time: dayjs(Date.now()).format(`YYYY-MM-DDTHH:mm:ss.SSS`),
platform: 'H5',
type: 'H5Error',
name: navigator.userAgent,
url: location.href,
code: error.code,
desc: message,
extend_msg: `source:${source}:${lineno}:${colno}`
... // 需要上傳的資訊
}
// 然後通過圖片或者介面上傳給到後臺
...
}
)
由於Vue
會捕獲所有Vue
單檔案元件或者Vue.extend
繼承的程式碼,所以在Vue
裡面出現的錯誤,並不會直接被window.onerror
捕獲,而是會拋給Vue.config.errorHandler
:
Vue.config.errorHandler = async function(error, source, lineno) {
const data = {
occr_time: dayjs(Date.now()).format(`YYYY-MM-DDTHH:mm:ss.SSS`),
platform: 'H5',
type: 'H5Error',
name: navigator.userAgent,
url: location.href,
code: error.code,
desc: message,
extend_msg: `source:${source}:${lineno}:${colno}`
... // 需要上傳的資訊
}
// 然後通過圖片或者介面上傳給到後臺
...
}
五、參考文章
1、騰訊二面:現在要你實現一個埋點監控SDK,你會怎麼設計?
2、為什麼大廠前端監控都在用GIF做埋點?
3、去大廠,你就應該瞭解前端監控和埋點!
4、miracle90/monitor
5、前端埋點總結
6、一篇講透自研的前端錯誤監控