移動端堆棧關鍵行定位的新思路

阿里雲 雲原生應用研發平臺EMAS 張月(此間)

一、前言

崩潰堆棧是我們日常應用問題排查中的重要輔助手段,在移動開發上也不例外,爲了支持用戶在堆棧上的快速定位,我們面臨一個看似比較簡單問題:高亮崩潰中的關鍵行, 輔助用戶快速定位問題。

崩潰堆棧關鍵行: 堆棧中是屬於用戶開發代碼中那行直接引起崩潰的代碼。

舉個例子:
在這裏插入圖片描述

二、 業界方案

業界的競品基本上是通過 Package Name判斷的,在沒有 Package Name 的情況下,有的競品會定位到第一行,有的則會定位到非系統庫的第一行。

例如: 友商這種情況下就將關鍵行掛在了第一行 fastjson 的位置。
在這裏插入圖片描述

這裏容易出現兩個問題:

  • Package Name 大多數時候和真正的崩潰包名關係不大。
  • App 組件化,包名不能覆蓋一方庫,二方庫。

爲了更好的解決這個問題,我們提出了下面用詞頻比/詞頻分的方式來解決問題的新方案。

三、新方案

所以在 Package Name 的基礎上,我們還需要一個輔助手段,讓我們能夠識別這兩種情況,從而在關鍵行定位更精準。

這裏我們想到的一個做法就是利用全量的 Crash 崩潰堆棧,計算詞頻比和相應的詞頻分,通過概率去優化我們的關鍵行判斷。

實現上分爲兩個平臺。

3.1 對於 iOS

1)主包判斷

這個問題,對於 iOS,其實不用考慮用戶填寫的 Bundle ID, 因爲 IOS Crash 天然就自帶 Binary Images,我們將用戶主包信息預存下來,用於後續判斷就行了。

Binary Images
在這裏插入圖片描述

2)直接定位:

在這裏插入圖片描述

對於組件化的包,我們可以通過 Binary Images 裏面的信息統計一下每個包名出現的頻率,具體的頻率分佈統計大致如下圖所示,縱座標代表包名出現的次數:

注:橫座標爲包名(這裏放不下),縱座標爲包名出現次數
在這裏插入圖片描述

出現的頻率越低,那麼我們越認爲他是一方庫或者二方庫。

3.2 對於 Android

對於 Android,情況稍微複雜一點,首先 Android 的 Crash 中其實是不能明確標識包名的,而且 Android 的 Package Name 並不是一個詞,而是一長串的以點分隔的包名, 例如

「com.aliyun.emasha.cache」。

如果單純的還以包名的詞頻比來做匹配的話,那麼就會出現下面的問題

  • 歷史數據 只出現 com.aliyun.emasha.cache 的包名, 下次出現個 com.aliyun.emasha.login 的就匹配不上了。
  • 同樣是 com.aliyun.emasha 的前綴,匹配到了 com.aliyun.emasha 和匹配到了 com.aliyun.emasha.cache 包名的詞頻相差很大,不符合常理。

所以還要解決這兩個問題

  • 能夠儘可能的覆蓋未出現的崩潰情況。
  • 隨着匹配的前綴越長,需要考慮前面的包名匹配帶來的影響。

所以這裏要引入包名分級和詞頻分的概念

  • 包名分級:將包名 split(".") 得到數組,從前往後爲 1級,2級,3級這樣的分級。
  • 包名詞頻分:根據包的詞頻比多級累加算出來的一個評價包名是否是三方庫的分數,分數越高,是三方庫的機率越大。

但這還不夠,如果我們的詞頻比只是單純的累加,那麼 com 開頭的的包名,詞頻分一定會很高,大於所有的 org 開頭的包名,但根據我們的經驗,其實不是這樣的,我們認爲不同級別的匹配,權重應該是不一樣的,所以我就拍腦袋想了個權重。

0 5 2 1 1 1

這裏舉個例子

com.alibaba.aliyun.emas.ha.tlog 這個包名
com 1
com.alibaba 0.3
com.alibaba.aliyun 0.1
com.alibaba.aliyun.emas 0.05
com.alibaba.aliyun.emas.ha 0.02
com.alibaba.aliyun.emas.ha.tlog 0.01
如果匹配到 com 那麼詞頻分爲 1 * 0
如果匹配到 com.alibaba 那麼詞頻分爲 1 0 + 0.3 5 = 1.5
如果匹配到 com.alibaba.aliyun 那麼詞頻分爲 1 0 + 0.3 5 + 0.1 * 2 = 1.7

以此類推

但是在我們的經驗中匹配到了 com.alibaba 和匹配到了 com.alibaba.aliyun,後者更有可能是關鍵行,所以它的詞頻分按理來說也就更低。所以我們這裏做一個符合常理的修正,對於位數過短的匹配,需要後幾位的權重做補齊。

最終結果如下:
如果匹配到 com 那麼詞頻分爲 1 0 + 1 5 + 1 2 + 1 1 + 1 1 + 1 1 = 10
如果匹配到 com.alibaba 那麼詞頻分爲 1 0 + 0.3 5 + 0.3 2 + 0.3 1 + 0.3 1 + 0.3 1 = 3
如果匹配到 com.alibaba.aliyun 那麼詞頻分爲 1 0 + 0.3 5 + 0.1 2 + 0.1 1 + 0.1 1 + 0.1 1 = 2

看上去是比較符合我們的經驗的。

所以這裏詞頻分的最終定義:根據包的詞頻多級累加算出來的一個評價包名是否是三方庫的分數,分數越高,是三方庫的機率越大。如果一個包名分級過短,需要把缺失的後面分級的也算上累加,用於增大短包名的詞頻分。

我們對所有的包做一個詞頻分統計,可以得到如下分佈圖

注:橫座標爲包名(這裏放不下),縱座標爲包名的詞頻分
在這裏插入圖片描述

根據觀察和測試,這裏把閾值定在 0.2 左右比較能區分用戶的包名和三方、系統庫。

3.3 整體架構

在工程實現上我們也做了一些優化

  • 以前業務數據是存儲在 OSS 中的,但是 EMR-OSS 目前文件處理較慢,這裏換成了更適合並行處理的 HBase。
  • 只計算增量 Crash 日誌, 對於存量的數據,以 HyperLogLog 的形式存儲,增量計算後與存量做 Merge。
    在這裏插入圖片描述

四、效果評估

常規的利用 Package Name 做判定: F1 Score
在這裏插入圖片描述

使用詞頻分思路的:F1 Score
在這裏插入圖片描述

五、真實效果評估

上面的效果評估只考慮到了每一個包名的情況,在生產因素下,考慮到崩潰行出現的位置,包名出現的頻率,以及沒關鍵行的情況,準確率可能會有所不同,所以我們在真實環境做了高亮測試,測試方式爲:對線上50個 App,每個 App 取前3條崩潰來做統計,總的準確率如下,可以說是比較高的。

安卓準確率:(333-9)/(333)*100%=90.91%
iOS準確率:(173-0)/(173)*100%=100%
總體準確率:(503-9)/(503)*100%=94%

六、思考

小需求可以做出大深度, 後續我們可以考慮更多跨用戶數據的脫敏拉通,理解數據,爲客戶帶來更多的數據價值。

七、接下來的方向

  • 組內算法的朋友說可以通過打標 + CNN 的方式來做深度學習下的三方包名判斷, 這個後續可以試一試。
  • 對於憑經驗拍腦袋相出來的參數和方程(詞頻分計算),其實都可以通過打標訓練的方式做參數和方程的固定,這也是一個優化方向。

八、寫在最後

移動研發平臺 EMAS

阿里巴巴應用研發平臺 EMAS 是國內領先的雲原生應用研發平臺(移動App、H5應用、小程序、Web應用等),基於廣泛的雲原生技術(Backend as a Service、Serverless、DevOps、低代碼等),致力於爲企業、開發者提供一站式的應用研發管理服務,涵蓋開發、測試、運維、運營等應用全生命週期。 歡迎大家移步使用:https://cn.aliyun.com/product/emas