了解日誌記錄

本文介紹了日誌記錄的過程,包括日誌標準、等級指南、類別、用途和多堆疊近似值。

日誌標準

由於logcat中使用的混合標準,Android 中的日誌記錄非常複雜。所使用的主要標準詳述如下:

來源例子堆疊層級指導
RFC 5424syslog標準) Linux 內核,許多 Unix 應用程式核心、系統守護程式
android.util.Log Android框架+應用程式日誌記錄Android框架及系統應用
java.util.logging.Level Java 中的一般日誌記錄非系統應用

圖 1:日誌等級標準。

儘管這些標準中的每一個都具有相似的等級結構,但它們的粒度有所不同。各標準的近似等效項如下:

RFC 5424 級別RFC 5424 嚴重性RFC 5424 描述android.util.Log java.util.logging.Level
0緊急狀況系統無法使用Log.e / Log.wtf SEVERE
1警報必須立即採取行動Log.e / Log.wtf SEVERE
2批判的關鍵條件Log.e / Log.wtf SEVERE
3錯誤錯誤狀況Log.e SEVERE
4警告警告條件Log.w WARNING
5注意正常但顯著Log.w WARNING
6資訊訊息傳遞Log.i INFO
7偵錯偵錯級訊息Log.d CONFIG FINE
- -詳細訊息傳遞Log.v FINER / FINEST

圖 2: syslog 、Android 和 Java 日誌記錄等級。

日誌等級指南

每個日誌標準都有現有的指南。所選的日誌等級遵循所使用的適當標準,例如使用syslog標準進行核心開發。

日誌等級從低到高的順序如下三圖所示:

ERROR這些日誌始終保留。
WARN這些日誌始終保留。
INFO這些日誌始終保留。
DEBUG這些日誌會被編譯,但會在執行時被剝離。
VERBOSE除開發期間外,這些日誌永遠不會編譯到應用程式中。

圖 3: android.util.Log

CONFIG靜態配置訊息的訊息級別
FINE提供追蹤資訊的訊息級別
FINER表示相當詳細的追蹤訊息
FINEST表示非常詳細的追蹤訊息
INFO資訊性訊息的訊息級別
SEVERE指示嚴重故障的訊息級別
WARNING指示潛在問題的訊息級別

圖 4: java.util.Logging.Level

0緊急狀況系統無法使用
1警報必須立即採取行動
2批判的關鍵條件
3錯誤錯誤狀況
4警告警告條件
5注意正常但重要的情況
6資訊性資訊性訊息
7偵錯偵錯級訊息

圖 5: RFC 5424 - 第 6.2.1 節

應用程式日誌記錄

android.util.Log類別使用Log#isLoggable透過TAG執行選擇性日誌記錄,如下所示:

if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
 Log.v("FOO_TAG", "Message for logging.");
}

可以在運行時調整日誌以提供選擇的日誌記錄級別,如下所示:

adb shell setprop log.tag.FOO_TAG VERBOSE

log.tag.*屬性在重新啟動時重置。重新啟動後也存在一些持久的變體。請見下文:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

Log#isLoggable檢查會在應用程式程式碼中留下日誌痕跡。布林DEBUG標誌使用設定為false編譯器最佳化繞過日誌跟踪,如下所示:

private final static boolean DEBUG = false;

… If (DEBUG) { Log.v("FOO_TAG", "Extra debug logging."); }

R8可以在編譯時透過 ProGuard 規則集以每個 APK 為基礎刪除日誌記錄。以下範例刪除android.util.LogINFO等級日誌記錄以下的所有內容:

# This allows proguard to strip isLoggable() blocks containing only <=INFO log
# code from release builds.
-assumenosideeffects class android.util.Log {
  static *** i(...);
  static *** d(...);
  static *** v(...);
  static *** isLoggable(...);
}
-maximumremovedandroidloglevel 4

這對於處理多個應用程式建置類型(例如,開發建置與發佈建置)非常有用,其中底層程式碼預計相同,但允許的日誌等級不同。必須為應用程式(特別是系統應用程式)設定並遵循明確的策略,以決定建置類型和發布期望如何影響日誌輸出。

Android 運行時 (ART) 中的系統日誌記錄

有幾個可用的類別可用於系統應用程式和服務:

班級目的
android.telephony.Rlog無線電記錄
android.util.Log一般應用程式日誌記錄
android.util.EventLog系統整合商診斷事件記錄
android.util.Slog平台框架日誌記錄

圖 6:可用的系統日誌類別和用途。

雖然android.util.Logandroid.util.Slog使用相同的日誌等級標準, Slog是一個只能由平台使用的@hide類別。 EventLog等級對應到/system/etc/event-log-tagsevent.logtags檔案中的條目。

本機日誌記錄

C/C++中的日誌記錄遵循syslog標準, syslog (2)對應控制printk緩衝區的Linux核心syslogsyslog (3)對應通用系統記錄器。 Android 使用liblog庫進行一般系統日誌記錄。

liblog使用以下巨集形式為子日誌組提供包裝器:

[Sublog Buffer ID] LOG [Log Level ID]

例如, RLOGD對應到[Radio log buffer ID] LOG [Debug Level] 。主要的liblog包裝器如下:

包裝類範例函數
log_main.h ALOGV , ALOGW
log_radio.h RLOGD RLOGE
log_system.h SLOGI

圖 7: liblog包裝器。

Android 具有更高級別的日誌記錄接口,比直接使用liblog更受青睞,如下所示:

圖書館用法
async_safe僅用於從非同步訊號安全環境進行日誌記錄的庫
libbase日誌記錄庫提供 C++ 日誌記錄流接口,類似於 Google 風格 (glog) 日誌記錄。 libbase可在外部專案中使用,並且可在使用libbase_ndk應用程式中使用。

圖 8:更高等級的日誌庫。

多堆疊近似

由於粒度和等級意圖的差異,不同的日誌標準沒有明確或精確的匹配。例如,錯誤日誌的java.util.logging.Levelandroid.util.Log等級不是 1:1 匹配:

java.util.Logging.Level android.util.Log
劇烈Log.wtf
劇烈Log.e

圖 9:標準 Java 日誌記錄與 Android 日誌記錄中的錯誤等級。

在這種情況下,請使用單獨的標準來確定要應用哪個等級。

在使用多個堆疊層級元件進行系統開發期間,請依照圖 1 確定每個元件使用哪個標準。有關層訊息傳遞的大致指南,請參閱圖 2。

安全和隱私

請勿記錄個人識別資訊 (PII)。這包括以下詳細資訊:

  • 電子郵件地址
  • 電話號碼
  • 名稱

同樣,某些細節即使沒有明確的個人身份,也被視為敏感。

例如,儘管時區資訊不被視為個人識別訊息,但它確實可以指示使用者的大致位置。

日誌政策和可接受的詳細資訊必須作為發布前安全和隱私審查的一部分進行處理。

設備日誌

對所有裝置日誌的存取(包括使用android.permission.READ_LOGS受到限制:

  • 如果後台應用程式要求存取所有裝置日誌,則該請求將自動拒絕,除非該應用程式:
    • 共用系統 UID。
    • 使用本機系統進程 ( UID < APP_UID )。
    • 使用DropBoxManager
    • 僅存取事件日誌緩衝區。
    • 使用EventLog API。
    • 使用儀器測試。
  • 如果前台有READ_LOGS的應用程式要求存取裝置日誌,系統會提示使用者批准或拒絕該存取要求。