ロギングについて

この記事では、ログの規格、レベルのガイドライン、クラス、目的、マルチスタックのおおよその値を含む、ロギングのプロセスについて説明します。

ログの規格

さまざまな規格が使用され 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 CONFIGFINE
- - 詳細なメッセージ Log.v FINER / FINEST

図 2: syslog、Android、Java のロギングレベル

ログレベルのガイドライン

ログの規格にはそれぞれ既存のガイドラインがあります。カーネル開発には syslog 規格を使用するなど、選択されたログレベルは使用されている適切な規格に準じます。

ログレベルの順序(最小から最大まで)は、以下の 3 つの図のとおりです。

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

アプリケーション ロギング

以下に示すように、選択されたロギングは Log#isLoggable を使用する android.util.Log クラスによって 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 規格に準じており、printk バッファを制御する(2)Linux カーネル syslog に対応する syslog や(3)一般的なシステムロガーに対応する syslog があります。Android は、一般的なシステム ロギングに liblog ライブラリを使用しています。

liblog は、次のマクロ形式を使用してサブログ グループのラッパーを提供します。

[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 Google スタイル(glog)のロギングと同様に、ロギング用の C++ ストリーム インターフェースを提供するロギング ライブラリ。libbase は両方の外部プロジェクトで使用でき、libbase_ndk を使用するアプリケーションで使用できます。

図 8: 上位レベルのログライブラリ

マルチスタックのおおよその値

粒度とレベル インテントの違いがあるため、異なるロギング規格に明らかに、または完全に一致するものはありません。たとえば、エラーログの java.util.logging.Level レベルと android.util.Log レベルは 1 対 1 で対応しているわけではありません。

java.util.Logging.Level android.util.Log
SEVERE Log.wtf
SEVERE Log.e

図 9: 標準の Java ロギングと Android ロギングにおけるエラーレベル

このような場合は、個々の規格を使用して、適用するレベルを決定します。

複数のスタックレベルのコンポーネントでシステム開発を行う際は、図 1 に従って、コンポーネントごとに使用する規格を決定します。階層メッセージのおおよその値のガイドについては、図 2 に従ってください。

セキュリティとプライバシー

個人情報(PII)のログは記録しないでください。これには、次のような詳細情報が含まれます。

  • メールアドレス
  • 電話番号
  • 名前

同様に、特定の詳細情報は、明確に個人を特定できない場合でも機密と見なされます。

たとえば、タイムゾーン情報は個人を特定できるとは考えられませんが、ユーザーのおおよその位置情報を示します。

ログのポリシーと許可される詳細情報は、リリース前にセキュリティおよびプライバシーの審査の一環として処理する必要があります。