瞭解記錄

本文將說明記錄程序,包括記錄標準、層級指南、類別、用途和多層架構近似值。

記錄標準

由於 Android 會在 logcat 中混合使用多種標準,因此記錄作業相當複雜。以下是主要使用的標準:

Source 範例 堆疊層級指南
RFC 5424 (syslog 標準) Linux 核心、許多 Unix 應用程式 核心、系統 Daemon
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 CONFIGFINE
- - 詳細訊息 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) 中的系統記錄

系統應用程式和服務可使用多個類別:

Class 目的
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 核心 syslog,而 syslog(3) 則對應至一般系統記錄器。Android 會使用 liblog 程式庫進行一般系統記錄。

liblog 會使用下列巨集形式為 sublogs 群組提供包裝函式:

[Sublog Buffer ID] LOG [Log Level ID]

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

包裝函式類別 範例函式
log_main.h ALOGVALOGW
log_radio.h RLOGDRLOGE
log_system.h SLOGISLOGW

圖 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
SEVERE Log.wtf
SEVERE Log.e

圖 9:標準 Java 記錄與 Android 記錄的錯誤層級。

在這種情況下,請使用個別標準來判斷要套用的等級。

在包含多個堆疊層級元件的系統開發期間,請按照圖 1 決定每個元件要使用的標準。如要瞭解訊息層級的概略指南,請參閱圖 2。

安全性和隱私權

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

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

同樣地,即使不是明確的個人識別資訊,某些詳細資料也可能會被視為敏感資訊。

舉例來說,雖然時區資訊不屬於個人識別資訊,但仍可用於判斷使用者的大概位置。

您必須在發布前,將記錄政策和可接受的詳細資料納入安全性和隱私權審查的一部分。

裝置記錄

所有裝置記錄的存取權 (包括使用 android.permission.READ_LOGS) 受到限制:

  • 如果背景中的應用程式要求存取所有裝置記錄,除非應用程式符合下列條件,否則系統會自動拒絕這類要求:
    • 共用系統 UID。
    • 使用原生系統程序 (UID < APP_UID)。
    • 使用 DropBoxManager
    • 僅存取事件記錄緩衝區。
    • 使用 EventLog API。
    • 使用檢測設備測試。
  • 如果前景中的應用程式使用 READ_LOGS 要求存取裝置記錄,系統會提示使用者核准或拒絕這類存取要求。