JavaScript架構(gòu)前端監(jiān)控搭建過(guò)程步驟
前言
上一篇介紹了,前端為什么要有監(jiān)控系統(tǒng)?前端監(jiān)控系統(tǒng)的意義何在?有小伙伴看完后留言想聽(tīng)些詳細(xì)的實(shí)現(xiàn)。那么本篇我們就開(kāi)始介紹前端監(jiān)控如何實(shí)現(xiàn)。
如果還不明白為什么,搞監(jiān)控有什么用,建議先看上篇文章:為什么前端不能沒(méi)有監(jiān)控系統(tǒng)?
在動(dòng)手實(shí)現(xiàn)之前,首先腦子里要有一個(gè)整體脈絡(luò),明白搭建前端監(jiān)控具體的流程步驟有哪些。因?yàn)榍岸吮O(jiān)控系統(tǒng)實(shí)際上是一個(gè)完整的全棧項(xiàng)目,而并不僅僅是前端,甚至主要的實(shí)現(xiàn)都是圍繞在 數(shù)據(jù)方面 的。
當(dāng)然了,還有一點(diǎn)說(shuō)明,本篇的實(shí)現(xiàn)主要是面對(duì)普通業(yè)務(wù),面向中小廠自研的方向。我看過(guò)大廠做的監(jiān)控系統(tǒng),非常復(fù)雜能力也非常強(qiáng),動(dòng)不動(dòng)就是億萬(wàn)級(jí)別的數(shù)據(jù),最后整還到了大數(shù)據(jù)的方向。我只介紹如何實(shí)現(xiàn)主要功能,如何解決問(wèn)題。
前端監(jiān)控的搭建流程分以下幾個(gè)階段:
- 采集階段:數(shù)據(jù)的采集
- API 階段:搭建 API 應(yīng)用,接收采集到的數(shù)據(jù)
- 數(shù)據(jù)存儲(chǔ)階段:API 應(yīng)用對(duì)接數(shù)據(jù)庫(kù),將采集到的數(shù)據(jù)存起來(lái)
- 查詢統(tǒng)計(jì)階段:對(duì)采集到的數(shù)據(jù)進(jìn)行查詢,統(tǒng)計(jì),分析
- 可視化階段:前端通過(guò) API 查詢統(tǒng)計(jì)數(shù)據(jù),做可視化展示
- 報(bào)警階段:API 對(duì)接報(bào)警通知服務(wù),如釘釘
- 部署階段:應(yīng)用整體部署上線
下面我就梳理一下每個(gè)階段的關(guān)鍵實(shí)現(xiàn)思路。
采集階段:要采集哪些數(shù)據(jù)?
做監(jiān)控的第一步就是采集數(shù)據(jù),有了數(shù)據(jù)才是實(shí)現(xiàn)監(jiān)控的前提。
采集數(shù)據(jù)的意義就是記錄用戶在使用產(chǎn)品過(guò)程中的真實(shí)操作,結(jié)合上一篇我們的分析,真實(shí)操作產(chǎn)生的數(shù)據(jù)可以分兩大類:異常數(shù)據(jù) 和 行為數(shù)據(jù)。
我們先分析一下異常數(shù)據(jù)。項(xiàng)目中的異??傮w可以分為兩大類,一類是前端異常,一類是接口異常。
前端異常
前端異??偨Y(jié)起來(lái)大概可以分為:
- JS 代碼執(zhí)行異常
- Promise 異常
- 靜態(tài)資源加載異常
- console.error 異常
- 跨域異常
其中最重要的,也是我們遇到最多的,就是各種各樣的 js 代碼執(zhí)行異常。比如類型錯(cuò)誤,引用錯(cuò)誤等等,這些異常大多是我們編碼不嚴(yán)謹(jǐn)導(dǎo)致的,因此收集此類異常有利于我們改進(jìn)編碼質(zhì)量。
然后就是 Promise 異常,Promise 是 ES6 最重要的屬性之一,考驗(yàn)我們的 js 異步編程能力,集中體現(xiàn)在接口請(qǐng)求上面,因此這兩部分的異常捕獲非常關(guān)鍵。
除此之外,靜態(tài)資源加載異常,一般指在 html 中引用一些圖片地址,第三方 js 地址等,各種原因不能正常加載了,這個(gè)也要監(jiān)聽(tīng)的到。
console.error 異常,一般是在用某個(gè)第三方前端框架,他里面自定義了一些錯(cuò)誤,會(huì)用 console.error
拋出來(lái),這類異常也有捕獲的必要性。
至于跨域異常,這個(gè)我們常常碰到,一般在前后端開(kāi)發(fā)時(shí)的聯(lián)調(diào)階段就能發(fā)現(xiàn)。不過(guò)也保不定后端在線上突然改了什么配置,導(dǎo)致前端跨域,為了安全這個(gè)也要監(jiān)聽(tīng)一下。
前端的異常采集大概就這 5 種吧,基本囊括了前端 90% 以上的異常情況。
接口異常
接口異常屬于后端的異常,但是接口異常會(huì)直接導(dǎo)致前端頁(yè)面錯(cuò)誤,因此這類異常是我們判斷線上問(wèn)題根源的重要依據(jù)。接口異??梢愿鶕?jù)響應(yīng)結(jié)果分類:
- 未響應(yīng)/超時(shí)響應(yīng)異常
- 4xx 請(qǐng)求異常
- 5xx 服務(wù)器異常
- 權(quán)限不足
有時(shí)候因?yàn)榫W(wǎng)絡(luò)問(wèn)題或者服務(wù)器問(wèn)題,前端在發(fā)起請(qǐng)求之后遲遲未收到響應(yīng),請(qǐng)求被掛起,這種時(shí)候就屬于未響應(yīng)/超時(shí)響應(yīng)異常。這類異常我們可以設(shè)置最大請(qǐng)求時(shí)間,超時(shí)之后主動(dòng)斷開(kāi)請(qǐng)求,并添加一條接口超時(shí)記錄。
除此之外,其他類型的接口異常我們就可以根據(jù) HTTP 狀態(tài)碼 或者后端返回的指定字段如 error_code
來(lái)判斷。
不管是用狀態(tài)碼還是其他判斷方式,只要能區(qū)分異常類型就可以,這個(gè)不做嚴(yán)格要求。
4xx 異常類型是請(qǐng)求異常,一般是前端傳遞的參數(shù)問(wèn)題,或者接口驗(yàn)證參數(shù)的問(wèn)題。處理這類異常的關(guān)鍵是保存請(qǐng)求參數(shù),可以方便前端排錯(cuò)。
5xx 錯(cuò)誤是服務(wù)器內(nèi)部處理的異常,這類異常的關(guān)鍵信息是報(bào)錯(cuò)時(shí)間,以及返回的異常說(shuō)明,將這些保存下來(lái),可以方便后端去查找日志。
權(quán)限不足我覺(jué)得也是一類重要的錯(cuò)誤。因?yàn)楝F(xiàn)在某些管理系統(tǒng)的權(quán)限設(shè)計(jì)比較復(fù)雜,有時(shí)候突然莫名其妙的接口調(diào)不通,影響用戶的下一步操作,這也需要記錄和追蹤。
行為數(shù)據(jù)
行為數(shù)據(jù)就比較寬泛了,用戶任何有意義的操作我們都可以定義為行為數(shù)據(jù)。
比如點(diǎn)擊某個(gè)按鈕,停留了多久,新功能的點(diǎn)擊率,什么時(shí)候使用,等等等等。自研監(jiān)控系統(tǒng)的一大優(yōu)點(diǎn)就是靈活,你需要任何有用的信息,都可以在這個(gè)階段設(shè)計(jì)。
這個(gè)階段非常關(guān)鍵,是監(jiān)控系統(tǒng)設(shè)計(jì)的核心,所以我寫的比較細(xì),大家在這個(gè)階段關(guān)于采集哪些數(shù)據(jù)也要多多考慮。而后面的階段,則都是基于此設(shè)計(jì)的具體實(shí)現(xiàn)。
API 階段:搭建上報(bào)數(shù)據(jù)的 API 接口
上一階段做好了采集數(shù)據(jù)的方案,當(dāng)采集到數(shù)據(jù)之后,接下來(lái)就要將 數(shù)據(jù)上報(bào)。
數(shù)據(jù)上報(bào)說(shuō)白了就是通過(guò)調(diào)用一個(gè) API 接口將這些數(shù)據(jù)傳過(guò)去然后存在數(shù)據(jù)庫(kù)中,因此本階段的任務(wù)就是搭建上報(bào)數(shù)據(jù)的 API 接口應(yīng)用。
作為一名光榮的前端工程師,開(kāi)發(fā)接口,自然要選擇同屬 JS 家族的 Node.js 了。Node.js 目前的框架也比較多,我比較喜歡輕量好簡(jiǎn)潔的,需要什么自己安裝,所以我選擇簡(jiǎn)單經(jīng)典的 Express 框架。
搭建 API 應(yīng)用要做的事情有:
- 目錄結(jié)構(gòu)設(shè)計(jì)
- 路由設(shè)計(jì)
- 鑒權(quán)認(rèn)證
- 參數(shù)驗(yàn)證
- 請(qǐng)求響應(yīng)封裝
- 錯(cuò)誤處理
還有一些細(xì)節(jié)的處理。這個(gè)階段對(duì)后端基礎(chǔ)薄弱的同學(xué)來(lái)說(shuō),是非常好的學(xué)習(xí)時(shí)機(jī)。
我非常建議前端小伙伴們掌握一部分后端基本知識(shí),至少在簡(jiǎn)單的原理方面明白是怎么回事。這個(gè)階段主要是搞明白 API 應(yīng)用是怎么搭建起來(lái)的,每個(gè)部分為什么要這么做,能解決什么問(wèn)題,這樣你的后端基礎(chǔ)知識(shí)就會(huì)建立起來(lái)了。
框架搭好之后,主要做的就是設(shè)計(jì)接口 URL 然后寫處理邏輯,保證這一步設(shè)計(jì)的接口能調(diào)通,并且能接收到數(shù)據(jù)。
數(shù)據(jù)存儲(chǔ)階段:接口對(duì)接數(shù)據(jù)庫(kù)
上一步我們搭建好了 API 接口,接收到了采集的數(shù)據(jù),那么我們這一步就是要對(duì)接數(shù)據(jù)庫(kù),將采集到的數(shù)據(jù)存到數(shù)據(jù)庫(kù)里。
數(shù)據(jù)庫(kù)的話,就選對(duì)前端最友好的,屬于 NoSQL 家族的文檔數(shù)據(jù)庫(kù) MongoDB
。
這個(gè)數(shù)據(jù)庫(kù)最大的特點(diǎn)是,存儲(chǔ)的數(shù)據(jù)格式類似于 JSON,操作起來(lái)就像在 JS 中調(diào)用函數(shù),組合 JOSN 數(shù)據(jù)一樣,對(duì)我們前端理解和入門非常容易,在實(shí)戰(zhàn)過(guò)程中你就能體會(huì)到它的優(yōu)雅了。
數(shù)據(jù)存儲(chǔ)階段,主要介紹數(shù)據(jù)庫(kù)的基本信息和操作,包括以下方面:
- 數(shù)據(jù)庫(kù)怎么連接
- 怎么設(shè)計(jì)字段
- 怎么做驗(yàn)證
- 怎么寫入
- 怎么查詢
這個(gè)階段比較關(guān)鍵的是 數(shù)據(jù)驗(yàn)證,在設(shè)計(jì)好數(shù)據(jù)庫(kù)字段之后,我們希望所有寫入的數(shù)據(jù)都要符合我們想要的數(shù)據(jù)格式。如果在驗(yàn)證之后不符合,我們可以補(bǔ)充或修改數(shù)據(jù)字段,或者直接拒絕寫入,這樣能保證數(shù)據(jù)的可靠性,也避免了不必要的數(shù)據(jù)清理。
做好了數(shù)據(jù)寫入的工作,還要加一部分簡(jiǎn)單的查詢和修改功能。因?yàn)槟銓懭霐?shù)據(jù)之后要看看執(zhí)行成功沒(méi)有,就可以查一個(gè)列表看結(jié)果了。
修改功能也很必要。前端監(jiān)控中有一個(gè)很常見(jiàn)的需求是:計(jì)算用戶的頁(yè)面停留時(shí)間。我的方案是在用戶進(jìn)入某個(gè)頁(yè)面的時(shí)候創(chuàng)建一條記錄,然后在離開(kāi)時(shí),修改這條記錄,加一個(gè)結(jié)束時(shí)間的字段,這就需要修改功能了。
最后還要提一下,很多人在聊怎么做 數(shù)據(jù)清洗。其實(shí)這個(gè)就看你前面存儲(chǔ)數(shù)據(jù)的時(shí)候驗(yàn)證做的怎么樣了。如果確實(shí)有可能存入無(wú)效的數(shù)據(jù),那么就可以寫一個(gè)清除數(shù)據(jù)的接口,寫自己的清理邏輯,然后定時(shí)執(zhí)行一下。
查詢統(tǒng)計(jì)階段:數(shù)據(jù)查詢和統(tǒng)計(jì)分析
前面經(jīng)過(guò)一系列準(zhǔn)備我們完成了 API 接口和數(shù)據(jù)寫入的功能,假設(shè)我們已經(jīng)采集到了足夠的數(shù)據(jù)并存入數(shù)據(jù)庫(kù),這個(gè)階段就是好好利用這些數(shù)據(jù)的時(shí)候了。
本階段的主要任務(wù)就是對(duì)數(shù)據(jù)進(jìn)行檢索和統(tǒng)計(jì)分析,基本上都是“查詢”的操作。
這里的查詢不單單只是查一下,具體怎么查,關(guān)系到了我們搜集的數(shù)據(jù)能否有效利用。我的思路還是從這兩個(gè)方面入手:
- 行為數(shù)據(jù):整體統(tǒng)計(jì)查詢,看某個(gè)時(shí)間段的趨勢(shì)
- 異常數(shù)據(jù):?jiǎn)螚l查詢,精確定位,排查具體的錯(cuò)誤
當(dāng)然了這只是從總體來(lái)說(shuō)。行為數(shù)據(jù)也會(huì)單條查詢,比如我要看某個(gè)時(shí)間某個(gè)用戶做了什么操作,這就屬于精確查找。異常數(shù)據(jù)也有統(tǒng)計(jì),比如異常接口觸發(fā)頻率的排行等。
行為數(shù)據(jù)的數(shù)據(jù)量會(huì)非常大,在用戶使用系統(tǒng)的過(guò)程中會(huì)頻繁產(chǎn)生然后頻繁被寫入數(shù)據(jù)庫(kù)。因此這類數(shù)據(jù)絕大多數(shù)情況是通過(guò) 聚合查詢 的方式從頁(yè)面,時(shí)間等多個(gè)維度做總體統(tǒng)計(jì),最后得出一些百分比的結(jié)論。這些統(tǒng)計(jì)值可以大致反應(yīng)出產(chǎn)品的實(shí)際使用情況。
這里有個(gè)優(yōu)化點(diǎn),因?yàn)轭l繁請(qǐng)求會(huì)加重接口負(fù)擔(dān),因此數(shù)據(jù)也可以本地先存儲(chǔ)一部分,達(dá)到一定量之后再請(qǐng)求接口,一次性存入。
異常數(shù)據(jù)對(duì)開(kāi)發(fā)人員來(lái)說(shuō)非常重要,是我們定位和解決 bug 的神輔助。不同于行為數(shù)據(jù)的多條統(tǒng)計(jì),異常數(shù)據(jù)我們更關(guān)心單獨(dú)每一條記錄的詳細(xì)信息,方便我們一目了然的看到錯(cuò)誤。
異常數(shù)據(jù)查詢也比較簡(jiǎn)單,和普通的列表查詢一樣,返回最新的異常數(shù)據(jù)即可。當(dāng)然了我們排查問(wèn)題之后,還應(yīng)該對(duì)處理好的異常標(biāo)記為已處理,這樣可以防止重復(fù)排查。
可以看出,這個(gè)階段最主要的還是做統(tǒng)計(jì)接口,為下個(gè)階段可視化圖表展示做準(zhǔn)備。
可視化階段:最終的數(shù)據(jù)圖表展現(xiàn)
上一個(gè)階段我們開(kāi)發(fā)了統(tǒng)計(jì)接口,查出了想要的數(shù)據(jù)結(jié)果,可惜這些結(jié)果只能程序員看懂,別人恐怕是看不懂。所以最終為了更直觀的反應(yīng)數(shù)據(jù),我們要用前端可視化圖表的方式,讓這些數(shù)據(jù)活起來(lái)。
在這個(gè)階段,我們終于回到了最熟悉的 前端領(lǐng)域。那本階段的任務(wù)相對(duì)來(lái)說(shuō)也簡(jiǎn)單順手,基于 React 搭建一個(gè)新的前端應(yīng)用,接入上一步的統(tǒng)計(jì)接口,再集成前端圖表庫(kù),將統(tǒng)計(jì)結(jié)果用圖表展現(xiàn)出來(lái)。
這個(gè)新應(yīng)用是真正要對(duì)外展示的前端監(jiān)控系統(tǒng),給團(tuán)隊(duì)內(nèi)部的開(kāi)發(fā)或產(chǎn)品同學(xué)使用,這樣他們可以實(shí)時(shí)查看產(chǎn)品生成的數(shù)據(jù)信息,從而解決自己的問(wèn)題了。
這一階段其實(shí)沒(méi)什么關(guān)鍵問(wèn)題要講,主要就是選擇一個(gè)好用的圖表庫(kù),對(duì)接接口。還有圖表的種類多種多樣,要考慮哪些數(shù)據(jù)適合哪種圖表,結(jié)合實(shí)際判斷一下。
最后,監(jiān)控系統(tǒng)的前端頁(yè)面和接口數(shù)據(jù)肯定不能所有人都看,所以還要有基礎(chǔ)的登錄頁(yè)面和功能。做到這里,本階段的任務(wù)就結(jié)束了。
報(bào)警階段:發(fā)現(xiàn)異常馬上報(bào)警通知
上一階段,監(jiān)控系統(tǒng)前端搭建完成,并將統(tǒng)計(jì)數(shù)據(jù)展現(xiàn)為圖表之后,整個(gè)監(jiān)控系統(tǒng)就基本可用了。
但是還有一種情況,就是用戶使用我們的產(chǎn)品突然報(bào)錯(cuò)了,錯(cuò)誤信息也被寫入了數(shù)據(jù)庫(kù)。如果此時(shí)你沒(méi)有主動(dòng)刷新頁(yè)面,事實(shí)上你也不可能一直刷新,那么這條錯(cuò)誤我們是根本不知道的。
如果這是一個(gè)很致命的 bug,影響很廣泛,Bug 發(fā)生我們竟然不知道,這就會(huì)給我們?cè)斐珊艽蟮膿p失。
所以呢,為了保證我們及時(shí)的解決 Bug,一個(gè)報(bào)警通知的功能就非常重要了。它的作用是在異常發(fā)生時(shí),第一時(shí)間 推送給開(kāi)發(fā)人員,這樣大家才能立即發(fā)現(xiàn)問(wèn)題,然后用最快的速度去解決,避免遺漏。
報(bào)警通知,一般現(xiàn)在通用的方案是對(duì)接釘釘或者是企業(yè)微信的機(jī)器人,我們這里使用釘釘。具體用哪個(gè)平臺(tái)還得看你的主體在哪個(gè)平臺(tái)。比如我的團(tuán)隊(duì)的主體在釘釘,那么在發(fā)送報(bào)警通知時(shí),可以直接用手機(jī)號(hào)來(lái) @ 你的任意組員,實(shí)現(xiàn)更精準(zhǔn)的提醒。
這一部分是 API 應(yīng)用的補(bǔ)充,申請(qǐng)釘釘開(kāi)發(fā)者權(quán)限之后,在 API 中接入相關(guān)代碼。
部署階段:萬(wàn)事俱備只等上線
前面的幾個(gè)階段,我們完成了數(shù)據(jù)采集,API 應(yīng)用搭建,數(shù)據(jù)存儲(chǔ),前端可視化展現(xiàn),以及監(jiān)控報(bào)警,整個(gè)前端監(jiān)控系統(tǒng)的功能就全部完備了。最后一步就是將前后端數(shù)據(jù)庫(kù)全部部署上線,供大家訪問(wèn)。
部署這塊主要是 nginx 解析,https 配置,數(shù)據(jù)庫(kù)安裝,和 nodejs 的應(yīng)用部署等,這個(gè)階段的內(nèi)容會(huì)偏運(yùn)維一些。不過(guò)別擔(dān)心,這里我也會(huì)對(duì)關(guān)鍵操作做詳細(xì)介紹。
當(dāng)這個(gè)系統(tǒng)上線以后,你就可以嘗試在你的任意一個(gè)前端項(xiàng)目,根據(jù)第一篇的采集方法,將采集到的數(shù)據(jù)通過(guò) API 保存,然后就可以登入監(jiān)控系統(tǒng)查看真實(shí)的使用數(shù)據(jù)了。
當(dāng)這一部分完成之后,恭喜你,一個(gè)小型的前端監(jiān)控系統(tǒng)就搭建好了。后續(xù)可以基于此不斷擴(kuò)展功能,慢慢讓這個(gè)自研的監(jiān)控系統(tǒng)更加強(qiáng)大。
總結(jié)
本篇介紹了前端監(jiān)控系統(tǒng)的搭建過(guò)程,將整體流程劃分為幾個(gè)階段,簡(jiǎn)述了每個(gè)階段要做什么事情,以及關(guān)鍵問(wèn)題是什么,幫你理清搭建監(jiān)控系統(tǒng)的思路,更多關(guān)于JavaScript架構(gòu)前端監(jiān)控搭建的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS+CSS實(shí)現(xiàn)感應(yīng)鼠標(biāo)漸變顯示DIV層的方法
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)感應(yīng)鼠標(biāo)漸變顯示DIV層的方法,涉及javascript對(duì)div層的逐漸顯示與隱藏的實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-02-02開(kāi)源的javascript項(xiàng)目Kissy介紹
本文向大家介紹了開(kāi)源的javascript項(xiàng)目Kissy,是taobao UED小組推的一款js框架,我們來(lái)簡(jiǎn)單研究下,為什么taobao這么推崇他呢。2014-11-11js+flash實(shí)現(xiàn)的5圖變換效果廣告代碼(附演示與demo源碼下載)
這篇文章主要介紹了js+flash實(shí)現(xiàn)的5圖變換效果廣告代碼,涉及JavaScript結(jié)合flash調(diào)用圖片實(shí)現(xiàn)幻燈廣告效果,并附帶演示與demo源碼供讀者下載參考,需要的朋友可以參考下2016-04-04回車直接實(shí)現(xiàn)點(diǎn)擊某按鈕的效果即觸發(fā)單擊事件
這篇文章主要介紹了回車直接實(shí)現(xiàn)點(diǎn)擊某按鈕的效果即觸發(fā)單擊事件,需要的朋友可以參考下2014-02-02JS實(shí)現(xiàn)iframe中子父頁(yè)面跨域通訊的方法分析
這篇文章主要介紹了JS實(shí)現(xiàn)iframe中子父頁(yè)面跨域通訊的方法,結(jié)合實(shí)例形式分析了JS實(shí)現(xiàn)iframe頁(yè)面跨域通訊常見(jiàn)操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-03-03javascript 實(shí)現(xiàn)簡(jiǎn)單的table排序及table操作練習(xí)
在這個(gè)列子中,練習(xí)了table的操作,主要有:tBodies、rows、cells,還有有關(guān)數(shù)組的排序方法:sort,按興趣的朋友可以研究下2012-12-12JS實(shí)現(xiàn)根據(jù)密碼長(zhǎng)度顯示安全條功能
這篇文章主要介紹了基于JS實(shí)現(xiàn)根據(jù)密碼長(zhǎng)度顯示安全條功能,非常不錯(cuò),在一些網(wǎng)站上經(jīng)常會(huì)遇到此功能,需要的的朋友參考下實(shí)現(xiàn)代碼吧2017-03-03js實(shí)現(xiàn)內(nèi)置計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)內(nèi)置計(jì)時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12