AndroidのlogcatをTerminalで

# IDEのLogcatViewerの不満

Logcatの定番Viewerといえば，Android StudioのLogcatViewerですよね．
でも，不満がありました

## 解像度が小さいサブディスプレイで扱いにくい

会社で支給されてるディスプレイ，サブディスプレイの解像度が小さいんです．
（いや，多分言えば買ってくれるんでしょうけど，どうせ置き場所もないし）

それは置いておいて，

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/fe70a5ce-4fce-d90d-9a3c-d80422ce917f.png)

フィルターのテキストエリア狭いよおおおお！！

ちなみにFullHDでもこの大きさ．たくさんフィルター掛けたい単語を並べるのもツライです．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/62b3fb15-dde7-096a-30c4-7d14aa790a5c.png)

## タブ化したい

LogcatViewer，タブ化したいって思ったことありませんか？
TAG1 と TAG2 と Warn以上でフィルタしたログを並べて見たい！！！という欲求．
Android StudioのLogcatViewerは複タブ化できません．
フィルターの条件を複数指定することはできますが，1つのViewに流れてしまいます．

# Terminalで解決してみる

`adb logcat` を Terminal で動かして解決しようと思います．

## Step1. 色を変える

adb logcat はそのまま出力しても全てのログレベルで文字色変わらないので， [Terminalで色付きadb logcat](https://qiita.com/fezrestia/items/bfd48decebe024bc9ba2) の記事を参考に `logcat_color.awk` を作りました．
Ubuntuターミナルのデフォルト背景は暗めの色なので，カラー指定だけ変えています．
（ちなみに，任意の色を指定する方法，だれかご存知でしたら教えてください．赤がまだ見難いです…）

```awk:logcat_color.awk
#!/usr/bin/awk -f

# adb logcat -v time
/^.* V\/.*$/ { print "\033[0m" $0 }
/^.* D\/.*$/ { print "\033[0;94m" $0 "\033[0m" }
/^.* I\/.*$/ { print "\033[0;92m" $0 "\033[0m" }
/^.* W\/.*$/ { print "\033[0;93m" $0 "\033[0m" }
/^.* E\/.*$/ { print "\033[0;91m" $0 "\033[0m" }
```

とりあえず， `adb logcat -v time | ~/bin/logcat_color.awk` とlogcatの出力をawkに流して色が付けば成功です．

## Step2. 複タブ化してみる

Ubuntuの場合， `gnome-terminal --tab` で新しいタブを開くことができます（ひとつ目のみ新しいWindow）
Terminalで `gnome-terminal --tab --tab` とするとこんな感じです

![名称未設定.png](https://qiita-image-store.s3.amazonaws.com/0/51949/ecfda76e-ae2c-923e-3594-704cf1a64e4f.png)


タブが2個開かれた状態でターミナルが開きます．

## Step3. 開いたタブでコマンドを実行する

`gnome-terminal` は -e オプションでコマンドを渡すことができます．
別タブで監視したいフィルターを書いた `adb logcat` コマンドを渡して，タブで動かします．

```bash
gnome-terminal \
--tab -e "sh -c 'adb logcat -v time WifiStateMachine:S VM_BMS:S ThermalEngine:S StatusBar:S QC-QMI:S | ~/bin/logcat_color.awk'" \
--tab -e "sh -c 'adb logcat -v time -s ActivityManager:* | ~/bin/logcat_color.awk'" \
--tab -e "sh -c 'adb logcat -v time *:W | ~/bin/logcat_color.awk'" \
```

上から，

- 指定タグを除いたログを表示
- ActivityManagerのログを表示
- Warn以上のログレベルを表示

です．

## Step4. bashスクリプト化

おおよそ取得したいログは決まっています．
毎回上を手打ちしたりコピペするのも面倒なので，bashスクリプトにまとめます．

```bash:~/bin/logcat.sh
#/bin/bash

exclude="WifiStateMachine:S VM_BMS:S ThermalEngine:S StatusBar:S QC-QMI:S" # ここに除外したいフィルター条件を並べる

gnome-terminal \
--tab -e "sh -c 'adb logcat -v time ${exclude} | ~/bin/logcat_color.awk'" \
--tab -e "sh -c 'adb logcat -v time -s ActivityManager:* | ~/bin/logcat_color.awk'" \
--tab -e "sh -c 'adb logcat -v time *:W | ~/bin/logcat_color.awk'" \
```

あとは好きなフィルター条件を書いて並べるだけです！

# まとめ

1タブ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/4c00b912-cb97-1a72-9c1d-7ce90628f0d8.png)

2タブ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/5f3fb8b2-836a-80e5-6faa-5a7338118d2a.png)

3タブ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/b699008f-06c7-ae83-f1d3-20595e342d6d.png)

# 改善余地

- タブのタイトルを変えたい
    - `gnome-terminal` の `--title` オプションがdeprecatedで使えなくなってた :sob:

- リンクやスタックトレースが見にくい
    - LogcatViewerだとオートリンクで色が変わったりしますからね

- スタックトレースからIDEの該当箇所に飛べない
    - これはどうしようもないですね

- 検索しにくい
    - とてもしにくい

# ここまで書いて

そう言えば [pidcat](https://github.com/JakeWharton/pidcat) というものが有ったことを思い出しました．
`sudo apt install pidcat` でインストールしたのですが，バージョンが古いのか一部コマンドオプションを渡すとエラーが出てしまいました．
GitHubから最新のPythonスクリプトを置き直したところ，エラーもなく見えるようになりました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/5b85bb7c-d0e7-2b3f-33e8-d77a4d68fae2.png)

デフォルトで十分見やすく， logcat_color.awk を通す必要も無いですが，やっぱりフィルターだけはどうにもなりませんね．

## 改行位置固定の問題

ただ，pidcatは実行したタイミングのターミナルウィンドウサイズを取得してその位置で改行を行うため，ウィンドウサイズを変更しても改行位置が変わってくれません．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/ff6b5373-a0e8-1841-b5fb-69ac63ec0582.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51949/82aec9f8-7110-2b0e-54d0-c9f4895045d5.png) ← ウィンドウサイズを変えても改行位置が変わらない

コードをちょっと読んだ所，やはりpidcatを呼び出した時点の [ウィンドウサイズを取得している箇所](https://github.com/JakeWharton/pidcat/blob/44b4a106bb25776cbb551044b303520a07a51c1e/pidcat.py#L85) がありました．

```python:pidcat.py
try:
  # Get the current terminal width
  import fcntl, termios, struct
  h, width = struct.unpack('hh', fcntl.ioctl(0, termios.TIOCGWINSZ, struct.pack('hh', 0, 0)))
except:
  pass
```

ここを関数化してあげて

```python:pidcat.py
def get_terminal_size():
  try:
    # Get the current terminal width
    import fcntl, termios, struct
    h, width = struct.unpack('hh', fcntl.ioctl(0, termios.TIOCGWINSZ, struct.pack('hh', 0, 0)))
  except:
    pass
```

indent_wrap() で呼び出してあげます

```python:pidcat.py
  def indent_wrap(message):
+   get_terminal_size()
    if width == -1:
      return message
    message = message.replace('\t', '    ')
    wrap_area = width - header_size
```

これで，TerminalWindowをグリグリ動かしても，ウィンドウの幅に応じて改行位置を変えてくれます．

## 複タブ化とフィルターはやっぱりbashで

ただ，結局フィルターしたいタグやログレベルは引数でつらつらと書き連ねなければいけないので，上と同様bash化してしまいます．

```bash:~/bin/logcat.sh
#/bin/bash

exclude="-i WifiStateMachine -i VM_BMS -i ThermalEngine -i StatusBar -i QC-QMI" # ここに除外したいフィルター条件を並べる

gnome-terminal \
--tab -e "sh -c 'pidcat.py ${exclude}'" \
--tab -e "sh -c 'pidcat.py -t ActivityManager'" \
--tab -e "sh -c 'pidcat.py -l W ${exclude}'" \
```

あと， [peco](https://github.com/peco/peco) と繋いでフィルタとかできると嬉しいんですが