背景shell
持續快速交付線上版本而且保證質量、性能始終處於優良的狀態,是技術研發、項目管理團隊的永恆追求。隨着移動開發技術的成熟,產業競爭的加重,各大頭部App逐步平臺化、容器化,承擔着各自公司業務主要入口的使命。這不可避免地致使其自己逐步巨型化,與早期移動應用相比,複雜度明顯上升。小程序
除此以外,快速的迭代開發節奏,複雜的用戶環境(網絡、設備、場景等)、多樣的應用框架,這些都給移動端的開發和管理帶來了巨大的挑戰。 事實上,傳統的軟件危機在移動開發上也有必定程度的體現。在上述背景下,本文從移動端面臨的質量和效率的挑戰出發,結合愛奇藝App的具體狀況,介紹了愛奇藝技術團隊對這個問題的思考與實踐。後端
遇到的挑戰網絡
從 宏觀 上看,愛奇藝App這種巨型應用面臨的複雜度來源於多個方面:業務規模大:業務模塊多達幾十個,如何正確管理、隔離各模塊之間的耦合、衝突,避免錯誤和故障的擴散蔓延,是一個不小的挑戰;架構
開發人員規模大:上述模塊不少分散歸屬於不一樣的開發團隊,且開發集成周期並不徹底同步,這給集成發佈帶來了很大的複雜性;框架
技術形態繁雜:因爲業務的特色,各團隊/業務所選擇的技術棧不盡相同,Native,RN,H5,小程序,Flutter等多種形態並存;不一樣的跨端語言/技術並行,如JS、Lua、C/C++等,如何保證全部這些環境正確隔離,有序協做,須要考慮不少方面的問題;ide
迭代速度快:目前愛奇藝App保持着雙週發版的節奏,後端前置開發,客戶端一週開發+一週測試,在這種快速的迭代週期下,保持App總體可維護性、可測試性等質量標準良好,對研發架構、流程、工具都提出了新的要求。工具
從微觀上看,各業務模塊自身也不一樣程度地面臨着技術複雜、需求變更頻繁、歷史沉澱追溯困難等挑戰;在快速迭代過程當中大多數時候屬於行進過程當中換輪子的狀態,其自己代碼質量、功能質量也是一個須要持續關注的主題。性能
解決方案單元測試
綜合上述各方面的因素,多種複雜性和不肯定性的疊加給持續高質量交付帶來了巨大的挑戰。在這種狀況下,單純簡單依賴測試人力覆蓋來進行質量保證,既不經濟,也不現實,沒法持久保證產品的總體質量。
在調研了業界實踐狀況並結合愛奇藝的實際狀況,通過充分討論以後,咱們肯定了:自動化、規範化、主動化、系統化的治理思路。具體來講,採起了下面一系列的措施:
首先,對於流程相對固定的UI業務場景,構造自動化測試;對於UI業務庫接口,均要求配套相應的單元測試case並自動化運行,將測試人員從繁瑣的重複工做中解放出來,聚焦於更復雜多變的場景;此外,在移動端引入了代碼覆蓋率自動統計機制(支持真機/模擬器 覆蓋單次提交/總體App)。單次提交質量和測試覆蓋質量有了切實的數據評估,使得開發和測試對於改動的驗證有的放矢。 其次,考慮到自動化和人力測試只能發現已經引入的缺陷,而且成本很高,並但願將缺陷儘可能扼殺在編碼和調試階段,將成本降到最低。那麼,如何達到這個目標呢?首先觀念上你們要達成一致,通過討論,你們都認同「最終產品的質量,須要測試保證,更須要開發來保證」,觀念達成一致以後,還須要尋找有效的手段來達到最終目標。通過調研討論,認爲日誌是一個很好的切入途徑,理由在於:覆蓋面廣:統一的日誌系統可以覆蓋全部模塊,確保監控沒有死角;
信息詳實:日誌由開發人員添加,輸出該模塊主要流程的關鍵節點,感興趣的上下文和內部狀態等內容,信息量遠大於接口白盒測試,更不用說與黑盒測試比較了;
能持久化:日誌信息隨着模塊代碼一塊兒迭代演化,沉澱下來。具體實施過程當中,能夠分期按優先級逐步累積,其成果能持久化地利用;
覆蓋全流程:日誌信息覆蓋開發調試->測試->內測->外測->線上發佈的全流程,可以在各階段發揮其做用;
方便工具化、自動化:開發統一的日誌SDK,統一日誌格式和規則,使日誌方便使用、更加工具化。若是同時開發相應的配套工具,就可以在各階段將日誌的利用很大程度上自動化,提升效率,下降使用成本;
日誌SDK
日 志SDK集成在主App和獨立App中,爲各模塊中的關鍵節點提供日誌監控與跟蹤,目前已經覆蓋了主要模塊 。 除了日誌分級、分片存儲等基本功能以外,日誌SDK還提供了不一樣的過濾策略、不一樣的存儲介質、不一樣的上報策略以及雲控遠程配置功能。 爲了防止日誌過分累積,支持存儲容量限制、過時自動清理等功能,日誌系統的結構以下圖:支持日誌分級格式化後輸出到不一樣的目標,除了常規的console輸出、文件存儲、服務端上傳以外,還支持定向輸出至日誌調試器LogDebugger、Web查看器等,方便開發和測試人員使用。
配套工具集
日誌SDK只是爲監控和診斷等功能提供了必要的途徑,爲了將其充分利用起來,還須要開發配套的工具。 這些工具按運行平臺能夠分爲: 客戶端、桌面端、Web端; 按功能能夠大致分爲質量類和效率類兩大類:
日誌調試器
平時使用日誌時遇到的一個常見的問題是,IDE的console除了業務方的日誌輸出外,還混雜着大量的系統日誌輸出、第三方庫的日誌輸出等,這些無關信息會將有效信息徹底淹沒。篩選出感興趣的模塊日誌主要靠關鍵詞搜索,在不知道或者沒有統一關鍵詞的狀況下,開發和測試人員很難對該模塊的日誌輸出有全局和直觀的瞭解。爲了解決該問題,方便和鼓勵你們利用日誌診判定位問題,咱們開發了日誌調試器,經過client-server的結構互相鏈接,支持本地調試、交叉調試、內網遠程調試,統一日誌輸出管道,這有效避免了日誌信息淹沒、沒法有效提取的問題;同時還支持格式化顯示、按level、module、關鍵詞監控等功能。
啓動後,該工具會自動搜索發現局域網內的客戶端,分別顯示客戶端App名稱、版本、設備標識及鏈接狀態等信息,並自動維護鏈接狀態,以下圖:
若是某客戶端爲在線狀態,點擊鏈接後便可鏈接至該客戶端,創建鏈接後,該客戶端經過LogSDK發送的日誌,會實時顯示在調試器窗口中,以下圖所示: 日誌調試器支持對日誌分級別、分模塊、分關鍵詞等進行監控的功能,使用者能夠對按照指定條件篩選出的日誌進行導出發送。Web查看器
爲了方便相關人 員在開發、調試及內測階段能隨時有一種途徑獲取被調試客戶端的日誌及內部狀態等信息,開發了Web查看器。 Web查看器支持查看實時/非實時日誌,查看指定模塊調試信息等,以下圖是實時查看日誌的場景:
主動診斷/調試
爲了進一步提升調試效率以及應對復現機會稀少、甚至調試器自己可能會對被調試對象產生干擾(詳見海森伯效應、Heisenbug)等場景,咱們借鑑嵌入式開發的調試方法構造了一套主動診斷調試機制,其特色在於:化被動爲主動:單純的日誌輸出與分析,仍是相對被動,但願模塊級別能支持必定的主動調試功能,特別是對於內部複雜的強狀態模塊/業務;
非接觸式,甚至是在遠程調試,覆蓋開發、測試、發佈階段:具體來講,在開發和內測階段,提供遠程命令通道,開發人員能夠經過shell對App進行交互式調試,如更精準地拉取日誌、精準地獲取該客戶端A/B測試狀態、相關配置信息等,同時還能夠執行各模塊自定義的調試指令,以獲取其特定的調試信息;發佈階段,經過push token通道下發主動調試指令,獲取客戶端內部狀態信息,方便更精準定位問題,爲修復bug和改善體驗提供資料。
框架可擴展:具體來講,框架實現最經常使用的基礎調試指令,業務方能夠根據其具體狀況定義本身的擴展調試指令;
可調試的設計
上一節中提到了模塊的主動調試機制,爲何要引入主動調試?其背景在於高複雜度的軟件產品和快速的迭代節奏給可靠的測試和調試帶來了巨大的困難,化解這些難題的一種作法是在設計和開發階段,規劃好調試功能,未雨綢繆,化被動爲主動,這就是Design for Debug的思想,該思想最初來源於集成電路開發領域,後來被引入軟件領域並逐步獲得重視。
其實,寬泛一些來說,在移動開發中,大到整個App、小到某個模塊、某個接口等都應該在必定程度上考慮到可調試設計。固然這是一個很是大的主題,咱們目前實現的模塊主動調試功能只是初步在模塊層面實踐了其思想,還須要進一步探索。
總結
日誌系統貫通開發、調試、測試、發佈的全流程,是提升效率和質量的一個很好的抓手,本文介紹了愛奇藝技術團隊以其爲核心構建的綜合診斷調試系統及配套的相關工具。
此外還介紹了正在探索的主動診斷/調試功能的原理,更進一步地談到了關於可調試設計的思想,這個最初源於集成電路領域的概念,在軟件模塊愈來愈複雜的今天,對咱們有必定的啓發。固然關於可調試設計,咱們目前還處於早期探索階段,歡迎與業界朋友們進一步交流討論。
end