こんにちは!わたくし現在、カバー株式会社でサーバーサイドのエンジニアをしています。今回、カバーのアドベントカレンダーに参加させていただくことになりました。
さて、サーバーサイドの開発ではログの確認をすることが多いと思います。昨今はクラウド全盛なため、主にブラウザでマネジメントコンソールからログを見る機会が多いかもしれません。
ターミナルでログを見たい
私は昔から SSH でサーバーに接続し tail コマンドでログを見ることが長かったため、ターミナルでログを見たい気持ちが強いです。
しかしながら、ログが大量にある場合など、普通にログを取得するだけでは対象のログを検索するのが難しいことがあると思います。今回はそんな時に使えるちょっとした工夫をご紹介しようと思います。
AWS では CLI ツールが提供されており、CloudWatch のログをターミナルから取得することができます。これにより tail を使うのと同じようにログを追うことができます。
では、それらの中から特定の API やユーザーのログに検索をかけたい時どうしますか?通常であれば grep をかけたり、時間などである程度ログを絞った後でエディターで検索をかけたりするのではないでしょうか。でも、検索条件をある程度変えて過去何日分のログを追いかけたりするにはもどかしかったりしますよね。
fzf の出番です
そこで fzf を使用します。fzf はあいまい検索が行えるデータ検索・選択ツールです。シェルのコマンドライン履歴やファイル名の補完によく使われています。
特徴は、入力データのあいまい検索ができ、かつ、選択したデータのプレビューが行えることです。また、かなり大きなデータを読み込ませても動作が重くなりません。
本来は標準入力から取得したリストからデータを選択するツールですが、プレビュー機能を利用しログの検索・閲覧に使います。
導入
Mac では Homebrew、Windows では Winget を使うと一発で入りますのでおすすめです。他にも GitHub に各 OS ごとのバイナリが公開されていますので、そちらから入手することもできます。
本記事ではその他に AWS CLI を使うことを前提で紹介していきますが、ログを取得するツールなどは適宜必要に応じてインストールして下さい。
使ってみる!
それでは fzf を利用してログを読み込んでみます。と言っても単純で、パイプをつかって fzf にログのデータを渡してやるだけです…
aws logs tail awslogs-ecs-develop --since 1d --format short --follow | fzf --style full --no-sort --cycle --tac --track --tail=1000 --border rounded --preview-window wrap --preview "jq -C -S -r -n {2..} -R ""fromjson?"""
fzf には --tail というオプションがあり、これを指定すると、標準入力から渡されたデータが指定された行数に達した場合、データを古いものから順に破棄していきます。これによりログが標準入力から順次流れてくる場合でも、fzf はメモリを使い切ることなく検索を行うことができます。
fzf について調べてみると、ログの閲覧に使われている例を見ることがほぼないのですが、このオプションが用意されていることから、制作者の方もこのような利用のされかたを想定しているのだと思います。
また、上記の例では jq をプレビューのコマンドに指定しています。これは JSON のログを見たいときに有効で、JSON フォーマットのログも見やすく成形して表示することができます。
さて、このように fzf でログを見た場合、実際にどのように見えるでしょうか。fzf を利用していない時と比較していきましょう。
利用していない場合
普通にログを tail しているとこんな感じでしょうか。どんなアクセスがあるかをざっとつかむには十分ですが、それ以上のことを望むともどかしかったりしますよね。あ…例に使えるログが限られているため、多少の見づらさはご容赦ください…
- tail すると常に上に流れる…
- JSON だと要素を探しにくい…
- 検索できない…
といった点が不満になってきます。
利用すると…
fzf は CLI のツールなので GUI はないですが、プレビューの機能を使いターミナル画面でも見やすく出力することができます。また、メモリに読み込んだデータを高速に検索することができます。
- tail してても流れない!
- 選択しているデータをプレビューできる!
- jq を使って JSON でも綺麗に!
- 検索で絞れる!
↑が fzf を通すことにより可能になりました!
オプション
参考までに前述した fzf に指定しているオプションについて記載しておきます。
–style: 表示スタイル(default | minimal | full)
–no-sort: 検索した時にマッチ度でソートしない(入力順のままにする)
--cycle: 最後(最初)に達したら最初(最後)にカーソルを移動する
–tac: 入力されたデータを逆順で表示する
--track: 入力データが更新されてもカーソルを固定する
--tail=NUM: メモリに保持するデータ上限
--border: 表示する枠の指定(rounded | sharp | bold | block | thinblock | double | horizontal | vertical | top | bottom | left | right|line | none)
--preview-window: プレビューウィンドウの表示設定(up | down | left | right, [no]wrap, [no]cycle, [no]follow, [no]info, [no]hidden)
--preview: プレビューするときに使用する外部コマンド
fzf は環境変数 FZF_DEFAULT_OPTS にオプションを記述しておくことができます。デフォルトで指定しておきたいオプションはこの環境変数に設定しておくとよいでしょう。
まとめ
いかがでしたでしょうか…?ターミナルでログをリアルタイムに監視することはよくあることだと思います。fzf を使うことで検索をやり直したり、対象だけ抽出して見たいといったことが柔軟にできるようになります。さらに動作も軽量です。試しに30万行ほどのログを読み込ませてみましたが問題なく動作していました。
ログで fzf を利用している例を見かけなかったため、本記事で紹介させていただきました。皆さんのご参考になれば幸いです。

