7
1

More than 1 year has passed since last update.

Amazon CloudWatch Logs でログを読むための手法メモ

Posted at

Amazon CloudWatch Logs でログを読むために学んだ手法をいくつかメモします。
あまり高度な機能は利用せず、ECS や Lambda をほぼデフォルト設定で使って出力されたログを調査するような想定です。

前提となる概念について

CloudWatch でログを読む際には「ログイベント」、「ログストリーム」、「ロググループ」の概念について意味を理解している必要があります。

下記のドキュメントを引用しつつ、ごく簡単に各概念を説明します。

ログイベント

ログイベントは、モニタリングされているアプリケーションまたはリソースによって記録されたアクティビティのレコードです。

ログイベント

AWS のコンソール画面ではこの画像のように表示されます。画像の各行がそれぞれログイベントです。

ログストリーム

ログストリームは、同じソースを共有する一連のログイベントです。

要するにログストリームとはログイベントが集まったもののようです。

ログストリーム

画像の各行が一つ一つのログストリームです。

ロググループ

ロググループは、保持、監視、アクセス制御について同じ設定を共有するログストリームのグループを定義します。

ロググループ

ロググループはログストリームの集まりです。画像の各行が一つ一つのロググループです。

まとめると 3 つの概念はLog eventsLog streamsLog groupsとなると思います。

CLI でログを読む

もちろんコンソール画面からでもログを読むことはできますが、CLI のほうが便利なときもあります。
AWS CLI の CloudWatch Logs 関連コマンドをいくつか紹介します。

  • 本稿はバージョン2.3.1で確認しています。
  • AWS CLI はデフォルトでは JSON で結果を出力します。しかし、JSON で出力されると人間には読みにくいです。そのため、--output textを指定して多少読みやすい形式で出力させています。
  • 必要な情報のみを取得するために--queryを指定してフィルタリングしています。このクエリは JMESPath という構文が使われています。jq で使うルールと似ていますが、少し違うものです。
  • Lambda のログストリーム名などは「$」が含まれることがあります。その場合適宜シングルクォーテーションで囲むなどしてください。(でないと変数展開しようとされます)

ロググループを一覧にする

aws logs describe-log-groups --query "logGroups[].[logGroupName]" --output text

ログストリームを一覧にする

--log-group-name の後ろに対象のロググループを指定します。

aws logs describe-log-streams --log-group-name /ecs/hello-spring --query "logStreams[].[logStreamName]" --output text

ロググループ、ログストリームを指定して読む

--log-group-name--log-stream-name を指定します。

aws logs get-log-events --log-group-name /ecs/hello-spring --log-stream-name ecs/minimal-spring/f4dd8cd7-0943-4a4f-b3b4-a13b7e5d9701 --query "events[].[message]" --output text

tail する

tail -fのように追記を追いかけて CloudWatch のログを読むこともできます。

aws logs tail --since 5m --format short --follow /ecs/hello-spring
  • --format shortすると TimeStamp などの表示が消え、見やすくなります。
  • since でその名の通りいつからのログを表示するか指定できます。デフォルトは 10 分です。

ログをファイルでダウンロードする

実は前述のget-log-eventsコマンドではあるログストリームのログをすべて取得できるとは限りません。
AWS CLI のドキュメントには

By default, this operation returns as many log events as can fit in a response size of 1MB (up to 10,000 log events).

とあり、最大 1MB、もしくは 10,000 ログイベントしか取得できないようです。しかし、目 grep したい、オンプレのログファイルに対して行っているようなシェル芸を実行したい、などといったときにログ全体が必要になることもあります。
この問題に直面する人は少なくないようで、検索するといくつかダウンロード方法を紹介するブログなどが見つかります。
Qiita だと例えば

がログをローカルにダウンロードする Python スクリプトに関する記事になっています。
この記事のPythonスクリプトを使うとログをダウンロードすることが可能です。

CloudWatch Logs Insights を使ったログの検索

ログを検索したい、と思った場合、AWS コンソール画面でも各ログストリームのページに「インベントをフィルター」というフォームがあり、ログを検索できるようになっています。
しかし、ログが多いと重すぎるのか結果がなかなか返ってこなかったり、返ってこなかったりと不便です。

このような場合に CloudWatch Logs Insights を使った検索が便利です。
ロググループに対して独自の文法によるクエリを発行できます。「インベントをフィルター」よりも動作が軽く、ログが多くてもきちんと結果が返ってきます。

CloudWatch Logs Insights

特定ワードで検索するなら下記のようなクエリをクエリ入力フォームに書きます。

fields @message,@logStream
| filter @message like "HikariPool-1"
| sort @timestamp
| limit 25

fieldsには取得して表示するフィールドを記載します。SQL の SELECT 句に近いです。
フィールドを複数にする場合は、

fields @message,@logStream

のようにカンマ区切りにします。
@messageはデフォルトで自動的に用意されるフィールドで「生の未解析のログイベント」を表します。(参考:サポートされるログと検出されるフィールド
要するに該当したログが表示されます。

filterはその名の通りフィルタリングを行います。高度な指定が可能らしいですが、grep したいだけならば非常にシンプルな判定のみで十分です。
想像できると思いますが、@message like "HikariPool-1"で部分文字列の一致のチェックを行っており、ログにHikariPool-1という文字列があれば対象となります。

sortはその名の通りソートします。SQL と同じように asc と desc を指定でき、デフォルトだと asc(昇順)になるようです。

limitも SQL と同じように返される結果の数を指定します。

「ロググループを選択」プルダウンでロググループを選択(複数可)し、「クエリの実行」ボタンを押下すると、例えば下記のような結果が取得できます。

クエリの実行結果

あるロググループ中でHikariPool-1という文字列を含むログイベントが検索できました。
画像だと fields@message だけを指定して実行していますが、@logStream も指定するとどのログストリームに所属するログイベントかも一目でわかる上に、クリックするとそのログストリームに遷移できるようにもなるため便利です。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1