了解日誌記錄

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

日誌標準

由於在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-tags中的event.logtags文件中的條目。

本機日誌記錄

C/C++ 中的日誌記錄遵循syslog標準,其中syslog (2) 對應於控制printk緩衝區的 Linux 內核syslog ,而syslog (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 SLOGW

圖 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)。這包括以下詳細信息:

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

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

例如,雖然時區信息不被視為個人身份信息,但它確實提供了用戶大致位置的指示。

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