聲網(wǎng)崩潰數(shù)據(jù)的自動(dòng)化閉環(huán)處理


01?崩潰信息的自動(dòng)化處理是趨勢(shì)
程序崩潰是由于發(fā)生某種嚴(yán)重錯(cuò)誤而導(dǎo)致程序無(wú)法繼續(xù)執(zhí)行下去,從而異常退出的現(xiàn)象,它是質(zhì)量保證過(guò)程中遇到最頻繁的問(wèn)題之一,通常這類問(wèn)題需要我們非常重視對(duì)待。當(dāng)用戶在使用你的 APP 遇到頻繁閃退或者崩潰時(shí),會(huì)造成大量用戶流失。
引起程序崩潰的原因有很多,通常是因?yàn)橐韵聨c(diǎn):
1. 程序邏輯問(wèn)題,發(fā)生了如數(shù)組越界、堆棧溢出、空指針異常等問(wèn)題;
2. 設(shè)備兼容性問(wèn)題,因?yàn)樵O(shè)備和系統(tǒng)的多樣性,特別是安卓系統(tǒng),可能達(dá)到上千種,很難做到完全的設(shè)備兼容;
3. 內(nèi)存管理錯(cuò)誤,程序內(nèi)部存在內(nèi)存泄漏問(wèn)題,長(zhǎng)時(shí)間的運(yùn)行和無(wú)法釋放對(duì)象的累積,導(dǎo)致了內(nèi)存溢出,最終發(fā)生程序崩潰;或者是程序所需要的運(yùn)行內(nèi)存超過(guò)了設(shè)備限制等。
現(xiàn)實(shí)生產(chǎn)過(guò)程中,因?yàn)槎喾N版本的迭代,可能會(huì)讓我們面對(duì)海量的崩潰數(shù)據(jù),需要對(duì)每一條數(shù)據(jù)逐個(gè)的去進(jìn)行人工校驗(yàn),篩選出重復(fù)問(wèn)題,保留有效數(shù)據(jù),并且提交 BUG 進(jìn)行跟蹤。不僅費(fèi)時(shí)費(fèi)力,效率低下,還很有可能會(huì)引發(fā)嚴(yán)重問(wèn)題的疏漏。所以建立一條便捷高效的自動(dòng)化的閉環(huán)處理流程十分必要。
02 常見(jiàn)解決方案的不足
以往常見(jiàn)的解決方案是集成騰訊的 Bugly SDK, 用來(lái)捕獲 Android 或者 iOS APP 中的崩潰信息。Bugly 提供了一套完整的崩潰信息監(jiān)控和解決方案。開(kāi)發(fā)者將移動(dòng)應(yīng)用集成 Bugly,然后通過(guò)崩潰監(jiān)控后臺(tái)服務(wù),可以方便的展示出用戶在使用 APP 過(guò)程中出現(xiàn)的崩潰/ANR 等問(wèn)題,并根據(jù)上報(bào)的崩潰信息快速定位和解決問(wèn)題。但是這種方案并不能應(yīng)用在桌面應(yīng)用上(Windows/Mac 等),而且 Bugly 目前也沒(méi)有開(kāi)放第三方接口,讓我們獲取崩潰數(shù)據(jù)列表以便于進(jìn)行自動(dòng)化分析處理。崩潰信息都要人工去進(jìn)行處理過(guò)濾,最終達(dá)到的效果并不能讓人滿意。
03 跨平臺(tái)的崩潰自動(dòng)化閉環(huán)處理方案
為了解決上述問(wèn)題,Agora 開(kāi)發(fā)了一套跨平臺(tái)(Android/iOS/Mac/Windows)的崩潰信息采集處理方案。當(dāng)發(fā)生崩潰的時(shí)候,Agora 的 SDK 會(huì)將相關(guān)信息(版本號(hào)、平臺(tái)、編譯號(hào)、崩潰偏移地址、符號(hào)表地址、DMP 文件鏈接等)提交到我們的后臺(tái)系統(tǒng),后臺(tái)通過(guò)綁定的堆棧信息和符號(hào)表進(jìn)行符號(hào)化,提取出地址和符號(hào)的對(duì)應(yīng)關(guān)系,進(jìn)而還原成開(kāi)發(fā)人員可以理解的崩潰堆棧信息。
符號(hào)化完成之后,系統(tǒng)會(huì)判斷當(dāng)前的 SDK 版本是不是已經(jīng)提交了相同問(wèn)題的 JIRA,如果沒(méi)有提交,就新增 JIRA。在新增 JIRA 的過(guò)程中還可以根據(jù)崩潰的模塊指派到對(duì)應(yīng)的負(fù)責(zé)人,比如最終定位到是 audio 模塊的崩潰,就指定到 audio 模塊開(kāi)發(fā)負(fù)責(zé)人,video 模塊的崩潰,就指定到 video 模塊的負(fù)責(zé)人,網(wǎng)絡(luò)模塊的崩潰,就指定到網(wǎng)絡(luò)模塊的負(fù)責(zé)人,優(yōu)化了手動(dòng)指派負(fù)責(zé)人的過(guò)程、大大提升了問(wèn)題處理的效率。如果當(dāng)前分析的結(jié)果是已經(jīng)提交過(guò) JIRA,則自動(dòng)關(guān)聯(lián)到相關(guān)的問(wèn)題上并更新對(duì)應(yīng)問(wèn)題的崩潰次數(shù)。整個(gè)處理的流程如下圖所示:

怎么區(qū)分一個(gè)版本相同的問(wèn)題是否提交過(guò)呢?目前有兩個(gè)維度,一個(gè)是通過(guò)編譯號(hào)和崩潰偏移地址確認(rèn),如果多個(gè)崩潰數(shù)據(jù)的編譯號(hào)和崩潰偏移地址是一致的,那么我們就將這幾個(gè)崩潰數(shù)據(jù)歸類為同一個(gè)問(wèn)題,提交 JIRA 的時(shí)候會(huì)匯總同一個(gè)問(wèn)題產(chǎn)生的次數(shù)。但是經(jīng)過(guò)一段時(shí)間的實(shí)踐,我們發(fā)現(xiàn)很多情況下同一個(gè)版本的編譯號(hào)和崩潰偏移地址不一致,但有可能是由于同一個(gè)問(wèn)題導(dǎo)致的。所以我們需要引入第二個(gè)維度,提取出堆棧詳情進(jìn)行分析。我們把能夠解析出來(lái)的行的信息拼接起來(lái),得到拼接字符串 Hash 值,然后根據(jù) Hash 值是否相同去進(jìn)行判斷,同樣的問(wèn)題是否已經(jīng)有過(guò)提交記錄。通過(guò)兩個(gè)維度的篩選,可以有效的去除重復(fù)問(wèn)題的 JIRA 提交,并且可以更有效的進(jìn)行崩潰數(shù)量的統(tǒng)計(jì)。其中我們可以制定一些不同的 Hash 生成方案來(lái)進(jìn)行重復(fù)崩潰問(wèn)題的過(guò)濾,可以通過(guò)最為寬松的方案,如通過(guò)最終崩潰的類名+方法名來(lái)生成 Hash;嚴(yán)格的方案如根據(jù)最終崩潰的文件名+模塊名+類名+方法名+參數(shù)名來(lái)生成 Hash。下圖是我們實(shí)踐過(guò)程中,通過(guò)自動(dòng)化解析崩潰數(shù)據(jù)提交的一個(gè) JIRA:

JIRA 中包含了當(dāng)前的版本號(hào)、編譯號(hào)、崩潰偏移地址、統(tǒng)計(jì)的崩潰次數(shù)、系統(tǒng)信息等。分析過(guò)程中還提取了崩潰堆棧中的關(guān)鍵信息,放在 JIRA 描述中,可以方便的讓開(kāi)發(fā)人員定位相關(guān)問(wèn)題。通過(guò)這種有效的篩選分析,我們可以把一個(gè)版本上萬(wàn)個(gè)崩潰數(shù)據(jù)匯總進(jìn)幾十個(gè) JIRA 里面, 大大提升了崩潰問(wèn)題的處理效率。
04 崩潰數(shù)據(jù)統(tǒng)計(jì)
平臺(tái)化地管理當(dāng)前發(fā)生的崩潰問(wèn)題,可以讓開(kāi)發(fā)/測(cè)試/項(xiàng)目管理者更方便地根據(jù)平臺(tái)、版本號(hào)、JIRA 狀態(tài)等信息來(lái)查找統(tǒng)計(jì)相關(guān)問(wèn)題:

我們還可以根據(jù)Hash匯總,快速地查看到在哪些版本發(fā)生了相同的問(wèn)題、發(fā)生的頻率如何,在以后的開(kāi)發(fā)過(guò)程中可以進(jìn)行更好的規(guī)避:

同時(shí)還可以定時(shí)記錄每日的崩潰數(shù)據(jù),獲取崩潰增量最高且未解決的 JIRA 進(jìn)行每日崩潰 Top10 告警,提醒相關(guān)開(kāi)發(fā)人員跟進(jìn)最高優(yōu)先級(jí)的問(wèn)題:

通過(guò)我們的自動(dòng)化實(shí)踐,提升了問(wèn)題解決的效率,減少了任務(wù)堆積和研發(fā)成本,在不斷提升代碼質(zhì)量的同時(shí)加速了版本迭代的速度,客觀上不斷提升了用戶體驗(yàn),為公司業(yè)務(wù)的發(fā)展不斷添磚加瓦。
Dev for Dev專欄介紹
Dev for Dev(Developer for Developer)是聲網(wǎng)Agora 與 RTC 開(kāi)發(fā)者社區(qū)共同發(fā)起的開(kāi)發(fā)者互動(dòng)創(chuàng)新實(shí)踐活動(dòng)。透過(guò)工程師視角的技術(shù)分享、交流碰撞、項(xiàng)目共建等多種形式,匯聚開(kāi)發(fā)者的力量,挖掘和傳遞最具價(jià)值的技術(shù)內(nèi)容和項(xiàng)目,全面釋放技術(shù)的創(chuàng)造力。