打造前端監控系統

子慕大詩人發表於2021-03-08

目錄

  • 前言
  • 需求背景
    • 解決什麼問題
    • 行業通用方案
    • 定製化
  • 系統架構與融合
    • 基本構成
    • 系統關聯融合
    • 高效運維
    • 小結
  • 資料收集與分析
    • 資料收集
    • 資料錄入
    • 資料分析
  • 問題發現與解決
    • 自動化整合測試
    • 資料聚合
    • 資料庫
  • 結語

前言

在上一篇文章《前端監控SDK開發分享》中,對客戶端SDK的實現做了分享。這篇文章將會分成四節(需求背景系統架構與融合資料收集與分析問題發現與解決)分享介紹我們是如何打造前端監控系統的。

一、需求背景

1.1 解決什麼問題

客戶端常常會遇到如下一些問題:

  • 白屏
  • 無響應
  • 卡頓
  • 服務異常
  • bug無法復現
  • 等等

面對這些執行在使用者端的問題,前端常常表示很無奈,解決這些問題之前,我們需要先知道客戶端發生了什麼,於是我們可以想到:

  • 收集錯誤,解決報錯、相容性等問題
  • 收集效能,解決慢查詢、慢載入等問題
  • 收集介面,發現介面錯誤、打通服務端監控
  • 收集多方面輔助資訊,綜合多方面分析

為了實現收集功能,我們需要提供一個前端監控平臺,它能夠收集資料、處理資料、儲存資料、查詢資料。其實就有很多現成的平臺或者開源專案我們可以直接使用。

1.2 行業通用方案

前端技術發展至今,相信大家已經對前端監控的這件事情非常熟悉,或多或少都會在我們的專案中用上它。比如搭建使用開源專案sentry、付費平臺阿里的ARMS、甚至小程式配套的前端監控服務。

(1). sentry
sentry主要提供的功能是收集錯誤。支援大多流行語言的客戶端和服務端,不支援小程式,但是目前有大公司根據sentry的上報資料結構,自己實現了小程式SDK並開源,目前關注度和流行度都偏低。除開錯誤,它的其它型別的前端監控能力相對來說很弱。

(2). 阿里ARMS
ARMS提供的功能與支援的客戶端比較齊全,小程式也支援。只是需要付費。總體來說提供的功能還是比較全面、符合國內的環境。

(3). 小程式自帶監控
微信小程式不斷的在完善內部的監控,各方面的功能也慢慢豐富了起來,但是隻能支援小程式本身。

在使用這些開源或者平臺前端監控服務的時候,始終有一些不足。比如:

  • 系統分散
  • 很難滿足增加一些自定義資料和查詢需求
  • 特性一直不更新、BUG解決週期長
  • 二次開發難度大

1.3 定製化

早期我們使用sentry,隨著公司多方面的發展,已經發現到sentry不能滿足好幾個方面的需求了。

如果完全從0到1來打造一套前端監控系統,成本也是很高的。甚至在早期,都可能沒人願意用,系統是否能立項或者持續發展下去也是一個問題。於是從一些開源專案中去尋找,去找一個方便改造也有一定功能模組的專案。在2019年底,我們找到了zanePerfor,因為它功能比較豐富,使用node+mongo符合我們前端的技術棧,也配套支援了微信小程式。

之後,我們開始基於它的程式碼,進行長期的改造和迭代。慢慢的改造成為一個更適合公司內部環境的一個前端監控系統。下一節,聊聊目前的系統基本構成、企業內部系統之間的關聯融合、以及運維服務如何保駕護航。

二、系統架構與融合

2.1 基本構成

  • 客戶端SDK
    • web
    • 小程式
    • ios
    • andriod
  • 服務端 node+EggJs
  • 資料庫 Redis Mongo+mongooseJs(orm)
  • 管理臺 Vue+ElementUI

為了實現前端監控,第一要素是要收集客戶端資料,為了方便客戶端整合監控系統、我們需要首先開發封裝一個統一的SDK、去幫助我們收集資料。在早期,客戶端方面我們優先支援的是web和微信小程式,隨著系統的迭代現在也支援了native

SDK收集了資料,我們還需要通過服務端介面來接收,在服務端,使用node+EggJsnode適合i/o密集型場景,符合前端技術棧。eggjs簡單易用、文件友好,大部分使用node的前端程式設計師都應該能很快上手。

服務端收集到資料並進行一些處理之後,我們需要儲存到我們的資料庫之中。在資料庫方面,使用mongo做持久化儲存,mongo 文件模型資料庫,資料擴充套件方便,類json結構方便和node配合使用,天生適合日誌系統。使用redis做資料快取,redis簡單易用的高效能key-value資料庫,市場上佔據主流,被大部分人都熟知。

最後,還需要一個管理臺,做資料查詢與管理。管理臺使用Vue+ElementUI,簡單快速。

下圖是目前系統技術關係圖:

客戶端SDK收集資料上報,node服務端獲取到資料後,先存在redis中,node服務會根據消費能力去拉取redis資料處理分析後儲存到mongo之中,最後我們通過管理後臺展示處理好的應用資料。

當初步的實現了我們的前端監控以後,我們還接入了公司內部現有的優質系統,豐富功能、提高了易用性、減少了工作量。

2.2 系統融合與關聯

  • SSO系統
  • 加入內部導航黃頁
  • 本地日誌系統 finder elasticsearch
  • APM系統 skywalking
  • 告警平臺
  • 操作日誌平臺
  • SPA平臺

(1) 接入內部SSO系統

企業內部我們有一套SSO單點登入系統,系統會為每個員工註冊一個賬戶,可以通過賬戶密碼、企業微信掃碼或者微信掃碼等方式登入。統一登入,不僅僅是解決了登入不同系統之間的賬戶密碼和登入方式問題,還更方便系統之間的相互跳轉和介面請求。

(2) 加入內部導航黃頁

在內部的導航頁加入我們的專案,大家使用方便進入。

(3) 本地日誌系統

前端監控系統的node後端服務,也會產生服務的本地日誌。通過儲存日誌到約定目錄,運維服務將會幫我們收集,並且提供了兩個查詢系統:finderelasticsearchfinder按照時間和資料夾結構劃分,它的檢視視角就像直接通過伺服器看本地的日誌一樣,大部分時候我們更習慣用它。 elasticsearch主要適合搜尋的方式查詢。

(4) APM系統 skywalking

前端監控系統的node後端服務,除了系統本地產生的執行日誌,它同樣應該被後端的監控系統所監控。APM應用效能管理,目的是通過各種探針採集資料,收集關鍵指標,同時搭配資料呈現以實現對應用程式效能管理和故障管理的系統化解決方案。我們企業內部統一使用skywalking,我們的大部分服務主要是javaskywalking提供了node探針,使我們的專案也能夠接入。接入之後,我們便可以通過skywalking管理臺查詢到後端node服務的效能以及呼叫情況了。

traceIdAPM工具會在服務端生成traceId,它標示一次呼叫的上下文id,通過此id可以查詢所做事情的足跡鏈。後端服務可以通過前端http請求把這次呼叫的traceId通過響應頭返回給客戶端。前端監控的前端SDK探針便可以收集traceId,通過收集到它,前端監控就可以打通後端監控。在前端監控管理後臺,我們不僅可以看到前端的監控網路日誌,還可以通過traceId查詢到後端鏈路資訊。

(5) 告警平臺

前端監控系統需要實時或定時的推送一些告警郵件等,內部告警平臺提供了告警策略配置、並會拉取前端監控資料。接入告警平臺可以減輕前端監控系統本身的剛需工作量。

(6) 操作日誌平臺

在閘道器層,操作日誌平臺可以攔截我們的管理臺操作請求,以此來記錄使用者的系統操作。幫助我們做敏感操作追溯以及報警等。

(7) SPA平臺

SPA平臺是公司內部自研的靜態資源釋出平臺,可以通過它半自動化管理業務專案,配置注入、靜態資源管理等。前端監控在收集到壓縮程式碼的報錯時,需要通過sourceMap檔案解析轉換為原始碼。大部分前端監控方案,需要手動上傳sourceMap檔案到監控系統,使用SPA平臺後,資源被統一管理,我們可以通過內部配置直接把sourceMap檔案存放在約定的位置,免去業務方手動上傳,提高了易用性。

當我們的系統的功能都已經實現,關聯絡統也成功融合以後,程式要穩定友好的執行線上上,還需要我們的運維服務來保駕護航。

2.3 高效運維

  • 日誌抓取
  • 自動化構建
  • 容器化
  • 負載均衡
  • 健康檢測、安全關閉
  • 等等

健康檢測、安全關閉

前端監控隨時都會收到業務方上報的資料,這個系統在重啟的時候,必須保障服務不間斷,也要保障在關閉的時候,是安全的不會丟失資料。當我們更新了程式碼,重新構建的時候,首先會預先啟動新的容器,當新的容器啟動完成後,逐步關閉替換舊的服務,舊服務也會在關閉前收到通知,停止接收新處理任務,當所有正在執行的任務處理完後再被關閉。

一個完整的線上系統,離不開運維服務,它做的很多事情、甚至是我們平時不知道的,我們開發人員應當關注並瞭解它。

2.4 小結

內部的獨立系統,各自負責某塊任務,系統之間互相關聯,運維服務保駕護航,構建了企業內部的生態環境,減少了很多重複的工作,也同樣可以讓某一個領域的系統做的更加深入和完善。

目前我們已經介紹了前端監控系統的需求背景和系統的構成情況,下一節我們將會稍微詳細的說明一下我們最核心的資料收集與分析。

三、資料收集與分析

3.1 資料收集

(1)效能
收集Native熱冷啟動、Web頁面載入、靜態資源、ajax介面等效能資訊,指標有載入時間、http協議版本、響應體大小等,這是為業務整體質量提升提供資料支撐,解決慢查詢問題等。

(2)錯誤
收集Nativejs報錯、靜態資源載入錯誤、ajax介面載入錯誤,這些常規錯誤收集都很好理解。下面主要說明一下"業務介面錯誤(bussiness)":

客戶端傳送ajax請求後端業務介面,介面都會返回json資料結構,而其中一般都會有errorcodemessage兩個欄位,errorcode為業務介面內部定義的狀態碼。正常的業務響應內部都會約定比如errorcode==0等,那如果不為0可能是一些異常問題或者可預見的異常問題,這種錯誤資料就是需要收集的。

由於不同團隊或者介面可能約定都不一樣,所以我們只會提供一個預設方法,預設方法會在ajax請求響應後呼叫,業務方自己根據約定和響應的json資料,在預設的方法中編寫判斷邏輯控制是否上報。像是下面這樣:

errcodeReport(res) {
  if (Object.prototype.toString.call(res) === '[object Object]' && res.hasOwnProperty('errcode') && res.errcode !== 0) {
    return { isReport: true, errMsg: res.errmsg,code: res.errcode };
  }
  return { isReport: false };
}

(3)輔助資訊
除了上面兩類硬指標資料,我們還需要很多其它的資訊,比如:使用者的訪問軌跡、使用者點選行為、使用者ID、裝置版本、裝置型號、UV/UA標識、traceId等等。很多時候我們要解決的問題並不是那麼簡單直接就能排查出來,甚至我們需要前端監控和其它系統在某些情況下能夠關聯上,所以這些軟指標資訊同樣很重要。

資料收集之後,並不能直接錄入到資料庫之中,而是要經過一定的處理。下面聊聊資料錄入的兩個過程。

3.2 資料錄入

(1)SDK過濾
一些三方的業務介面和資源等,有一定請求量,甚至它們自己也會會常常報錯。或者總有一些我們內部的介面我們並不想要做收集,這些資料收集起來會汙染我們的資料視角,影響我們檢視管理臺資料。客戶端SDK提供過濾配置,業務方可以根據具體業務過濾一些不需要收集的介面等。或者內建一些企業約定過濾的介面路徑。

(2)服務端處理
SDK上報的資料,服務端也是需要經過二次處理再儲存,例如為了查詢方便對原始資料做拆分等。

3.3 資料分析

當我們的資料已經錄入到資料庫以後,我們就可以對我們的資料應該分析和查詢了。除了管理臺基礎的資料查詢功能,我們也會提供圖表和日報,來幫助我們滿足不同的場景。

3.3.1 日報

日報可以從已有的資料中,篩選出重點資訊和分析後的內容,雖然平臺就在那裡,但是可能大家有時候真的不怎麼關注。日報的彙報目標物件目前主要是開發和測試人員。

3.3.2 圖表

圖表只是一種資料的展示形式,比如頁面效能載入實時圖表,實時錯誤圖表。在大部分情況下,可能我們都不會一直關注著,但是比如上線新版本的時候,我們可以一直開啟關注它的變化。圖表是資料視角的一種補充。

經過前面3節,對前端監控系統的功能都大致介紹完了。第四節,我們主要分享一下在打造前端監控系統的過程中,我們遇到過哪些問題,我們是如何解決的。

四、問題發現與解決

4.1 自動化整合測試

JS-SDK屬於一個需要長期維護和更新的獨立庫,它被使用在很多業務專案中。隨著程式碼量和特性的增加、人工測試成本變得越來越高,開發過程伴隨強烈的不安全感,測試覆蓋率低的可怕。於是從無到有,我們開始完善自動化整合測試。

我們的JS-SDK主要是加入探針監聽業務專案的執行狀態而收集資訊,整合測試是我們關注的重點。我們的Web SDK執行環境依賴Web瀏覽器環境,而不能單純的在node之中執行。目前我們有兩種測試方式並存。

通過終端測試,可以幫助我們支援持續整合環境(程式碼提交倉庫以後託管平臺提供的環境中進行託管測試)。
通過瀏覽器測試,可以讓程式碼執行在最真實的環境中,也可以做瀏覽器的相容測試。

4.2 資料聚合

在管理臺視角,我們是需要將資料進行聚合歸類的,這是為了讓我們更清晰的檢視我們的監控資料。但是一些原因會對資料造成聚合影響。

(1) 動態路由

有部分介面使用動態路由設定引數,如xxx.com/api/getuid/15501/detail。此類介面會導致根據url無法聚合同一個介面,因此SDK預設會把此類介面的動態引數部分替換為*。替換後上面的連結變成xxx.com/api/getuid/*/detail

這樣我們就能在服務端把他們歸類為一個介面。目前是正則匹配的全數字,剛好內部有此類介面的服務引數部分都是純數字。如果動態引數部分會存在非純數字的引數就會無法判別。只有SDK提供配置列表,業務方去一一配置相關連結,讓SDK自動替換。但是這樣對業務方使用不友好,也不好維護。所以一旦有此類情況發生,最好的建議就是用?或者訊息體的方式帶引數吧!

(2) 介面錯誤資訊不固定

前端監控收集到ajax業務錯誤響應資訊以後,會按照介面路徑+錯誤資訊的方式聚合同一個錯誤。有發現過一個介面響應的錯誤資訊帶了隨機值,隨機值可能是當前請求的配置的唯一id。大致如下:

{
    errMsg: '發生了異常(d1nbj1az5)',//括號內的為隨機值
    errcode: 1
}

解決方法就是,和服務端約定好,如果需要返回額外設定一個欄位,而不是放在錯誤資訊中。

4.3 資料庫

4.3.1 表設計

在迭代native版本時,對於表結構設計有多種方案的考慮。對於日誌系統,最終決定還是使用反規範化設計,通過犧牲空間來提高吞吐。

4.3.2 查詢優化

(1)索引

當資料量變得越來越大,查詢越來越慢時。我們對索引做了調整,以時間欄位建立索引,同時客戶端查詢條件預設定義合理的時間範圍,以此來優化查詢速度。並適當的使用複合索引。

(2)慢查詢

在早期,一些慢查詢、比如分鐘級定時任務使用的mapReduce語句,拉低了資料庫效能,通過一定的優化、低效語句替換,我們解決了這些慢查詢。線上優化前資料庫24小時平均cpu使用率78%,優化後為27%。下圖便是測試環境優化後的效果截圖,峰值發生了明顯下降。

4.3.3 獨享資料庫

最初前端監控系統和其他業務系統共享使用雲資料庫。由於前端監控在某段時期存在資料庫慢查詢的問題,而這個慢查詢剛好也是分鐘級別的定時任務。導致共享資料庫有很多慢查詢記錄,CPU消耗也一直維持在較高位置。前端監控本身也會保持一定的監控資料併發量在做儲存。前端監控拖累了整個資料庫,並且由於慢查詢日誌很多,導致其它業務在排查資料庫慢日誌的時候,很難找到他們自己的日誌。後來,運維同事就給單獨配置了一個獨享資料庫給前端監控。

遷移前配置12核32g三節點(一主兩從),遷移後為2核4g三節點。雖然配置變小了,但是前端監控獨享資料庫後平均響應速度反而變快了。前端監控的資料是屬於日誌資料,量更大,導致資料庫效能下降,影響到業務資料服務。日誌系統的資料庫和業務分離也是正確合理的。

當然系統的迭代過程中還有很多問題和細節,這裡就不一一列舉了。

結語

目前前端監控系統已經執行1年多,服務公司幾十個應用,它仍然有很多不足,它也一直保持規劃和迭代。記錄於此,繼續努力。

End

相關文章