前端監控之單頁應用的監控


原文鏈接:https://www.cnblogs.com/yalong/p/15954026.html

背景

公司有大量單頁應用的項目,有的年代久遠,想把一些不用的項目下掉,或者把使用頻率很低的工具進行功能重組,避免占用大量人力去維護眾多項目;
但是不知道這些系統是否有人,以及有多少人在用,以及哪些頁面使用頻率最高;
所以需要統計項目的pv,uv

需求分析

  1. 由於單頁應用的路由跟后端沒有交互,所以后端無法統計到具體的pv,最多統計個uv,所以前端實現比較合適
  2. 由於系統很多,而且vue, react都有,關鍵版本也不一致,所以設計方案要兼容多框架,多版本
  3. 還是由於系統太多,所以要盡量減少對現有代碼的侵入,降低接入成本
  4. 既然要實現統計pv,uv,那么能不能統計多一點的數據,比如首屏加載耗時,異常信息等
  5. 那么就搞一套適合當下的前端監控吧

監控系統數據采集功能拆解

前端監控的核心是采集相關數據,然后才上報,這里只說數據的采集

一.采集首屏加載相關數據

首屏加載性能指標如下:

  1. DNS 解析耗時: domainLookupEnd - domainLookupStart
  2. TCP 連接耗時: connectEnd - connectStart
  3. SSL 安全連接耗時: connectEnd - secureConnectionStart
  4. 網絡請求耗時 (TTFB): responseStart - requestStart
  5. 數據傳輸耗時: responseEnd - responseStart
  6. DOM 解析耗時: domInteractive - responseEnd
  7. 資源加載耗時: loadEventStart - domContentLoadedEventEnd
  8. First Byte時間: responseStart - domainLookupStart
  9. 白屏時間: responseEnd - fetchStart
  10. 首次可交互時間: domInteractive - fetchStart
  11. DOM Ready 時間: domContentLoadEventEnd - fetchStart
  12. 頁面完全加載時間: loadEventStart - fetchStart
  13. http 頭部大小: transferSize - encodedBodySize
  14. 重定向次數:performance.navigation.redirectCount
  15. 重定向耗時: redirectEnd - redirectStart

這么多指標我們選擇三個指標,代碼如下:

let fn = () => {
  let timing = performance.getEntriesByType('navigation')[0]
  let TTI = timing.domInteractive - timing.fetchStart; // 首次可交互時間
  let L = timing.loadEventStart - timing.fetchStart; // 頁面完全加載時間
  let FP = timing.responseEnd - timing.fetchStart; // 白屏時間
  let obj = {
    TTI, L, FP
  }
  console.log(obj)
}
window.addEventListener('load', fn)

其他指標獲取方式相同

二.采集pv uv

問題分析

采集PV UV的核心是監聽瀏覽器路由變化,這就不得不提到vue-router 跟react-router了

在每個項目中是可以專門寫各自的router監聽,但是成本太高,代碼侵入太強,而且不同框架,不同版本寫法還不一樣
所以就不准備使用框架本身的router,用原生js寫一套統一路由監聽多好,這樣就不得不先了解下vue-router 跟react-router的實現原理了

vue-router react-router實現原理

這倆的實現原理網上有很詳細的說明,有需要可自行百度,這里就簡單說下:

以vue-router為例,router有兩種模式: hash模式 和 history模式

hash模式就是改變hash,通過 hashchange 可以監聽hash改變

history模式就是正常的url地址,通過history.replaceState history.pushState 實現

MDN上說 replaceState 和 pushState 會觸發 popState,但是親測,觸發不了,要想監聽這倆方法,只能監聽方法本身,也就是 window.addEventListener('replaceState', historyFn);

同時不管哪種模式下都可以通過 history.go/back/forward 以及瀏覽器的前進后退來改變瀏覽器的url

瀏覽器前進后退操作、history.go/back/forward調用、hashchange的時候觸發popState

總結

要想監聽瀏覽器的url變化,只需監聽如下

   window.addEventListener('hashchange', hashFn);
   window.addEventListener('replaceState', historyFn);
   window.addEventListener('pushState', historyFn);
   window.addEventListener('popstate', historyFn);

這樣就囊括了 hash變化,replaceState,pushState, 瀏覽器前進后退,history.go/back/forward;

但是hash改變的時候,會同時觸發 hashChange 和 popState,
可以通過一個公共變量,hashFn、historyFn 每次執行都給這個變量temp賦值,在觸發數據上報的時候,判斷下,如果temp變量的值 跟現在的url地址是一樣的,就代表已經上報了該url的數據了,阻止當前上報行為即可

代碼如下:

let tempUrl = ''

let historyFn = (e) => {
  let href = e.currentTarget.location.href
  if (tempUrl === href) { // 已經觸發過了
    return false
  } else { // 沒有觸發過,就賦值
    tempUrl = href
  }
  console.log('history change')
}

let hashFn = (e) => {
  let href = e.newURL
  if (tempUrl === href) {
    return false
  } else {
    tempUrl = href
  }
    console.log('hash change')
}

window.addEventListener('hashchange', hashFn);
window.addEventListener('replaceState', historyFn);
window.addEventListener('pushState', historyFn);
window.addEventListener('popstate', historyFn);

三.采集異常報錯

異常數據捕獲其實還是挺復雜的,因為上線以后,代碼都是編譯壓縮后的代碼,而且vue、react 框架本身也會對異常進行捕獲並進行console.error

調研過sentry,這個工具挺好的,但是接入成本比較高,結合當前狀態,那么就退而求其次,監聽console.error不就行了嗎,不要求看解壓后的詳細代碼,就看個異常輸出就行,對於啥內存泄漏,頁面崩潰,這些就不需要了。

具體代碼如下:

const monitorErrorInitFn = () => {
  /**
   * console.error 打印的錯誤,就是要處理上報的信息
   */
  const oldErrorLog = console.error;

  console.error = null // 這一步是避免重復添加
  console.error = function(str) {
    oldErrorLog(str)
    console.log('看我,我監聽了 error 輸出')
  }
}

monitorErrorInitFn()

這樣做是比較草率的,如果需要詳細的報錯信息可以考慮接入sentry 或者其他成熟的工具

項目整體設計

目前為止,數據搜集已經做到了,那么如何讓開發者方便,快捷的接入使用呢?
步驟如下:

1.首先監控系統有個自己的管理后台,用戶在監控后台填寫要接入的項目名稱,項目線上域名,用戶信息存放的位置,然后系統把這些數據保存在數據庫中並生成唯一id

2.把的數據搜集工具封裝成一個npm包,名字就叫u-spa吧,這個npm包對外暴露一個方法,並把id作為參數穿傳進來

3.u-spa,初始化的時候,通過id向后端發送請求,獲取用戶填寫的信息,包括系統名稱,線上域名,用戶信息存放位置,並把這些數據存放在 localStorage 中

4.觸發數據上報的時候,就可以把需要采集的數據,並結合localStorage 中的網站信息,獲取當前用戶名,並限制在當前域名下,一起上報到后端,over

ps:
1.填寫線上域名的原因是只處理線上的數據采集,本地、測試環境就不用采集和上報了

2.填寫用戶信息存放的位置(可以在 localStorage中,也可以在 cookie中),是為了明確知道當前用戶是誰,如果接入的系統本身沒有存儲用戶信息,那么在npm初始化請求的時候,后端可以生成一個唯一的 userId,並存放在redis中,設限24小時過期時間,以此 userId 作為用戶信息的標識,不過這種情況下,只能統計當天的pu、uv,比如用戶第一天使用了,第二天沒使用,那么第三天生成的 userId 就跟之前的不一樣了,這樣統計n天之內的數據就不太准確了,所以還是建議上報真實的用戶名或者郵箱

u-spa

u-spa 就是咱們封裝的收集數據並上報的工具
代碼地址: https://github.com/YalongYan/u-spa

安裝如下

npm i u-spa -S

使用如下

import uSpa from 'u-spa'

uSpa(id)

就是在入口文件里添加上面兩行代碼就可以了,id就是在監控后台填寫完網站信息,生成的id
現在只是在觸發上報的是,console出了上報信息,真實使用還需要搭配上傳數據接口。

特性

1.采集頁面首次加載的性能指標,並上報
2.監聽url改變,並上報數據,包括首頁也會觸發上報
3.監聽console.error 並上報打印的數據
4.接入方便,只需兩行代碼
5.無技術壁壘,不管是vue 還是 react都可以支持
6.其實u-spa 不只是限制在單頁應用上使用,多頁應用也是可以用的

總結

其實前端監控,需要監控,以及可以監控的數據,還有很多

比如可以統計頁面的訪問時長、記錄頁面點擊區域並生成點擊熱力圖、統計按鈕級別的點擊事件等等

需要從實際需求出發, 滿足業務需求才是第一位

本文只說數據的采集,其實搭配還需要有后端服務,對數據的接受,以及把這些數據通過圖標等形式展示出來,這樣才是一個完整的監控系統

參考地址:

理解瀏覽器歷史記錄

如何做前端異常監控?

友盟的監控工具

hash 跟 history 的區別


免責聲明!

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



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