2014/02/01

Android のログレベル使い分け

Android の Log には以下のようなログレベルが用意されていますが、その使い分けが明確に決まっているわけではありません。
  • Verbose
  • Debug
  • Info
  • Warn
  • Error
  • Assert
プロジェクトでルールが決まっている場合はそれに従えば良いのですが、個人の場合、使い分けに悩みます。
私も、しばらく試行錯誤してきたのですが、ある程度自分のルールが決まったので備忘録として書いておきます。また、そのうち変わるかもしれませんが。

Verbose

一時的なデバッグに使用。
例えば、以下のようにループ中のデータを確認したい場合等です。

        while ((buff = fileInputStream.read()) != -1) {
            Log.v(TAG, "read data " + buff);
            
            // Do something
        }

動作確認が終わった場合は、コードごと消してしまうのが前提。
このコードが残っていると、動作が非常に遅くなりますし、LogCat のバッファがあっという間に埋まってしまいます。
まさに Verbose (冗長)なログです。

リリースする前に検索をかけて Verbose を使用しているところが無いようにします。

Debug

名前のごとく、デバッグ用に使用します。
Verbose と違って定常的なデバッグログ出力用です。
自分(と内部構造に明るいメンバー)に動作状況がわかるような情報を提供します。
例えば、以下のように特定のメソッドが呼ばれたかどうかを観測するために使ったりします。

        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick");
                
                // Do something
            }
        });

リリース時、コードは残しますがログが出ないように細工します。(細工については後述)

Info

これもデバッグに必要な情報を出力するのに使用します。
Debug との違いは、そのプロダクトがライブラリだったと仮定し、ブラックボックスとして使っているユーザにも意味のある情報を提供するために使用する点です。
例えば、以下のように読み込んだファイルサイズを出力する等です。

        int size = 0;
        while ((buff = fileInputStream.read()) != -1) {
            // Do something
            size++;
        }
        Log.i(TAG, "The size of read file is " + size);

Debug との違いが微妙なので、判断が難しいこともありますが、あまり厳密に考えないのがポイントです。
リリース時、コードは残しますがログが出ないように細工します。(細工については後述)
ただし、ライブラリとして提供する場合は、ログを出しておく場合もあります。

Warn

本来、起こってはいけないが、場合によっては起こりえるエラーが発生した場合に使用します。
例えば、以下のようにファイルが存在しなかった場合等です。

        try {
            fileInputStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            Log.w(TAG, "File not found. : " + file, e);
        }

Warn は必然的に catch句の中に記述されることが多くなります。
余談ですが、catch句の中に記述されるログは上述のように Stack Trace も表示するようにしています。

リリース時、コードは残しますがログが出ないように細工します。(細工については後述)
ただし、ライブラリとして提供する場合は、ログを出しておく場合もあります。

Error

プログラムの構造上起こりえないエラーが発生した時に使用します。
例えば、先ほどの FileNotFoundException も、事前にそのファイルを生成することが保証されているのであれば、Error を使用します。

        if (!file.exists()) {
            // Do something
            return;
        }
        try {
            fileInputStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "File not found. : " + file, e);
        }

上記の例でも、ファイルの存在確認を行った直後に、別のプログラム等にファイルが消されたりすると Error が起こります。
そこまで考慮してプログラムを書いているのであれば、Warn を使用し、そのようなことを考慮していないのであれば Error とするわけです。
基本的には、自分が起こりえないと思っている、もしくは起こる可能性が限りなく低いと思っている事象に対して Error を使います。

Error は、リリース時にもログが出るようにしておきます。

Assert

基本的に使用しません。
このログレベルはシステムに重大な問題が起こった場合のものなので、一般プログラマが使用することは無いと思います。

ログが出ないように細工する件について

私はリリース時にログが出ないように細工をしています。
Java にはプリプロセッサが無いので、ログの出力を切り替えられるクラスを用意しています。
具体的には以下の様なクラスです。

ただ、実際はもっと簡単なテンプレートを用意して使っています。
というのも、個人的には、この手のクラスはライブラリ化するより、都度作った方が良いと思っているので。

2014/8/12 追記

0 件のコメント: