監控平臺前端SDK開發實踐

做者簡介:楊婷,美團點評點餐終端團隊成員。javascript

監控平臺

監控的重要性和必要性沒必要多說,這是提升故障處理能力和保障服務質量所必須的一環。
那麼監控究竟要作什麼呢?簡而言之:及時上報錯誤,收集有效信息,提供故障排查依據。前端

  • 及時上報錯誤:相信每一個程序員都有這樣的經驗,發生線上問題後,經由運營或者產品反饋到開發人員,其中流轉過程多是幾分鐘甚至幾十分鐘,這段時間可能直接致使公司的經濟損失。若是有一個監控系統,在線上出現問題時,監控系統可以第一時間報警,而且通知到開發人員,那開發人員就能夠第一時間修復上線,直接可使公司損失最小化。
  • 收集有效信息:特別是移動時代,定位一個問題時,須要不少用戶信息(如用戶手機版本,網絡狀況,操做流程等)。若是沒有監控數據,每每只能靠猜,又或是來回找產品運營甚至出現問題的用戶去溝通定位,其中不可避免的會花費大量的時間。可是若是監控系統裏記錄了設備信息,錯誤發生時的場景信息,以及用戶的操做流等程,咱們就能夠直接根據這些信息進行問題定位,在最短期內完成故障修復,減少問題的影響面。
  • 提供故障排查依據:監控前端SDK所上報的錯誤信息和其餘的記錄信息,其最終目的都是做爲咱們排查故障的依據,爲咱們保障服務提供堅實的依靠。

監控分類

因此咱們監控平臺須要包括記錄型監控和捕捉型監控:java

  • 記錄型監控
    • 頁面訪問記錄:用戶訪問了哪些頁面
    • 資源加載記錄:頁面中加載了哪些資源
    • 用戶行爲記錄:用戶在頁面上作了哪些操做,目前咱們只記錄用戶的點擊行爲
    • 接口調用相關記錄:頁面調用了哪些接口
  • 捕捉型監控
    • DNS劫持:頁面是否被劫持
    • 資源加載錯誤:哪些資源加載失敗了,爲了捕獲跨域js的錯誤,須要在相應資源標籤上添加crossorigin屬性。
    • 頁面錯誤:頁面渲染過程當中出現的錯誤
    • 內部邏輯錯誤:用戶特定操做出現的錯誤,經過用戶行爲定位
    • 接口錯誤:調用接口失敗

場景還原法

場景還原是監控面板提供的一個很是有用的功能,它將支撐系統處理過的全部記錄和錯誤按照時間順序展現。經過場景還原的列表,咱們能夠還原出指定用戶在瀏覽頁面過程當中發生的全部事情及其前後順序,從而判斷問題發生的時機和環境。node

假設如下場景:webpack

PM:BD反饋用戶在購物車刷不出來啦!
RD:什麼?我試試!我這裏能夠看到的呀
PM:商戶反饋,店裏有的用戶能夠有的用戶不行
RD:別急,告訴我shopId和打不開的用戶的帳號,我去監控平臺上看一下
PM:xxx
RD在監控面板上使用場景還原功能,調出了該用戶的全部信息記錄。發現該用戶是從菜品詳情頁進入的購物車,而再查看正常的用戶都不是從這個入口進的,定位到是菜品詳情頁跳購物車的部分有問題,並馬上進行了修復程序員

在以上這種用戶可能有多種操做的場景中,場景還原法能夠針對特定用戶,還原其完整的操做路徑和頁面上發生的全部事情,幫助復現問題。
另外,一些非必現的問題,經常是因爲不一樣機型或環境引發的,也能夠在場景還原中復現問題的發生環境予以判斷。
web


監控平臺整體分爲三部分:

  • 監控前端SDK:收集用戶端錯誤和相關信息,並進行上報
  • 監控web層支撐系統:處理上報的監控信息
  • 監控面板:提供實時查看上報信息的面板,方便監控數據的便捷使用

本文主要介紹監控前端SDK的實踐經驗,仍有許多須要改進的地方,歡迎你們拍磚,幫助咱們改進。ajax

總體設計


如圖所示,整個監控平臺分爲前端SDK、web層支撐系統和監控面板三大部分,前端SDK運行在前端頁面中,收集監控數據上報到支撐系統裏,做爲監控面板上查詢的數據源。

就前端SDK來講,能夠分爲數據模塊、數據處理模塊、上報模塊三大部分,其中數據模塊包括各具體監控數據模塊和環境數據模塊:api

  • 數據模塊
    • 各監控模塊:獲取須要上報的具體內容信息(EventData或ErrorData)
      • DNS劫持檢測
      • 資源完整性檢查
      • 資源加載錯誤
      • API監控
      • 全局錯誤
      • 用戶交互
      • 自定義上報
    • 環境模塊:獲取環境數據
  • 數據處理模塊:將環境數據和各內容數據,處理成接口對應的格式,並返回標準格式數據
  • 上報模塊:從環境模塊獲取環境數據,再和內容數據一塊兒根據不一樣監控類型分發到對應的數據處理模塊。獲取標準數據後發送到node層。
    上報模塊先查看本地緩存數據,將本地數據和新產生的數據一塊兒上報,若上報失敗則存入localStorage

詳細設計

SDK裏採用單例模式,包括各監控模塊、環境模塊和上報模塊。
每一個具體監控模塊獲取上報模塊實例進行上報,上報模塊內部保證同時只會有一個上報請求。
事件的監聽都在捕獲階段進行,防止由於事件冒泡被阻止而遺漏信息。跨域

環境模塊

環境模塊收集如下環境信息:項目配置信息、web環境數據、jsbridge環境數據
其餘的一些諸如UA、isp等web層能夠獲取的信息由web層獲取。
該模塊暴露init和getEnv方法

  • init接收用戶配置的環境參數
  • getEnv更新頁面url,再返回當前env對象freeze的一個副本

上報模塊

採起單請求上報的方式,每一個用戶同時只會有一條上報請求,每次將當前記錄到的監控信息列表一塊兒上報,成功後再繼續上報。

上報結束以前的新上報記錄都存在localstorage,收到成功消息後刪除已上報數據,繼續上報,不成功的記錄保留在localstorage。此處需注意對localstorage存儲的上限作好控制。

在當前沒有數據正在上報的狀況下觸發上報,嘗試將當前localstorage的數據和新數據所有上報,若上報記錄過多,則分條發送。所有發送完或上報失敗,本次上報結束。

各具體監控模塊

DNS劫持

HTTPS頁面被劫持後頁面資源沒法獲取,劫持者無利可圖的狀況下會下降劫持的動力。
若仍被劫持,前端資源未到達本地,也沒法完成上報,只能從網絡層去監控。
因爲我司已經全量切了HTTPS,所以該模塊不在本監控系統中。
不過以前本團隊作過對HTTP域下的劫持檢測,其檢測思路爲請求Node層指定域名下的樣本HTML或JS資源,對比返回結果是否符合預期。

資源完整性檢查

資源完整性檢查模塊的任務是記錄頁面加載了哪些資源,並進行上報。
當咱們排查問題時,能夠查看當前頁面已經加載成功了哪些資源及其加載順序,排除由於某些資源沒有加載或者加載順序不當而引發錯誤的狀況。


資源加載完整性檢查的上報時機分四類,每次將開始監聽到觸發上報之間全部記錄到的已加載資源一塊兒上報,減小上報請求數:

  1. onload:window.onload時觸發
  2. onload_timeout: onload超時(5秒)時觸發
  3. async:window.onload後必定延時(5秒)觸發,上報後中止監聽
  4. hash_change:onhashchange開始監聽,必定延時(5秒)觸發上報,上報後中止監聽

內存中維護一個已加載資源的數組,每次上報後刪除已上報的資源記錄。

資源加載錯誤監控

window上error事件代理,過濾window自己的error
根據標籤類型判斷資源類型,src或href爲資源地址
爲了捕獲跨域js的錯誤,須要在相應資源標籤上添加crossorigin屬性。

API錯誤監控

一樣採用XMLHttpRequest加hook方式實現。
open時記錄接口url,send後根據status判斷,接口調用失敗時進行上報。

XMLHttpRequest.prototype.open = function open(method, url, bool) {
    monitor.originXHR.open.apply(this, [method, url, bool]);
    // get something...
    // this.ajaxUrl = url;
}

XMLHttpRequest.prototype.send = function send(_data) {
    const self = this;

    this.addEventListener('readystatechange', () => {
        if (self.readyState === 4) {
            if (self.status !== 200 && self.status !== 304 && this.ajaxUrl !== REPORT_URL) { // filter urls
                // report error info
                // ...
                // monitor.reporter.report(dataTypes.API_ERROR, error);
            }
        }
    }, false);

    monitor.originXHR.send.apply(this, [_data]);
};複製代碼

過濾掉sdk自己的上報地址(防止上報失敗引發循環上報)和一些其餘須要忽略的接口地址。

敲黑板,接口訪問url時多是一個相對路徑,建議補全協議和domain

全局錯誤監控

監聽window上的error事件,過濾事件代理的error。

用戶交互監控

監聽window上捕獲階段的click事件,記錄點擊相關數據。

業務代碼中能夠爲比較關注的元素添加data屬性,每次點擊將會上報被點擊元素的指定屬性、附加信息和domPath幫助定位該元素。

記錄用戶交互信息能夠明確問題發生時,該場景下用戶的具體操做路徑,結合環境數據、資源加載記錄和錯誤數據,整個問題場景就一目瞭然了。

接入方式

sdk的接入方式分爲如下兩種:

  1. 先加載sdk
    • 優勢:能夠記錄頁面加載完成前的狀況,加載的資源,以及發生的錯誤
    • 缺點:影響頁面加載速度,直接拷貝在head中,對業務接入不友好
  2. 後加載sdk
    • 優勢:不影響頁面性能
    • 缺點:只能監控加載成功的頁面,但咱們須要關心頁面加載失敗的場景

爲了知足功能須要,當前監控平臺v1的引入方式是將壓縮後的sdk代碼直接引入到被監控頁面的head中,並由業務代碼初始化配置項目名稱等。該步操做能夠藉助webpack的插件來幫助完成,減輕業務組接入的複雜度。

後續改進方向考慮採用:核心基礎庫+loaders/plugins 的方式,將必須先加載的sdk代碼引入在head中,其他代碼等頁面加載完成後再異步添加。

以上就是咱們終端團隊監控平臺前端SDK部分的實踐分享啦,歡迎你們批評指正,有好的建議也但願能提出來幫助咱們改進。咱們後續將不斷優化,也將繼續與你們保持討論。耐心看到這裏的讀者,表示十二萬分的感謝~~

相關文章
相關標籤/搜索