背景
これまで CloudWatch Logs に適当にログ出力していたアプリについて、検索しづらいなーと思ったので、なんかいい方法がないかと調べてみたところ、Insights という機能でもっと便利に検索できそうだったので試してみました。
これまでのやり方
特にいい方法を知らなかったので、「すべてのログストリームを検索」などで適当にフィルタリング条件を入力して絞るくらいでした。
(というかイマイチ使いづらいなーとは思いつつも、その他のサービスでは CloudWatch 外でログを管理していたので、そんなにしっかり使う機会もなくこれでとりあえずは事足りていた)
今回試してみた方法
サイドバーにある「ログのインサイト」というのを試してみました。
どうやらこれを使うと、クエリを実行して対象のログを抽出することができるらしいです。
そのためにはログを JSON 形式で出力しておくと都合がよいみたいでした。
AWS CLI を使ってログを出力する
アプリからは適当なテキスト形式で「とりあえず出しているだけ」状態だったので、いったんAWS CLIでログを書き出してみました。
エスケープなどの都合でシンプルに JSON 形式で書き出すのが難しかったので tempfile を挟む方法で出力しています。
# Create a temporary file
tempfile=$(mktemp)
# Write the JSON log event to the file
echo '[{"timestamp":'$(date +%s)000', "message":"{\"level\": \"info\", \"message\": \"Test message\", \"timestamp\": \"'$(date +%s)000'\"}"}]' > $tempfile
# Use the file as the parameter to the AWS CLI command
aws logs put-log-events \
--profile sample-dev \
--log-group-name "sample-log-group" \
--log-stream-name "i-12345678abcdefgh" \
--log-events file://$tempfile
CloudWatch Logs では以下のように確認できました。
{
"level": "info",
"message": "Test message",
"timestamp": "1691110540000"
}
次にこれを Insights で検索してみます。
Insights で検索
ロググループを選択した上でクエリを入力します。
クエリについては公式ドキュメントが参考になるかと思います。
(こちらの記事も参考になりそうです)
fields @timestamp, @message, @logStream, @log
| filter message = "Test message"
| sort @timestamp desc
| limit 20
まぁ雰囲気でだいたい分かるし書けるかなと思いますが、filter で WHERE 句を書ける感じですね。
これでクエリを実行すると以下のように先ほど出力したサンプルのログがヒットしました。
さきほどのログの JSON と見比べてもらうとわかりやすいんですが、JSON の key がフィールドとして認識されているので、それを検索条件として使える感じになっています。
@ つきのフィールドは AWS が用意してくれているもののようですね。
注意点
コスト
クエリの実行、というかクエリを実行してスキャンされるログの量に応じてコストがかかります。
コストについてはこちらの公式ドキュメントを参照ください。
スキャンしたデータ 1 GB あたり 0.005USD
これを見ると正直たかが知れているような気はしますが、今回は試し打ちしただけなので実際に稼働しているアプリケーションに対して実行するとどの程度のスキャン料になるかがよくわかっていないです。
そのへんは要チェックかなと思いました。
ネストした JSON は認識できない?
みたいなことを何処かで見たのですが見失ってしまったのでメモのみ。確認してないのですが。
なので JSON は可能ならばフラットな構造にしておくほうが良いかなと思いました。
そういう構造の場合は Athena を使うなど別の方法を選択することになるのかなと。
まとめ
CloudWatch Logs にログ出力する場合は形を決めて JSON 形式で出力しておくと Insights でクエリ実行して抽出できて便利そう。
これについてはもうちょっとちゃんと調べてみたいと思いました。