LoginSignup
8
4

More than 3 years have passed since last update.

CloudWatch LogsでAWSコンソールでfilterできない量のログをCLIでなんとかする

Last updated at Posted at 2019-08-30

こんな課題を解決したい

  • CloudWatch Logsでログを調査したい
  • 特にログ周りの整備や連携は進んでいないので、現状CloudWatch Logsだけでなんとかしている
  • 探したいおおまかな時間とキーワードはわかっている
  • AWS Console上でイベントのフィルターで時間とキーワードを指定して検索しようとする
  • ログが多すぎて、いつまで経っても結果が帰ってこない
  • 基本Lambdaのログを想定(他でも使えると思います)

これを、CLIとコマンドを組み合わせて、なんとか周辺のログを取得するお話です

モデルケース

  • 今回は、例えば以下のようなLambdaのログを仮定してみます
    • Lambda関数名: TestLambda
    • 取得したい時間: 2019/08/20 10:00 - 10:10 (1566262800000 - 1566263400000)
    • 検索したいキーワード: Error

その他条件

  • 1日分の該当LogGroupのログがDLできる規模であること
  • AWS CLI, jq が使えること

結論

先に利用したコマンドだけ記載するとこんな感じです。

# ログストリーム一覧取得
aws logs describe-log-streams --log-group-name '/aws/lambda/TestLambda' --log-stream-name-prefix '2019/08/20/[1234]' | jq '.logStreams | sort_by(.lastEventTimestamp)' | jq '.[] | select(.lastEventTimestamp > 1566263400000)| select(.firstEventTimestamp<1566262800000)' | grep -e logStreamName | cut -d '"' -f 4 > log-stream-list.txt

# ログストリーム一覧からログを取得
while read line; do aws logs get-log-events --log-group-name '/aws/lambda/TestLambda' --log-stream-name $line >> all.log; done < log-stream-list.txt

# ログの整形
cat all.log | jq '.events[]| select(.timestamp>1566262800000) | select(.timestamp<1566263400000)' > log_between_timestamp.log

上記コマンドの解説のようなもの

どういう経緯で上記コマンドになったのか、一応記載しておきます

CLIでDLしてみよう

  • AWSコンソールでうまくいかないなら、CLIを使おう
  • AWSコンソールでやろうとしたことをコマンドにするとこんな感じ?
    • aws logs filter-log-events --log-group-name '/aws/lambda/TestLambda' --start-time 1566262800000 --end-time 1566263400000 --filter-pattern 'Error'
  • 当たり前だがコンソールと同様のことをさせているので返ってこない・・・
  • LogStreamがわかれば、Stream名を指定すればすぐに落とせるんだけど・・・
    • e.g.) aws logs get-log-events --log-group-name '/aws/lambda/TestLambda' --log-stream-name '2019/08/20/[1234]dae4553dv12349gosjgoe2342qwahwks'
    • [version]まではわかっても、そのあとはわからないと思います

該当しそうなLogStream全部とる

今回の主題です。
大抵Streamがどれかはわからないので、当てはまりそうなStreamは全部取ってこようと思います。

Stream名の一覧を取得する

当てはまりそうなStream名がわからないと、結局get-log-eventsで取得できません。
Stream名の一覧を取得してみます。
firstEventTimestamp, lastEventTimestamp で絞り込めます。
jqのsort_byselectを使って絞ります。

aws logs describe-log-streams --log-group-name '/aws/lambda/TestLambda' --log-stream-name-prefix '2019/08/20/[1234]' | jq '.logStreams | sort_by(.lastEventTimestamp)' | jq '.[] | select(.lastEventTimestamp > 1566263400000)| select(.firstEventTimestamp<1566262800000)' | grep -e logStreamName | cut -d '"' -f 4 > log-stream-list.txt

リストを元に実際にログを取得する

以下のような感じで、対象のStreamからログ取得するコマンドをぐるぐる回して1つのログファイルを作ります。
1つにするのが大きそうなら、shellなどにして適宜ファイル分けるなり、整形したりしてください。

while read line; do aws logs get-log-events --log-group-name '/aws/lambda/TestLambda' --log-stream-name $line >> all.log; done < log-stream-list.txt

ログ内のメッセージを欲しい timestamp で絞る

基本的に、1つのLogStreamには、lastEventTimestampまでのログが入っており、開始時刻はわかりません。
目的の時刻よりはかなり多いはずなので、絞り込みます。

cat all.log | jq '.events[]| select(.timestamp>1566262800000) | select(.timestamp<1566263400000)' > log_between_timestamp.log

解析を行う

以上で目的の時刻間のログのみが取れたはずです。
あとは普通にgrep 'Error'などで探して、Hitした部分と同じRequestIDで処理を抽出して、同様にjqなどを駆使して解析できるはずです。

8
4
1

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
8
4