記錄--前端性能監控初步實戰

来源:https://www.cnblogs.com/smileZAZ/archive/2023/01/11/17044397.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在當下前後端分離的主流環境下,前端部分的優化變得越來越重要。為了提升前端的性能和用戶體驗,我覺得可能需要從三個維度採集數據進行分析。 前端埋點。通過埋點收集和統計網頁的UV/PV、設備型號、瀏覽器等數據進行分析,比如可以有針對性對使 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

前言

在當下前後端分離的主流環境下,前端部分的優化變得越來越重要。為了提升前端的性能和用戶體驗,我覺得可能需要從三個維度採集數據進行分析。

  1. 前端埋點。通過埋點收集和統計網頁的UV/PV、設備型號、瀏覽器等數據進行分析,比如可以有針對性對使用比較靠前的設備、瀏覽器等做優化和體驗。
  2. 網頁性能收集和監控。 採集一個頁面從請求開始到完成這個過程中的數據指標。比如收集和監控首屏載入時間、dom渲染時長、響應比較慢的介面等。有了這些數據可以很直觀和針對性的對網頁的性能進行優化和升級。
  3. 錯誤收集和監控。收集網頁中的js的報錯、靜態資源載入報錯,保證網頁正常訪問和降低bug率。

1.前端埋點

採集用戶的行為,監控產品在用戶端的使用情況,根據數據可以明確,前端可以針對性的做優化和體驗。

可以簡單的初步建立這樣的數據模型:

{
 ip: ip地址,統計uv
 ua: 瀏覽器的userAgent //方便區分瀏覽器的品牌
 os: 系統名稱
 current_page_all: 當前頁面訪問總次數
 width:瀏覽器寬度,   
 height:瀏覽器高度, //統計瀏覽器的尺寸
 current_enter_time: 進入當前頁面的時間戳
 current_leave_time: 離開當前頁面的時間戳
 project_id: 項目的id,
 url: 當前url,
 user_uni_id: 臨時分配給用戶唯一的id
 ....
 還有其他
}

2.在網頁中植入對應的js代碼

//進入
document.addEventListener('DOMContentLoaded',function(){
   ...
   let args = {
     ua: navigator.userAgent,
     os: navigator.platform,
     width: document.body.clientWidth || document.documentElement.clientWidth,
     height: document.body.clientHeight || document.documentElement.clientHeight,
     project_id: md5('abcd'),
     user_uni_id: '臨時分配給用戶唯一的id',
     url: window.location.href,
     current_enter_time: new Date().getTime()
     ....
   };
   let img = new Image();
   img.onload = function() {
     img = null;
   };
   img.src= `https://localhost:9700/bury.gif?args=${qs(args)}`;
 });

//離開
window.onbeforeunload = function() {
   ...
   let args = {
     ...
     leave_time: new Date().getTime()
     ....
   };
   let img = new Image();
   img.onload = function() {
     img = null;
   };
   img.src= `https://localhost:9700/bury.gif?args=${qs(args)}`;
}
  1. 收集數據並上報
const fs = require('fs');
route.get('/bury.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  let d = new Date();
  let year = d.getFullYear();
  let month = d.getMonth()+1;
  let day = d.getDate()+1;
  fs.writeFile(`../logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ctx.body = {};
});

簡單的設想方案是先把數據收集到文本文件里,然後定時的分析這些文本文件,然後把篩選後的放到資料庫中。

2.網頁性能收集

網頁性能主要是收集是輸入url地址到網頁請求完成資源下載完成這段時間範圍內一些請求、載入等指標。

  • 比如舉幾個簡單的指標:

  • 首屏載入時長

  • HTML 文檔被載入和解析完成

  • 網頁載入完成時間

  • 白屏時間

  • 其他…

  1. 具體實現方案(一):
//index.html
<html>
 <head>
   <script>
     window.startTime = Date.now();
   </script>
 </head>
 <body>
   <script>
     let diff = Date.now()-window.startTime;
     console.log('白屏時長'+diff);
     document.addEventListener('DOMContentLoaded',()=>{
       console.log('HTML 文檔被載入和解析完成時間'+Date.now()-window.startTime); 
     });
     window.onload = function() {
       console.log('網頁載入完成時間'+Date.now()-window.startTime); 
     };
   </script>
   <script src="a.js"></script>
   <script src="b.js"></script>
   ....
 </body>
</html>

使用performance API

Performance是W3C性能小組引入進來的一個新的API,他可以很好的獲取到首屏載入時間、白屏時間、dns查詢時間等,是一個很方便的獲取網頁性能指標的API,而且目前大部分主流瀏覽器是支持的。

https://www.caniuse.com/

1.Performance一些常用用法的總結

let timing = window.performance.timing
//白屏時間
timing.responseStart - timing.navigationStart
//DNS 查詢時長
timing.domainLookupEnd - timing.domainLookupStart
//request請求耗時
timing.responseEnd - timing.responseStart
//HTML 文檔被載入和解析完成耗時
timing.domComplete - timing.domInteractive
//網頁載入完成耗時
timing.loadEventEnd - timing.navigationStart
//重定向耗時
timing.redirectEnd - timing.redirectStart;
//占用的記憶體
window.performance.memory.usedJSHeapSize;

2.此外還有一些高級用法,比如可以收集一些請求和靜態資源的請求時間

let  time = [];
let entryLists = window.performance.getEntries();
for(let i=0;i<entryLists.length;i++) {
  let item = entryLists[i];
  let obj = {};
     let soureTypes = ['script','css','xmlhttprequest','link','img'];
     if(soureTypes.indexOf(item.initiatorType)>=0){
       obj.name = item.name;  
       //請求時間
       obj.reqTime = item.responseEnd - item.responseStart;
       time.push(obj);
     }
}

3.關於Performance的更多用法可以參考:

https://www.jianshu.com/p/1355232d525a
https://blog.csdn.net/hb_zhouyj/article/details/89888646

4.收集數據上報

收集上報數據,使用koa2創建介面performance.gif

const fs = require('fs');
route.get('/performance.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  let d = new Date();
  let year = d.getFullYear();
  let month = d.getMonth()+1;
  let day = d.getDate()+1;
  fs.writeFile(`../performance-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ctx.body = {};
});

3.錯誤收集和監控

錯誤收集主要就是針對js報錯、靜態資源載入等出錯信息進行收集。

  1. 收集js報錯最先想到的可能是try catch。
try {
    console.log(b);
    } catch(e) {
      console.log(e);
      sendErrorReq();
    };

但是使用使用的話,每個頁面收集錯誤都要充斥這try catch,這樣其實是不太好的。

而且catch似乎沒辦法捕獲到非同步的操作。

try {
      setTimeout(()=>{
       console.log(b); 
      })
    } catch(e) {
      console.log(e);
      sendErrorReq();
    };

試了一下沒有執行到catch裡邊的sendErrorReq函數。

使用try catch是一種局部錯誤監聽方式。

  1. 用window.onerror或者是window.addEventListener(‘error’)

window.onerror

/**
      *msg 錯誤信息
      *url 錯誤所在的頁面地址
      *row 錯誤所在的行數
      *col 錯誤所在的列數
      **/
     window.onerror = function(msg,url,row,col) {
       console.log(msg,url,row,col, error);
     };
    b();

使用window.onerror可以檢測到js的報錯,但是沒法監聽靜態資源載入失敗的情況。

<img src="一個不存在的圖片地址" alt="">

window.addEventListener(‘error’)

window.addEventListener(‘error’)能夠監聽到靜態資源載入出錯

window.addEventListener('error',(e)=>{
      let localName = e.srcElement.localName;
      let currentSrc = e.srcElement.currentSrc;
      if(localName=='img') {
        console.log(`圖片${currentSrc}載入失敗了`);
        sendErrorData(currentSrc);
      }
      ...
      // e.preventDefault();
    },true);

必須設為捕獲過程中執行,否則依然無法監聽。

3. promise錯誤的收集

new Promise((resolve,reject)=>{
       reject('hi');
    }).catch(e=>{
      console.log(e);
      sendErrorData(e)
    });
axios.get(...).catch(e=>{
  console.log(e);
   sendErrorData(e)
})

但是有種情況,如果promise不加catch的話,
沒法通過window.onerror去監聽,但是還是通過監聽unhandledrejection事件去收集的

4.unhandledrejection

window.addEventListener('unhandledrejection', event => {
       console.log('error:'+event.reason); 
        sendErrorData(event.reason);
    });   
    new Promise((resolve,reject)=>{
       reject('hi');
    });

在看下在vue中收集報錯,以vue-cli3創建的項目進行演示

測試了一下window.onerror這種方式 無法監聽錯誤的。

在網上找了下原因

可以看到在vue的源碼里,因為如果沒有定義errorHandler就會走到logError這個方法,所以沒法使用window.onerror進行監聽。

5.errorHandler

在vue的手冊中,推薦監聽vue報錯的可以使用errorHandler這個配置方法。

//main.js
Vue.config.errorHandler = function (err, vm, info) {
  console.log('錯誤是:', err)
  sendErrorData(err);
}
然後隨便故意寫錯
mounted() {
  a();
}
  就能收集到報錯信息了

 當然最後把收集的錯誤上報給伺服器,創建一個介面error.gif。

const fs = require('fs');
route.get('/error.gif',async (ctx)=>{
  let queryStr = ctx.querystring;
  ....
  fs.writeFile(`../error-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
   ctx.status = 200;
   ctx.type = 'image/gif';
   ...
});

本文轉載於:

http://events.jianshu.io/p/a6572eb10e00

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 隨著數據量的增大,傳統關係型資料庫越來越不能滿足對於海量數據存儲的需求。對於分散式關係型資料庫,我們瞭解其底層存儲結構是非常重要的。本文將介紹下分散式關係型資料庫 TiDB 所採用的底層存儲結構 LSM 樹的原理。 ...
  • 在使用MybatisPlus分頁功能時發現:前端查詢第一頁是沒問題的,但是向後查詢的時候數據始終是第一頁的 查詢第一頁的時候發現沒有任何問題 往後查詢,比如查詢第二頁時數據和第一頁一樣 開始以為是代碼問題,把sql單獨拿出來執行發現還是會有重覆數據 上網查詢發現是因為ORDER BY排序的欄位有重覆 ...
  • 分享概要 一、業務場景 二、架構演進 三、架構設計 四、穩定性 五、效率 一、業務場景 在開始講解之前,我先為大家介紹一下B站的業務場景。B站的業務大體上可以分為以下幾類: 1、點播類業務 點播類業務就是大家經常看的視頻以及稿件之類相關的業務,這類數據使用場景的特點有: 數據一致性要求較高 耗時敏感 ...
  • 前言 最近閱讀 Catcher、BugSnag、Rollbar 三個 Flutter 異常監控開源框架,文章鏈接如下: Flutter 異常監控 - 壹 | 從 Zone 說起 Flutter 異常監控 - 貳 | 框架 Catcher 原理分析 Flutter 異常監控 - 叄 | 從 bugsn ...
  • 一、推送成功收不到消息,推送返回:{"message":"success","requestID":"1523868*****2842718","resultcode":0} 排查步驟: 1、網路不穩定,切換穩定網路進行測試; 2、檢查手機是否為EMUI8.0.0系統,如果是早期的EMUI8.0,則 ...
  • Vue.js是一個漸進式的JavaScript框架,它使用了響應式系統來維護應用程式的狀態。響應式系統是Vue.js的核心部分,它使得應用程式能夠自動地更新視圖,當數據發生變化時。 ...
  • Vue04 12.Vue2 腳手架模塊化開發 目前開發模式的問題: 開發效率低 不夠規範 維護和升級,可讀性比較差 12.1基本介紹 官網地址 什麼是Vue Cli腳手架 12.2環境配置,搭建項目 VUE安裝教程+VScode配置 搭建Vue腳手架工程,需要用到NPM(node package m ...
  • Flexbox 是 CSS3 中的一種佈局模式。它允許元素在一個容器中自動排列,可以使用靈活的方式創建複雜的佈局。Flex 佈局有很多優點,例如,它很容易實現響應式設計,並且可以很容易地對齊和排列元素。 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...