こんな課題を解決したい
- CloudWatch Logsでログを調査したい
- 特にログ周りの整備や連携は進んでいないので、現状CloudWatch Logsだけでなんとかしている
- 探したいおおまかな時間とキーワードはわかっている
- AWS Console上でイベントのフィルターで時間とキーワードを指定して検索しようとする
- ログが多すぎて、いつまで経っても結果が帰ってこない
- 基本Lambdaのログを想定(他でも使えると思います)
これを、CLIとコマンドを組み合わせて、なんとか周辺のログを取得するお話です
モデルケース
- 今回は、例えば以下のようなLambdaのログを仮定してみます
- Lambda関数名:
TestLambda
- 取得したい時間:
2019/08/20 10:00 - 10:10
(1566262800000 - 1566263400000)
- 検索したいキーワード:
Error
- Lambda関数名:
その他条件
- 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]まではわかっても、そのあとはわからないと思います
- e.g.)
該当しそうなLogStream全部とる
今回の主題です。
大抵Streamがどれかはわからないので、当てはまりそうなStreamは全部取ってこようと思います。
Stream名の一覧を取得する
当てはまりそうなStream名がわからないと、結局get-log-events
で取得できません。
Stream名の一覧を取得してみます。
firstEventTimestamp
, lastEventTimestamp
で絞り込めます。
jqのsort_by
とselect
を使って絞ります。
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
などを駆使して解析できるはずです。