聊聊前端日志库在 SaaS 产品中的应用与设计
文 | 元三 網易智企資深前端開發工程師
一、前言
筆者所在的公司業務主要是為企業提供全流程的企業服務和一整套 SaaS 解決方案。對于企業服務 SaaS 產品來說,客戶完成購買并不意味著產品價值已經完全交付,因為客戶在首次購買產品時,往往需要經過一系列培訓并使用后,才能真正產生價值。因此從本質上來看幫助客戶解決在使用過程中出現的問題是 B 端產品中提供的有償服務,是產品價值鏈條中非常重要的一環。
本文將著重介紹開發者排查客戶反饋問題這個場景下前端日志庫的應用,以及如何設計開發適用于此類場景的前端日志庫。
二、SaaS 業務下前端面臨的挑戰
筆者以前是做 C 端業務出身,天然帶著 C 端業務的思維,覺得前端把產品交互體驗做到極致就夠了。當我這個做法套用到做 SaaS 業務上,著實吃了不少虧。B 端產品和 C 端產品在付費方式的差異、購買決策人和實際使用者不同、產品用途不同(B 端客戶購買產品的根本原因是為了幫助企業賺錢,C 端產品購買決策有可能只是一時沖動好玩),導致 SaaS 企業經營關注的指標和 C 端產品存在較大差異,間接導致了對研發側的導向不同。C 端業務前端在研發資源投入上可能為了用戶體驗不計成本,優化網頁性能以提升用戶粘性,表現在移動互聯網、電商等行業往往關注 DAU、MAU、GMV 等量級指標。B 端產品的核心關注大部分能否幫助客戶提升效率,產品能否幫助客戶達成他的工作目標、能否幫他快速達成目標比產品界面是否美觀重要得多。衡量一家優秀的 SaaS 企業有一項比較重要的指標——NDR(收入留存率),對 SaaS 業務的前端開發來說,首要解決的挑戰來自如何通過軟件研發工作去提升產品易用性、任務效率、服務效率等指標,從而為企業帶來提高 NDR 的分子(存量客戶的續費+增購)的效果。
B 端和 C 端對比
| 用戶場景 | 清晰的目的,幫助企業提升效率和質量。 |
| 頁面交互方式 | 流程嚴謹、低風險、高效率 |
| 常見付費方式 | 按年預付 |
| 常用經營指標 | NDR、CAC |
值得一說的是,在這方面《云計算軟件產品使用體驗質量 度量模型及度量方法》也提出5項指標維度用于衡量產品使用體驗,非常具有參考性。這些指標維度包括易用性、任務效率、滿意度、一致性、頁面性能。其中易用性包括易操作性、易學性、清晰性,任務效率包括功能利用率、任務完成率、任務完成耗時。基于 SaaS 產品收入可持續性的考量,SaaS 企業的目標之一是提高依靠軟件產品輸出價值的比重,降低依靠人工服務輸出價值的比重,因為只有軟件產品輸出價值邊際成本最低,才能不斷提升產品服務效率。在這一點上,純粹依靠人工服務終歸是邊際成本非常高的,因此在 SaaS 業務場景下依靠技術創新去提升解決問題的效率是前端能夠提供的非常大的產品價值。
三、如何解決客戶反饋問題
當我們把視角聚集到客戶反饋問題的解決上時,可以先將客戶反饋問題分為功能咨詢類、問題報障類、售前咨詢類。其中開發者主要關注的是問題報障類,也存在一些技術支持回答不了的功能咨詢類問題會流向開發者,針對這類問題一般可以采用建設內部的問題排查系統來解決。其中前端開發者主要遇到的反饋問題既有來自于 SDK 接入這一類的咨詢,也有客戶認為產品功能不符合預期的問題報告。
針對此,前端為了有效且快速定位這些問題原因,一方面可以在客戶端打日志并上報到問題排查系統之中,另一方面,對于 S 類 A 類客戶(基于 SaaS 企業針對客戶企業規模的分層模型)的緊急問題,如有必要可以迅速和客戶溝通,使用遠程協助之類的工具在客戶的設備中復現并定位問題原因。對于后者,我們設計開發了基于 Chrome 瀏覽器 Chrome DevTools 協議的**遠程調試解決方案 woodpecker-remote,它能夠支持網站開發者對網站用戶的 Chrome 瀏覽器直接進行遠程調試。對于前者來說,我們設計開發了前端日志庫 **woodpecker-log 以支持將客戶端運行狀態等信息進行持久化存儲供開發者調試排查問題。
四、前端日志的概念
這里先介紹一下前端日志的概念。通常來說一般在后端開發時經常會聽到日志的概念,對后端來說日志是指一種用于記錄服務端啟動、運行狀態的文件。這里的前端日志指的也是用于記錄客戶端運行狀態在客戶端存儲或者上傳到服務器存儲形成的日志文件。一般前端在開發、測試環境使用 Console 記錄運行狀態就夠了,但在生產環境就需要將客戶端日志信息發送到服務端存儲起來,方便日后排查定位用戶反饋問題時使用。
五、傳統的前端日志存在的問題及挑戰
六、基于 B 端業務的前端日志庫設計
上述問題中,首要解決的是日志和用戶反饋問題相關度的問題。核心思路是使用客戶端進行日志存儲,在發生問題時由用戶或者程序發現進行主動上報,而不是定時定頻率上報到服務器。這里留兩個問題:用戶如何發現問題?程序(員)如何發現問題?另外,性能問題和JS異常也是產生客戶反饋的問題來源之一,但從日常SaaS業務的客戶反饋問題來源統計來看,這兩塊并不是主要來源。另外的JS異常監控、性能監控兩個領域已經有比較成熟的前端基建支持。因此,非JS異常和性能問題導致的客戶反饋問題是前端日志庫主要覆蓋并解決的問題。
6.1 一些典型的需要記錄前端日志的場景
首先在開始設計之前,先思考一下,前端會如何使用日志庫。有這些典型場景可能需要前端記錄日志。
對第3種場景,這里簡單列了在程序斷言為 false 時使用前端日志庫記錄日志的 Demo:
6.2 日志庫 SDK 的可維護性
相比于幾千行代碼在單一文件內維護,將 SDK 獨立成項目并采取前端工程化方式開發更具備可維護性。前端工程化是指采用模塊化、組件化、規范化、自動化的技術方案從軟件工程的角度解決工程的質量、可維護性問題。這里列舉了一些關鍵技術選型:
對于 SDK 相對底層的代碼來說,Typescript 語言天然提供的類型文檔具備可讀性和易讀性,靜態類型檢查可以幫助框架或庫的使用者在代碼運行階段之前發現錯誤,智能語法感知可以提供有用的 API 類型提示。
需要考慮為 SDK 的使用者提供多種 JS 模塊規范的支持,以 rollup 為例,配置如下:
在開發階段對 SDK 的自動化測試主要關注單元測試和集成測試。單元測試是用于對模塊、函數或類進行正確性檢驗,可以采用 jest 框架。值得注意的是,對 indexedDB 存儲和查詢進行單元測試時需要模擬數據庫,可以使用 fake-indexeddb 來 Mock。集成測試的目的是將系統之間的各個模塊組裝起來并使用真正的外部依賴、訪問真正的 indexedDB 數據庫對代碼進行正確性檢驗。此例中我們采用了 Karma + Mocha + chai 的方案,對 ChromeHeadless、FirefoxHeadless、Safari 瀏覽器進行測試。
基于語義化版本規范 semver 進行版本控制。
6.3 使用 indexedDB 在客戶端存儲日志
localStorage 適合對少量數據進行 key-value 存儲,在客戶端日志存儲的場景中使用 indexedDB 更加合適,它具備以下優點:
- 存儲和查詢結構化數據,支持二進制
- 支持事務
- 異步
- 處理大量數據
假定使用 10M 容量,300bytes 的日志,可以存 34952 條;最長支持循環錄制 8 天日均 **4369 **條。
6.4 性能開銷
- 網絡性能(延遲、請求失敗率)——日志長度、請求體積
- 使用獨立域名服務器處理日志請求 Chrome 對同一域名的并發最大連接數限制
- DNS 預獲取 dns-prefetch
- 日志存儲前進行字符串壓縮
- 使用基于 Gzip 算法的 JS 實現 LZMA-JS, 實測 Level6,300bytes,壓縮率79%
- sendBeacon
- 數據可靠異步傳輸,并且不會延遲頁面的卸載或影響下一導航的載入
- 合并請求
- 合并多個小體積的日志分頁上報,單頁約 1M
- HTTP/2 頭部壓縮
- 運行性能
- 全異步非阻塞式操作,存儲、檢索、上報
- 維護存儲隊列支持批量日志存儲操作
6.5 API 設計
SDK 初始化設置
| options.appKey | String | 實例記錄日志時會存儲的應用名稱,用于區分不同應用記錄的日志,不傳時實例使用 $anonymous 作為應用名 | $anonymous | 可選 |
| options.bytesQuota | Number | 設定客戶端可使用的 indexedDB 存儲上限,單位為 MBytes。不同應用共用存儲上限,超出上限后,將啟用循環記錄功能,自動刪除最早的日志 | 10 | 可選 |
| options.reportUrl | String | 傳入后 report 方法將使用該地址作為上報日志的服務器地址,如不傳,則需要在調用 report 時指定該參數 | – | 可選 |
| options.enableSendBeacon | Boolean | 開啟后使用 sendBeacon 上報日志 | FALSE | 可選 |
| options.debug | Boolean | 開啟后在客戶端 console 控制臺打印調試信息 | FALSE | 可選 |
實例方法
| trace/info/warn/error/fatal | 日志記錄到客戶端 | wpLog.trace(content: string); |
| queryByDate | 按發生時間檢索日志 | wpLog.queryByDate(startDate?: number, endDate?: number); |
| queryByContent | 按關鍵字檢索日志 | wpLog.queryByContent(content: string); |
| report | 日志上報到服務器 | wpLog.report(startDate?: number, days?: number, reportUrl?: string, session?: boolean, env?: boolean); |
6.6 線上出現問題,但是代碼中沒有打日志怎么辦
我們常常需要發布前就在代碼中設計好業務關鍵流程執行時需要打印的日志。否則,當我們需要定位問題的時候,才發現自己并沒有輸出相關的日志,這樣就會比較被動。此時只能臨時改代碼加日志,重新發布。有沒有一種方案,可以在遇到問題的時候,再去代碼中相應位置加日志,用戶執行改業務流程時就能立刻打印出相關日志,而不用重新走一遍發布流程。 這里介紹一種在 woodpecker-proxy 中的實現,借助 MutationObserver 接口監聽 script 插入 DOM 事件,改寫瀏覽器 JS 請求,將其代理到目標服務器,從而實現在目標服務器修改 JS 加入日志代碼即可在用戶瀏覽器記錄日志。Demo 地址:DEMO。
6.7 日志規范——分級別、分應用打印日志
遵循良好規范記錄的日志,有利于排查問題時能夠快速根據信息級別、應用進行日志篩選。
分級別
| trace | 主要輸出調試性質的內容。 |
| info | 記錄系統的正常運行狀態,某些重要的業務處理已經結束。 |
| warn | 發生這個級別問題時,處理過程可以繼續,但必須對這個問題給予額外關注。 |
| error | 錯誤發生時,已經影響了用戶的正常訪問,也需要馬上被處理,但是緊急程度要低于 FATAL 級別。 |
| fatal | 致命錯誤,系統中發生了非常嚴重的問題,必須馬上有人進行處理。 |
分應用
由于客戶端存儲受同源限制,日志訪問只能在自身域名下進行。多個應用可能會在同一域名下記錄日志,區分應用名進行存儲易于隔離不同應用的日志信息。
6.8 問題的上下文需要收集哪些信息
- 設備、瀏覽器、頁面信息
- 關聯一次會話的用戶界面交互操作
- 關聯一次會話的頁面跳轉
6.9 如何在收到客戶反饋時快速找到相關日志
七、未來努力的方向
- 加強可靠性
- 網頁崩潰時如何保障前端日志庫依然正常工作,記錄此時的日志?使用 Service Worker 監控網頁崩潰。
- 更直觀的問題上下文環境
- 采用瀏覽器錄屏方案錄制出現問題前后的用戶界面。
- 更友好的客戶通知和告警
- 使用 Notification桌 面通知。
八、參考資料
- 云計算軟件產品使用體驗質量 度量模型及度量方法
- 前端日志規范
- woodpecker-log
- woodpecker-remote
- woodpecker-proxy
總結
以上是生活随笔為你收集整理的聊聊前端日志库在 SaaS 产品中的应用与设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebRTC 系列之音频会话管理
- 下一篇: 打破传统降噪技术 看网易云信在语音降噪的