小程序錯誤異常監控方案
發表時(shí)間:2021-1-11
發布人(rén):融晨科技
浏覽次數:99
本文主要(yào / yāo)介紹了(le/liǎo)微信小程前端錯誤異常監控系統,用于(yú)捕獲收集線上(shàng)小程序項目代碼在(zài)使用生命周期中出(chū)現的(de)異常情況。
背景
每一個(gè)前端項目上(shàng)線後都會在(zài)出(chū)現線上(shàng)問題,不(bù)論是(shì)PC項目還是(shì)移動端項目,在(zài)後端服務中,可以(yǐ)通過錯誤或業務日志來(lái)記錄錯誤的(de)情況,這(zhè)些數據可以(yǐ)幫助開發者快速定位系統的(de)狀态,追查bug,了(le/liǎo)解錯誤異常的(de)基本情況。但是(shì)在(zài)前端開發的(de)領域内,成型的(de)日志監控系統比較少見,尤其是(shì)在(zài)小程序端。
關于(yú)前端異常監控,網上(shàng)有很多開源的(de)項目,比如騰訊的(de)badjs,淘寶的(de)JSTracker,阿裏巴巴的(de)fdSafe系統,支付寶的(de)sai.js,國(guó)外的(de)sentry異常捕獲平台,到(dào)目前爲(wéi / wèi)止,已經有很多的(de)解決方案在(zài)很多年前被提出(chū)并且實現了(le/liǎo),但是(shì)他(tā)們的(de)方案并不(bù)是(shì)完全适用于(yú)每一個(gè)項目的(de)開發者,比如國(guó)内的(de)fundebug,關注了(le/liǎo)所有的(de)Error收集場景,但是(shì)他(tā)們解決的(de)問題其實都是(shì)接下來(lái)要(yào / yāo)講到(dào)的(de)一些通用問題,如果針對到(dào)具體項目,還是(shì)看業務方如何選擇。
每當小程序出(chū)現卡頓的(de)情況,用戶都會下意識的(de)考慮是(shì)自身手機的(de)問題,但是(shì)在(zài)使用别的(de)小程序卻不(bù)存在(zài)這(zhè)種問題,就(jiù)會導緻用戶退出(chū)不(bù)再使用。因爲(wéi / wèi)小程序的(de)特點,獲取用戶的(de)成本很低,同樣用戶放棄使用的(de)成本也(yě)很低,那麽既然用戶體驗很差,所以(yǐ)用戶很大(dà)概率會直接退出(chū),并且從此不(bù)再使用。
如上(shàng)圖所示,微信在(zài)小程序後台也(yě)有做錯誤監控,但是(shì)監控手段沒法将錯誤原因細分。比如以(yǐ)下幾點:
? 網絡請求錯誤統計,但無法快速定位到(dào)服務端;
? 有JS錯誤統 計,但無法快速定位錯誤堆棧;
? 無頁面維度監控,無法知道(dào)用戶打開頁面的(de)體驗;
? 無地(dì / de)域運營商監控,無法知道(dào)不(bù)同地(dì / de)域運營商下的(de)小程序性能;
? 頁面退出(chū)率高,無法知道(dào)是(shì)否是(shì)性能導緻的(de);
? 關于(yú)promise或async/await異步方法中報錯信息的(de)沒有監控。
設計方案
1. 架構設計
在(zài)參考了(le/liǎo)市面上(shàng)諸多的(de)監控系統,并結合原始前端監控的(de)結構,總結一下:
1)SDK編寫,主要(yào / yāo)是(shì)暴力埋點,錯誤攔截,代理監控,上(shàng)報策略,API設計,日志接口以(yǐ)及數據存儲;
2)上(shàng)報的(de)日志實現實時(shí)查詢;
3)監控日志可視化管理後台的(de)開發。
以(yǐ)上(shàng)3點是(shì)基本,後期可以(yǐ)再加入場景重現,多平台管理,郵件報警等成熟的(de)功能
2. 流程設計
用戶在(zài)使用小程序的(de)整體生命周期内,sdk扮演一個(gè)類似行車記錄儀的(de)角色,用戶在(zài)點擊使用産品時(shí)觸發到(dào)項目内部的(de)錯誤,SDK接收到(dào)這(zhè)個(gè)信息,然後将這(zhè)個(gè)錯誤觸發的(de)時(shí)間點以(yǐ)及作爲(wéi / wèi)開發正想要(yào / yāo)收集的(de)錯誤信息在(zài)本地(dì / de)先做一個(gè)簡單的(de)整理, 作爲(wéi / wèi)主體上(shàng)報至後台服務端,服務端接收數據并根據預先定好的(de)規則保存進入數據庫當我們打開後台管理系統的(de)時(shí)候會将這(zhè)些數據以(yǐ)項目分組的(de)形式,再做錯誤分組,做一個(gè)可視化的(de)展示。當某些錯誤到(dào)達上(shàng)限阈值的(de)時(shí)候會向項目的(de)參與人(rén)發送報警郵件。
3. SDK設計
如何定位小程序前端線上(shàng)問題,是(shì)一個(gè)比較複雜的(de)問題,因爲(wéi / wèi)它可能在(zài)用戶使用過程中的(de)一系列操作之(zhī)後發生,錯誤的(de)原因有很多,可能源于(yú)不(bù)同機型,不(bù)同環境版本,網絡接口,請求環境或者複雜的(de)操作等。
尤其是(shì)這(zhè)樣四個(gè)W的(de)問題:誰在(zài)什麽環境下做了(le/liǎo)什麽導緻什麽錯誤?
接下來(lái),我先從這(zhè)個(gè)角度開始設計小程序監控系統。
WHO did WHAT and make WHICHerror in WHICH environment?
(1)第一個(gè)W——WHO
基礎用戶信息,當監聽到(dào)用戶在(zài)引入sdk時(shí)有配置開關,那就(jiù)可以(yǐ)在(zài)小程序項目啓動的(de)到(dào)時(shí)候執行微信原生方法,獲取用戶信息。其中網絡狀态中的(de)IP是(shì)需要(yào / yāo)在(zài)上(shàng)報錯誤的(de)時(shí)候服務端獲取,此外openid和(hé / huò)unionid因爲(wéi / wèi)不(bù)同的(de)小程序在(zài)獲取到(dào)之(zhī)後一般保存在(zài)全局globalData或本地(dì / de)storage緩存中。
(2)第二個(gè)W——DO WHAT
小程序在(zài)整個(gè)使用的(de)生命周期裏面出(chū)現的(de) 各種直觀的(de)錯誤情況,我從用戶可視角度分爲(wéi / wèi)五種,對于(yú)開發者和(hé / huò)運營者來(lái)說(shuō),錯誤等級和(hé / huò)優先級都是(shì)一緻的(de)。
正常情況下,一般用戶使用時(shí)出(chū)現這(zhè)些問題的(de)時(shí)候都會首先想到(dào)的(de)是(shì)自身手機出(chū)現問題,可是(shì)如果其他(tā)小程序可以(yǐ)正常使用,或者使用流程沒有問題的(de)話,用戶的(de)流失率就(jiù)會增加。所以(yǐ),當頁面出(chū)現這(zhè)些問題的(de)時(shí)候都可以(yǐ)認定他(tā)發生了(le/liǎo)錯誤。
(3)第三個(gè)W——WHICH ERROR
這(zhè)裏要(yào / yāo)獲取的(de)是(shì)錯誤的(de)分類,三種類型的(de)錯誤:
1)http請求錯誤
a、請求返回的(de)statusCode不(bù)是(shì)200時(shí)
b、request的(de)fail回調函數被觸發時(shí)
當發生以(yǐ)上(shàng)事件時(shí),存儲兩部分日志,一個(gè)是(shì)請求的(de)堆棧信息,一個(gè)是(shì)事件請求的(de)全部信息,包括請求頭部,請求方式,請求參數,請求地(dì / de)址等。
2)js請求錯誤
JavaScript異常監控的(de)方法采用暴力埋點的(de)方式,但是(shì)由于(yú)它會造成污染代碼的(de)後果,所以(yǐ)在(zài)api使用的(de)時(shí)候會提供開關的(de)形式來(lái)謹慎選擇。默認采用劫持函數的(de)形式。
在(zài)默認app.js中監聽onLaunch、onShow、onHide、onError生命周期函數,其中在(zài)onLaunch中執行獲取用戶基礎信息,當監控到(dào)有執行onError是(shì)就(jiù)記錄一次報錯信息。
js的(de)錯誤類型主要(yào / yāo)分爲(wéi / wèi)以(yǐ)下幾種:
3)資源上(shàng)傳下載錯誤
小程序不(bù)能直接分享到(dào)朋友圈,我們一般采用的(de)方法是(shì)将小程序碼繪制成canvas圖片,然後保存到(dào)手機相冊,再以(yǐ)圖片的(de)形式來(lái)分享朋友圈。上(shàng)傳圖片或canvas上(shàng)的(de)元素時(shí),采用wx.uploadFile方法來(lái)上(shàng)傳,然後繪制對應文件的(de)tempFilePaths緩存,這(zhè)時(shí)我們可以(yǐ)監控wx.uploadFile的(de)fail回調函數。當我們要(yào / yāo)把繪制好的(de)圖片保存到(dào)相冊時(shí),使用wx.downloadFile方法,這(zhè)裏也(yě)是(shì)監控這(zhè)個(gè)方法的(de)fail回調函數。
(4)第四個(gè)W——WHICH ENVIRONMENT
此外,爲(wéi / wèi)了(le/liǎo)更好地(dì / de)複現用戶的(de)操作流程,當用戶再點擊頁面按鈕或者打開頁面的(de)時(shí)候,sdk還會收集保存頁面的(de)堆棧信息和(hé / huò)執行方法的(de)堆棧信息,這(zhè)樣在(zài)可視化後台就(jiù)可以(yǐ)直接觀察出(chū)用戶的(de)使用流程。
每一條錯誤信息在(zài)上(shàng)報的(de)時(shí)候都會存儲這(zhè)些類型的(de)數據,當收集到(dào)信息的(de)時(shí)候就(jiù)會在(zài)sdk中對錯誤進行分類,根據捕獲的(de)錯誤關鍵字來(lái)區分錯誤的(de)類型和(hé / huò)等級。在(zài)上(shàng)報的(de)同時(shí)增加每條錯誤信息的(de)标識和(hé / huò)分組。
4. 上(shàng)報方式
異常錯誤上(shàng)報方式采用接口請求的(de)方式,将具體數據收集到(dào)後向服務端發送,無需關注是(shì)否發送成功,但是(shì),考慮到(dào)在(zài)大(dà)型應用中,日志量比較大(dà),我采取抽樣,合并,過濾三個(gè)方法減少日志的(de)輸出(chū)。
再使用api的(de)時(shí)候可以(yǐ)配置當前日志達到(dào)多少條的(de)時(shí)候進行上(shàng)報,默認值爲(wéi / wèi)3條,同時(shí)可以(yǐ)配置上(shàng)報接口是(shì)異步還是(shì)同步,init的(de)時(shí)候配置reportType的(de)方式是(shì)sync(同步)/async(異步),默認爲(wéi / wèi)sync。
在(zài)初始化sdk的(de)時(shí)候可以(yǐ)新增錯誤類型,當發現監控到(dào)的(de)錯誤是(shì)屬于(yú)配置好的(de)信息,那就(jiù)選擇不(bù)上(shàng)報。
上(shàng)報錯誤消息,但是(shì)這(zhè)裏需要(yào / yāo)再做一個(gè)操作,那就(jiù)是(shì)監控的(de)是(shì)非上(shàng)報接口的(de)https請求。如果監控系統的(de)服務出(chū)現什麽問題導緻這(zhè)個(gè)上(shàng)報接口失敗,那就(jiù)說(shuō)明這(zhè)個(gè)借口已經出(chū)錯。如果同步監聽的(de)話,就(jiù)會導緻陷入死循環,不(bù)停地(dì / de)監控不(bù)停的(de)上(shàng)報。所以(yǐ)需要(yào / yāo)将這(zhè)個(gè)接口或者域名排除出(chū)去。
5. 後台可視化系統
當服務端得到(dào)前端上(shàng)報的(de)信息之(zhī)後,經過數據分析和(hé / huò)處理,需要(yào / yāo)前端可視化的(de)展示數據分析後的(de)結果。
這(zhè)個(gè)後台其實是(shì)一般的(de)工具系統,包括用戶管理、權限管理、錯誤聚合以(yǐ)及展示錯誤詳情。具體展示整個(gè)應用的(de)日志和(hé / huò)單個(gè)用戶的(de)單個(gè)錯誤。
1)整個(gè)應用:
· 固定時(shí)間段内的(de)發生的(de)錯誤總數,錯誤占比,可視化曲線走勢圖
· 相同錯誤的(de)分組集合信息
· 每一項分組的(de)錯誤優先級,開發人(rén)員的(de)分配,可操作功能
· 根據sdk版本,錯誤分類篩選
2)單個(gè)用戶
· 用戶基本訪問頁面堆棧信息,執行方法堆棧信息,接口請求堆棧信息
· 每條錯誤的(de)基本信息,錯誤位置,詳情,錯誤時(shí)間點
· 用戶基礎信息,手機版本,使用基本場景
總結
前端的(de)錯誤監控是(shì)一個(gè)任重而(ér)道(dào)遠的(de)任務,它的(de)存在(zài)對任何前端開發都起一個(gè)相當重要(yào / yāo)的(de)作用。我們監控系統是(shì)針對微信小程序的(de)原生前端代碼做異常監控,會逐步針對百度,支付寶,頭條小程序做兼容,做到(dào)一套SDK監控全平台。
因爲(wéi / wèi)小程序的(de)特殊性,它不(bù)同于(yú)傳統的(de)web前端監控,對于(yú)部分能有效的(de)體現錯誤詳情的(de)方式還不(bù)夠友好,我們将通過soursemap等方式來(lái)變相模拟。同時(shí)也(yě)會對promise或async/await等做兼容監控,對上(shàng)報方式作出(chū)更優化的(de)處理。
作者簡介:
趙炳琦 58同城ABG高級前端開發工程師 負責二手車小程序相關開發