美团开源 Logan Web:前端日志在 Web 端的实现
1.前言
Logan 是美團(tuán)點(diǎn)評(píng)推出的大前端日志系統(tǒng),支持多端環(huán)境運(yùn)行,可為客戶端、Web、小程序等用戶端環(huán)境提供前端日志的存儲(chǔ)、收集、上報(bào)及分析能力,能夠幫助開發(fā)人員快速定位并解決端上問題,便于及時(shí)響應(yīng)用戶反饋與排除異常。
2018 年 10 月,Logan 在社區(qū)開源了 Android 與 iOS 端的 SDK,實(shí)現(xiàn)了在客戶端進(jìn)行日志存儲(chǔ)及上報(bào)代碼的功能,引起用戶端相關(guān)開發(fā)者的廣泛關(guān)注。詳細(xì)可參見博客文章:《Logan:美團(tuán)點(diǎn)評(píng)的開源移動(dòng)端基礎(chǔ)日志庫》。
2019 年 12 月 12 日,Logan 開源了在 Web 環(huán)境運(yùn)行的 SDK、日志分析平臺(tái)以及服務(wù)端代碼,為開發(fā)者們提供了 Logan 大前端日志系統(tǒng)的一整套實(shí)現(xiàn)方案,進(jìn)一步解決了多端環(huán)境中日志的存儲(chǔ)與采集問題。
本文將圍繞 Logan 在 Web 端的應(yīng)用背景、技術(shù)實(shí)現(xiàn)、美團(tuán)點(diǎn)評(píng)的實(shí)踐、開源整體進(jìn)展以及未來規(guī)劃這幾個(gè)方面展開介紹,以方便讀者對(duì) Logan 大前端日志系統(tǒng)有更加深入的了解。
Logan 項(xiàng)目地址:https://github.com/Meituan-Dianping/Logan。
2.背景
2.1 為何需要 Logan?
在 Logan 誕生前,用戶端開發(fā)者在面對(duì)用戶反饋頁面功能異常時(shí),最常說的靈魂三答是:
這三條回答分別對(duì)應(yīng)著開發(fā)者在解決端上問題時(shí)的心路歷程:
“啥問題”:通過與用戶溝通,獲取異常發(fā)生前后過程的詳細(xì)描述,嘗試在開發(fā)者本地模擬,以期復(fù)現(xiàn)問題。
“我這里看是好的”:問題沒有復(fù)現(xiàn),應(yīng)該是用戶端兼容性的 bug。
“你重啟下”:想不出修復(fù)的辦法,只能“死馬當(dāng)活馬醫(yī)”,碰碰運(yùn)氣。
對(duì)用戶端的開發(fā)者來說,本地?zé)o法復(fù)現(xiàn)的問題好比“斷了線的風(fēng)箏”,讓人無計(jì)可施。如果有辦法獲取到事發(fā)時(shí)完整的日志流以及用戶環(huán)境的上下文信息,就能夠幫助開發(fā)者快速了解并還原問題的發(fā)生現(xiàn)場,可以更有效地定位排查問題,讓風(fēng)箏最終被拉回到開發(fā)者手里。正是因?yàn)檫@樣的迫切需要,Logan 大前端日志系統(tǒng)才應(yīng)運(yùn)而生。
2.2 Logan 日志系統(tǒng)的策略與核心
2.2.1 Logan 在各端實(shí)行的通用策略
雖然用戶端上完整的日志流及上下文環(huán)境信息更有助于開發(fā)者定位到問題,但對(duì)每個(gè)用戶端的日志流都進(jìn)行實(shí)時(shí)上報(bào)的話,也會(huì)出現(xiàn)如下問題:
巨大開銷:耗費(fèi)用戶流量,占用企業(yè)帶寬與服務(wù)器存儲(chǔ)資源。
大海撈針:在海量日志中可能只有極少部分的日志能夠幫助復(fù)現(xiàn)問題。
因此 Logan 在各端上實(shí)行的通用策略,是本地日志存儲(chǔ)結(jié)合觸發(fā)上報(bào)的模式,如流程圖所示:
a. 平時(shí)在用戶端腳本執(zhí)行過程中產(chǎn)生的日志會(huì)落地到本地的存儲(chǔ)容器中。
b. 當(dāng)遇到用戶反饋或者端上異常被捕獲時(shí),Logan 以特定機(jī)制觸發(fā)本地日志的上報(bào)。
c. 本地日志流將在用戶端上傳,由服務(wù)端收集并解析,最后上傳至云端存儲(chǔ)。
d. 由 Logan 統(tǒng)一的日志分析平臺(tái)向開發(fā)者提供日志數(shù)據(jù)的可視化展示。
e. 開發(fā)者利用 Logan 日志排查定位并解決問題后,向用戶反饋或者排除異常。
2.2.2 Logan 的三大核心
上文所闡述的 Logan 通用策略中的工作流程也決定了 Logan 日志系統(tǒng)擁有三大核心:
用戶端 SDK(客戶端版、Web 版及小程序版):負(fù)責(zé)存儲(chǔ)與上報(bào)端上日志。
服務(wù)器端:負(fù)責(zé)接收、解析、整合與分析日志。
日志分析平臺(tái):提供日志的查詢與數(shù)據(jù)可視化展示。
2.3 Logan 在 Web 端面臨的問題
在 Web 環(huán)境中若要實(shí)現(xiàn)端上日志存儲(chǔ)及上報(bào)需要解決三大難點(diǎn):
如何存儲(chǔ)?需要解決 Web 本地大體積日志流的存取。
如何保障日志安全?在本地已存儲(chǔ)的日志需要有數(shù)據(jù)安全保障。
如何上報(bào)?需要有效的機(jī)制觸發(fā)日志的上報(bào)。
2.4 Logan Web 做了什么?
Logan Web 是 Logan 在 Web 端的存儲(chǔ)及上報(bào)實(shí)現(xiàn)方案,利用現(xiàn)有的前端技術(shù)加以優(yōu)化與整合,有效地解決了 Web 端面臨的三大難點(diǎn)。我們將存儲(chǔ)與上報(bào)的實(shí)現(xiàn)封裝在 Web 端的 SDK 內(nèi),開發(fā)者只需在頁面腳本中引入該 SDK,便可直接使用 Logan 在 Web 端上的日志安全存儲(chǔ)與上報(bào)能力。
下面將重點(diǎn)圍繞存儲(chǔ)方案、數(shù)據(jù)安全及上報(bào)機(jī)制這三點(diǎn),具體闡述 Logan Web 目前的技術(shù)實(shí)現(xiàn)。
3. 技術(shù)實(shí)現(xiàn)
Logan Web 在底層利用了現(xiàn)有前端技術(shù)來實(shí)現(xiàn)大體積日志的安全存儲(chǔ):
存儲(chǔ)方面:利用瀏覽器的 IndexedDB 作為本地日志的大容量存儲(chǔ)容器。
日志安全方面:使用混合加密模式確保本地已存的隱私日志數(shù)據(jù)不會(huì)被破解。
Logan 為 Web 開發(fā)者提供了 logan-web 這個(gè) SDK 包,其內(nèi)部主要分為存儲(chǔ)與上報(bào)兩大核心模塊,底層依賴了 IndexedDB 存儲(chǔ)與加密組件。開發(fā)者可在頁面腳本中引入并加載該 SDK 來調(diào)用日志存儲(chǔ)或上報(bào)接口。
3.1 Logan Web 整體技術(shù)架構(gòu)
以下是 Logan Web 的整體架構(gòu)示意圖:
a. logan-web 提供了一個(gè)入口文件,它將在日志存儲(chǔ)方法或者日志上報(bào)方法被觸發(fā)時(shí),異步地獲取存儲(chǔ)或上報(bào)模塊。
b. 存儲(chǔ)模塊中會(huì)優(yōu)先處理日志內(nèi)容的加密及包裝,再執(zhí)行后續(xù)的分頁存儲(chǔ)流程。
c. 上報(bào)模塊會(huì)分頁讀取指定天的日志數(shù)據(jù),并行上報(bào)至接收日志的服務(wù)端,進(jìn)行后續(xù)的日志解析、解密、整合及分析。
d. 這兩大核心模塊都會(huì)使用 Logan DB 模塊封裝的日志存取邏輯,該模塊還會(huì)控制本地日志數(shù)據(jù)的存儲(chǔ)容量以及日志分頁。
對(duì) IndexedDB API 的調(diào)用被封裝在獨(dú)立于 logan-web 的 idb-managed 包中,該包主要解決在使用 IndexedDB 進(jìn)行本地存儲(chǔ)時(shí)遇到的技術(shù)挑戰(zhàn)。
3.2 本地存儲(chǔ)方案:idb-managed
3.2.1 原生 IndexedDB API 的局限
IndexedDB 支持大容量存儲(chǔ),并且其讀取操作是異步化的,非常適合作為 Logan Web 的本地存儲(chǔ)容器。但 IndexedDB API 在使用上會(huì)遇到如下幾個(gè)問題:
(1)DB 版本升級(jí)問題
本地 DB 依靠版本的升級(jí)來更新庫表結(jié)構(gòu),當(dāng)本地該 DB 的版本升級(jí)后,嘗試連接低版本 DB 的操作將失敗。
(2)獲取 DB 數(shù)據(jù)前需要設(shè)置 DB 版本及庫表信息
獲取 DB 數(shù)據(jù)前需要首先連接 DB,如果連接時(shí)沒有設(shè)置恰當(dāng)?shù)膸毂硇畔?#xff0c;下一次存儲(chǔ)時(shí)依然以同版本建立連接,IndexedDB 則不再更新該 DB 的庫表結(jié)構(gòu),最終會(huì)因?yàn)榇鎯?chǔ)數(shù)據(jù)不匹配表結(jié)構(gòu)而導(dǎo)致存儲(chǔ)失敗。
(3) IndexedDB 不提供數(shù)據(jù)的時(shí)效設(shè)置與過期數(shù)據(jù)清理
IndexedDB 默認(rèn)數(shù)據(jù)是持久化落地的,盡管它的可用容量遠(yuǎn)大于 LocalStorage,但在像 Logan Web 這樣需要隨時(shí)間不斷更新本地?cái)?shù)據(jù)的使用場景下,就需要一套隨時(shí)間迭代的數(shù)據(jù)更新機(jī)制來“除舊存新”。
(4)原生 IndexedDB API 不提供多表間的原子性增刪操作
原生的 IndexedDB API 只提供了單條數(shù)據(jù)的添加,以及單表內(nèi)的數(shù)據(jù)批量刪除操作,并不直接提供 API 對(duì)多表的數(shù)據(jù)進(jìn)行添加或者刪除的原子性操作( 要么全部生效,要么全不生效 )。Logan DB 的庫表結(jié)構(gòu)涉及到兩張表數(shù)據(jù)間的聯(lián)動(dòng),需要多表間原子性增刪來保證日志數(shù)據(jù)在兩張表間保持一致。
3.2.2 idb-managed 的解決手段
為了統(tǒng)一解決以上在使用 IndexedDB 時(shí)面臨的困擾,我們額外封裝了 idb-managed 包,該包隨著 Logan Web 一起開源。
idb-managed 中分別針對(duì):
問題 1 與 2:提出并實(shí)現(xiàn)了 DB Manager 機(jī)制來解決 DB 版本升級(jí)與數(shù)據(jù)獲取的困境。
問題 3:封裝了對(duì)存儲(chǔ)數(shù)據(jù)的時(shí)效設(shè)置、過期處理邏輯。
問題 4:利用事務(wù)回滾方法實(shí)現(xiàn)在多表內(nèi)的原子性增刪操作。
(1)DB Manager 機(jī)制
idb-managed 中內(nèi)建了一個(gè) DB Manager 來管理當(dāng)前所有本域下的 DB 版本與庫表結(jié)構(gòu)信息,其實(shí) DB Manager 自身就是一個(gè)版本號(hào)固化的 DB,它本身不存在升級(jí)問題。建立鏈接示意圖如下:
當(dāng)對(duì)一個(gè)新 DB 建立連接時(shí),會(huì)將腳本中設(shè)置的 DB 版本及庫表信息注冊(cè)到 DB Manager 中并把數(shù)據(jù)存儲(chǔ)下來。下一次如果有該 DB 的低版本嘗試連接時(shí),DB Manager 會(huì)用當(dāng)前已注冊(cè)的庫表信息連接并打開 DB,由此避免了 DB 升級(jí)而導(dǎo)致連接低版本失敗的問題 。
同時(shí),因?yàn)橛?DB Manager 來統(tǒng)一管理本地的 DB 信息,所以從 DB 獲取數(shù)據(jù)可以無需知曉 DB 庫表結(jié)構(gòu),只需要 DB 名和表名即可。當(dāng)本地庫表不存在時(shí),DB Manager 會(huì)阻止對(duì)該 DB 的連接,直接返回空數(shù)據(jù),避免了錯(cuò)誤的庫表結(jié)構(gòu)污染本地 DB。
(2)數(shù)據(jù)時(shí)效控制
idb-managed 會(huì)為每張表建立一個(gè)到期時(shí)間索引,開發(fā)者可對(duì)單條數(shù)據(jù)、單個(gè)表或者單個(gè)庫設(shè)置一個(gè)持久化時(shí)間限制,在數(shù)據(jù)存儲(chǔ)時(shí) idb-managed 會(huì)根據(jù)這些限制及優(yōu)先級(jí)順序(單條 > 單表 > 單庫)計(jì)算該條數(shù)據(jù)的到期時(shí)間,并與數(shù)據(jù)一起保存下來,過期的數(shù)據(jù)會(huì)在該表下一次添加數(shù)據(jù)時(shí)先行刪除。
(3)多表間原子性增刪操作
IndexedDB 中數(shù)據(jù)的增刪操作全部建立在事務(wù)(IDBTransaction)基礎(chǔ)之上,idb-managed 封裝了多表批量數(shù)據(jù)的增刪操作接口,并將這些操作包裹在一次事務(wù)內(nèi)。如果在一次事務(wù)中發(fā)生異常,idb-managed 將執(zhí)行本次事務(wù)的回滾,從而保證這批操作具有原子性。
3.3 日志加密方案:混合加密
混合加密方式吸取了對(duì)稱加密與非對(duì)稱加密各自的優(yōu)勢:
對(duì)稱加密:保證對(duì)長內(nèi)容加密的效率。
非對(duì)稱加密:保證對(duì)稱密鑰的安全性。
Logan Web 選擇了 AES-128-CTR 結(jié)合 RSA-1024 的混合加密模式。在存儲(chǔ)每條具有私密性的日志前都會(huì)經(jīng)歷以下加密流程:
a. 準(zhǔn)備對(duì)稱密鑰與初始向量:隨機(jī)產(chǎn)生 AES 對(duì)稱密鑰 AES Key 及初始向量 IV。
b. 對(duì)稱加密:使用 AES Key 及 IV 對(duì)日志明文進(jìn)行 AES-CTR 對(duì)稱加密,得到日志密文。
c. 非對(duì)稱加密 AES Key:使用 RSA 公鑰對(duì) AES Key 進(jìn)行非對(duì)稱加密,得到 AES Key 密文。該 RSA 公鑰與服務(wù)器端的私鑰是成套的,只有該私鑰可以解開該 AES Key 密文,從而解開日志密文。
e. 包裝數(shù)據(jù):將以上初始向量、日志密文與 AES Key 密文包裝成一條日志對(duì)象,隨后存儲(chǔ)落地。
3.4 上報(bào)的觸發(fā)機(jī)制
用戶端的日志上報(bào)觸發(fā)機(jī)制一般分為兩大類:
用戶主動(dòng)觸發(fā)。優(yōu)點(diǎn)是上報(bào)的日志能夠?qū)?yīng)到用戶反饋的個(gè)案;缺點(diǎn)是存在交互上的用戶教育成本,同時(shí)依賴用戶反饋的異常處理流程,過于滯后。
代碼層面觸發(fā)。優(yōu)點(diǎn)是用戶無需感知上報(bào)流程;缺點(diǎn)是可能存在大量“無幫助”的上報(bào)日志,需要對(duì)觸發(fā)條件做好頻率控制。
Logan Web 在兩類方式上提供了配置與接口,供 SDK 使用方自行選擇與擴(kuò)展,例如:
(1)用戶主動(dòng)觸發(fā)
PC 端:Logan Web 在美團(tuán)點(diǎn)評(píng)內(nèi)實(shí)踐時(shí),為業(yè)務(wù)方提供了 DOM 元素配置項(xiàng),用于 Logan Web 綁定觸發(fā)上報(bào)的鉤子函數(shù)。
H5 手機(jī)端:Logan Web 可擴(kuò)展內(nèi)置設(shè)備搖動(dòng)檢測,利用瀏覽器的 DeviceMotionEvent 事件監(jiān)聽,當(dāng)用戶“搖一搖”時(shí),引導(dǎo)上報(bào)流程的美團(tuán)卡通形象會(huì)出現(xiàn)在頁面?zhèn)葯?#xff0c;如下圖所示。
通用:Logan Web 在美團(tuán)點(diǎn)評(píng)內(nèi)擴(kuò)展提供了接口供業(yè)務(wù)方顯示或者隱藏引導(dǎo)上報(bào)流程的側(cè)欄。
(2)代碼層面觸發(fā)
考慮到用戶主動(dòng)觸發(fā)方式存在的弊端,Logan Web 提供了上報(bào)接口供使用者在代碼層面調(diào)用。另外 Logan Web 也正在迭代實(shí)現(xiàn)內(nèi)部的代碼觸發(fā)上報(bào)邏輯,提供在 Web 端內(nèi)異常發(fā)生等特定場景下主動(dòng)上報(bào)日志的能力。
4. Logan Web 在美團(tuán)點(diǎn)評(píng)內(nèi)的實(shí)踐
Logan Web 已在美團(tuán)內(nèi)部上線,并持續(xù)迭代了一年多的時(shí)間,覆蓋公司很多主要的業(yè)務(wù)線。截止 2019 年 11 月,公司內(nèi)使用 Logan Web 的頁面 PV 量已達(dá)日均 1.5 億余次,Web 上報(bào)日志量達(dá)日均 500 余次,約 97% 上報(bào)的 Web 日志在 Logan 日志分析平臺(tái)上被公司研發(fā)同學(xué)搜索查閱。利用 Logan 日志系統(tǒng),公司各研發(fā)團(tuán)隊(duì)已能夠盡早獲得完整的用戶端日志流及環(huán)境信息,幫助業(yè)務(wù)及時(shí)排查問題并響應(yīng)用戶反饋。
另外,在美團(tuán),Logan Web 除了提供上文介紹的技術(shù)實(shí)現(xiàn)之外,還利用美團(tuán)內(nèi)部的通用 JS 橋組件實(shí)現(xiàn)了與 Logan 客戶端日志的打通,如下圖流程所示:
這意味著在美團(tuán)現(xiàn)有的 App 環(huán)境(如美團(tuán) App、點(diǎn)評(píng) App 等)中運(yùn)行的 H5 頁面如果使用了 Logan Web,所記錄的日志會(huì)利用 JS 橋傳給 Logan 客戶端,與客戶端日志一起落地在 App 本地文件中。因此在美團(tuán)的 App 環(huán)境內(nèi)上報(bào)的日志流中可查看上下文連續(xù)的 Web 端日志與客戶端日志,日志分析平臺(tái)展示的某篇日志詳情示意圖如下:
5. Logan 開源進(jìn)展與未來規(guī)劃
在 Logan Web 開源前,我們?cè)诿缊F(tuán) Logan 開源技術(shù)交流群中進(jìn)行了開發(fā)者需求調(diào)研,依據(jù)收集到的建議,Logan Web 這次開源版本將支持 TypeScript,同時(shí)提供了本地日志的加密策略選擇。開源的代碼及使用文檔可在 Meituan-Dianping/Logan/WebSDK 倉庫下查閱,開發(fā)者也可以在項(xiàng)目中直接通過 npm 包引入的方式引入 logan-web。同時(shí) Logan Web 底層依賴的 idb-managed 也已在 GitHub 與 npm 倉庫開源。
隨著本次 Logan Web 同時(shí)開源的還有 Logan 服務(wù)端與 Logan 日志分析平臺(tái)的實(shí)現(xiàn),讀者可一并在 Logan 代碼倉庫 下找到相應(yīng)的代碼和使用文檔。客戶端 SDK 的實(shí)現(xiàn)博客可點(diǎn)擊參考:《美團(tuán)點(diǎn)評(píng)移動(dòng)端基礎(chǔ)日志庫——Logan》。
目前 Logan 已開源了客戶端 SDK、Web 端 SDK、服務(wù)端及日志分析平臺(tái),已經(jīng)為社區(qū)開發(fā)者們提供了初步完善的整套 Logan 日志系統(tǒng)實(shí)現(xiàn)。在未來我們將繼續(xù)優(yōu)化擴(kuò)展 Logan 能力,幫助開發(fā)者們?cè)诟鞫谁h(huán)境中,都能更快更早更方便地定位問題及排除異常。
6. 聯(lián)系我們
本次開源只是 Logan 貢獻(xiàn)社區(qū)的一小步,我們希望在未來 Logan 能夠?yàn)樯鐓^(qū)提供更完整可靠的大前端日志服務(wù),我們誠摯地歡迎開發(fā)者向我們提出寶貴的建議,與我們共建社區(qū)。您可以挑選以下方式向我們反饋建議和問題:
在 github.com/Meituan-Dianping/Logan 提交 PR 或者 Issue。
微信添加 MTDPtech03,該美團(tuán)助手可邀請(qǐng)您加入美團(tuán) Logan 開源技術(shù)交流微信群,或者回復(fù)您的建議。
郵件發(fā)送至 edp.bfe.opensource@meituan.com。
7. 作者簡介
孫懿,美團(tuán)點(diǎn)評(píng)基礎(chǔ)技術(shù)部前端技術(shù)中心資深工程師。
8. 招聘信息
美團(tuán)點(diǎn)評(píng)基礎(chǔ)技術(shù)部前端技術(shù)中心負(fù)責(zé)美團(tuán)云平臺(tái)運(yùn)維領(lǐng)域的前端基礎(chǔ)研發(fā)工作,包含前端監(jiān)控、日志系統(tǒng)、長連通信、運(yùn)維工具等基礎(chǔ)建設(shè)。歡迎各路英雄掃碼投遞簡歷,我們滿心期待您的加入。感興趣的同學(xué)可將簡歷投遞至:tech@meituan.com(郵件標(biāo)題注明:基礎(chǔ)技術(shù)部前端技術(shù)中心)。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的美团开源 Logan Web:前端日志在 Web 端的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。