android日誌蒐集原理及方案比較

說明: 本文只討論Log日誌,而不是應用的埋點日誌。

Android 日誌架構

用一張圖來了解Android Log的架構:

這裏涉及到三個進程:

APP進程: 調用Log的接口打日誌,最終通過soctket通信發送給Logd進程
Logd進程:有一個緩衝區用於存儲日誌(環形緩衝區,當滿時會沖掉舊的日誌)
Logcat進程:可以在adb shell中創建(可以創建多個),查看緩衝區中日誌的進程(Android Studio的logcat也是一個Logcat進程)。

環形緩衝區是一個邏輯上的循環隊列,寫者可以往裏面寫東西,而一旦有內容會通知等待隊列裏的讀者們來讀取內容,否則等待隊列列處於阻塞狀態。 這就意味Logcat進程讀取也是阻塞形式的。

基於緩存的日誌方案

普通應用

  該方案會在系統的Log類上封裝一層,應用調用封裝層的日誌接口。封裝層將業務記得log緩存到一個StringBuffer中,當量達到一定閾值後,再刷到文件中。到達一定條件上傳到服務端。

基於緩存的日誌方案 對於普通應用:實現一套自己的Log,將每次打的日誌緩存

系統應用

在應用中開啓一起Logcat進程,不斷的讀取Logd進程中的日誌到緩存中,當日質量達到一定的閾值後再刷如文件。這種方案可以蒐集到所有應用的日誌。

缺點:

1. 寫文件 + 加密 會出現cpu峯值
2.崩潰或者進程意外退出 緩存中的日誌可能無法刷到文件中,關鍵崩潰信息可能丟失。
3. 對於智能設備中專門做一個日誌進程去搜集所有應用的日誌,這種方案其實是簡單可行的。

基於內存映射mmp的方案

mmp 原理:

內存映射,簡而言之就是將用戶空間的一段內存區域映射到內核空間,映射成功後,用戶對這段內存區域的修改可以直接反映到內核空間,同樣,內核空間對這段區域的修改也直接反映用戶空間。那麼對於內核空間<---->用戶空間兩者之間需要大量數據傳輸等操作的話效率是非常高的。

以下是一個把普遍文件映射到用戶空間的內存區域的示意圖。

系統層提供了具體的將用戶空間地址映射到內核空間的具體接口函數,這裏未作學習。

通過mmp讀取磁盤文件:

如果在拷貝數據時,發現物理內存不夠用,則會通過虛擬內存機制(swap)將暫時不用的物理頁面交換到硬盤上,上圖步驟4所示。這個過程也與內存映射無關。

通過系統read/write文件原理:

它首先將文件內容從硬盤拷貝到內核空間的一個緩衝區,如圖過程1,然後再將這些數據拷貝到用戶空間,如圖過程2,在這個過程中,實際上完成了 兩次數據拷貝 ;

而mmap()也是系統調用,mmap()中沒有進行數據拷貝,真正的數據拷貝是在缺頁中斷處理時進行的,由於mmap()將文件直接映射到用戶空間,所以中斷處理函數根據這個映射關係,直接將文件從硬盤拷貝到用戶空間,只進行了 一次數據拷貝 。因此,內存映射的效率要比read/write效率高。

mmp作爲日誌方案優勢

1.讀寫文件比普通文件操作效率更高
2.不會丟日誌(進程退出時能刷日誌到映射的地址中) 會寫日誌的時機: 內存不足 進程退出 調用 msync 或者 munmap 不設置 MAP_NOSYNC 情況下 30s-60s(僅限FreeBSD)
3. 對於CPU峯值問題,參考微信XLOG解決方案如下: 追加每行日誌時,先壓縮後加密(避免了對整個文件的壓縮/加密)

思考:
大多數用戶的日誌時無用的,日誌上傳場景考慮,通過指令撈取
具體日誌策略需要綜合多方面考慮: 流暢性/完整性/容錯性/安全性
MMP的具體使用還要結合具體場景,需要測試追加日誌大小
參考: https://blog.csdn.net/tencent_bugly/article/details/53157830 http://ju.outofmemory.cn/entry/224106 https://blog.csdn.net/coolwriter/article/details/80493166

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章