AndroidのLogとTimberについて

### AndroidのLogとTimberについて
Android開発をしている際にLogを用いてデバックや値の確認をする人が多いと思います。今回、普段使っているLogについてもっと使いやすい方法はないのだろうかと思い調査をしてまとめました。そこでTimberというライブラリを知ったのでTimberについてもまとめました。

### Logについて
まずLogはClassとして定義されていてLogを出力するAPIを提供しています。その中にも様々なmethodが存在しています。そしてLogには優先度というものが存在しています。優先度の高い順番に記載をすると以下のようになります。

| Log Type | 意味 |
|:---------|------|
|e|error エラー|
|w|warn 警告　
|i|info 情報
|d|debug デバック|
|v|Verbose*1 詳細|

*1 verbose : 口数が多いなど意味があり詳細を表しています。

#### コードでの利用方法
実際のコード上では以下のような形式で記載されます。

```kotlin
Log.e("MainActivity", "This is Erroer")
Log.i("MainActivity", "This is Info")
```
まず最初の"MainActivity"の部分はtagです。ここで指定をしておくことによってこの後でLogをチェックする際に楽にLogを見つけ出すことが出来ます!!そしてその後ろの部分が実際のLogのメッセージになります。

### Logの確認方法
実際にコード上にLogを仕込んだあとで、アプリを動かしている際にどこでチェックをするのかというとAndroid Studio上にあるLogcatで確認をします。ここに設定をしたLogが表示されていきます。

この中から特定のLogを検索する際に先ほどのTagを利用すると便利になります。
画像のMainと入力されている場所にI/MainActivityやE/MainActivityとログレベルとタグを入力すると指定したLogを表示することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199067/c8872450-4c24-4dc1-c979-fd68e6067a54.png)


I/MainActivityで検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199067/f21e03f7-3131-6f60-ae1a-49a0d836ca1f.png)

E/MainActivityで検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199067/759845af-4256-9a4f-c8a8-184434f111a1.png)

### Timber
今まで説明していたのはLogクラスを利用したLogの表示方法でした。タグの記載とメッセージの記載両方を行う必要があり少し手間がかかると思います。TimberというLogライブラリを利用するとLogのタグ（先ほどのMainActivity）を自動で設定してくれます。

### Timberの導入方法
#### 1. Gradleの更新
まずGradleにTimberを追加します。以下のような記載になると思います。

```gradle
dependencies {
   ...
   implementation 'com.jakewharton.timber:timber:4.7.1'
}
```

バージョンに関してはこのリポジトリで確認できるはずです。

https://github.com/JakeWharton/timber

#### 2. Applicationクラスを継承したクラスの生成
今回の場合はApplicationクラス自体を変更するのではなくApplicationクラスのサブクラスを作成して対応しました。（ここの対応方法についてはAndroid CodelabのLifeCycles and loggingを参考にしました。）
以下のようなクラスを作成します。

```kotlin
class SampleApplication : Application() {
    override fun onCreate() {
        super.onCreate() 

        Timber.plant(Timber.DebugTree())
    }
}
```

そしてクラスを作成したらAndroidManifest.xmlの<application>を編集します。
```xml
<application
    android:name = ".SampleApplication"
```

#### 3. Timberの利用
ここまで設定をし終わるとコード上でもTimberを利用することが出来ます。利用方法としてはLogと同じく以下のようなコードを記載します。以下のように記載することでLogと同様にLogcatでログレベル/クラス名で検索を行うことが出来るようになります。

```kotlin
Timber.e("This is Error")
Timber.i("This is Info")
```

#### 4. Timberの便利な機能
TimberにはLintが搭載されているため、Timberの誤った記載にはエラーが出るようになっています。今回はそれらのLintに関してもLogと比較しながら記載していきます。TimberのリポジトリのREADME.mdからよく使いそうなものを抜粋しました。

##### TimberArgCount (Error)
Timberでは引数に%sなどを利用して引数に変数を利用することが出来ます。その際に引数の数が正しくないことをエラーとして表示することが出来ます。

```kotlin
val firstName = "Ryo"
Timber.i("Hello %s %s!", firstName) //ここがエラー表示!!
//Wrong argument count, format string Hello %s %s! requires 2 but format call supplies 1
Log.i("MainActivity", String.format("Hello, %s", firstName)) //Logでエラーを出さないように表示をする場合
```

##### TimberArgTypes (Error)
指定された書式文字列に対して誤った型の引数を検知してエラー表示をしてくれます。
```kotlin
val firstName = "Ryo"
Timber.i("Hello %b!", firstName) 
//Wrong argument type for formatting argument '#1' in Hello %b!: conversion is 'b', received String (argument #2 in method call)
```

##### TimberTagLength (Error)
tagの最大の長さとして決められている23文字以上になるとエラーを表示してくれます。

```kotlin
val firstName = "Ryo"
Timber.tag("TagNameThatIsReallyReallyReallyLong").i("Hello %s!", firstName) 
//The logging tag can be at most 23 characters, was 35 (TagNameThatIsReallyReallyReallyLong)

Log.i("TagNameThatIsReallyReallyReallyLong", String.format("Hello, %s", firstName)) //Logの場合も同様なエラー
//The logging tag can be at most 23 characters, was 35 (TagNameThatIsReallyReallyReallyLong)
```

##### LogNotTimber (Warning)
Logの利用を検知してTimberを使うようにという警告を出してくれます。

```kotlin 
val firstName = "Ryo"
Log.i("MainActicity", String.format("Hello, %s", firstName))
//Using 'Log' instead of 'Timber'
```

##### BinaryOperationInTimber (Warning)
Timberでは、string型の変数を連結する際に+を用いようとすると警告がでるようになっています。%sなどの書式文字列を利用することが推奨されいます。

```kotlin
val firstName = "Ryo"
val lastName = "Test"
Timber.i("Hello " + firstName + " " + lastName + "!")
//Replace String concatenation with Timber's string formatting
```

### まとめ
- 普段使っているLogにもログレベルというものが存在している。
- それらを使い分けてかつ検索の際にも指定して検索を行うことが出来る。
- Timberを利用することによって、Logを書くたびにタグを記載する必要がなくなる。
- TimberにはLintが存在していてかつ書式文字列も利用することが出来るのでコードの可読性も向上する。

### 参考資料
Logクラスについて

https://developer.android.com/reference/kotlin/android/util/Log

Logcatを使用してログの書き込み、表示を行う

https://developer.android.com/studio/debug/am-logcat

Lifecycles and Loggin (Android Codelab)

https://developer.android.com/codelabs/kotlin-android-training-lifecycles-logging?index=..%2F..android-kotlin-fundamentals#3

Timberのリポジトリ

https://github.com/JakeWharton/timber