AWS Lambda 関数開発をしてると CloudWatch ログを参照することが多いので、書いたスクリプトを備忘録的に公開。
CloudWatch ログは、ロググループ→ログストリーム→ログレコード という階層構造になっており、Web コンソールからログレコードを参照する場合はいちいちこの階層を辿らなきゃならず、ウザったいです。という訳で、ロググループ名と期間を指定して、ログレコードをダンプするスクリプトを書きますた↓。jq が要ります。
#!/bin/sh if [ $# -ne 3 ]; then echo "usage: "`basename $0`" <ロググループ名> <開始期間(YYYY-MM-DD hh:mm:ss)> <終了期間(YYYY-MM-DD hh:mm:ss)>" exit fi # パラメタ LOGGROUP=$1 DT_FROM=$2 DT_TO=$3 # 指定期間を Unixtime [ms] に UT_FROM=`date -d "$DT_FROM" +%s`000 UT_TO=`date -d "$DT_TO" +%s`000 # jq の select 条件 COND="(($UT_FROM <= .firstEventTimestamp) and (.firstEventTimestamp <= $UT_TO))" COND="$COND or (($UT_FROM <= .lastEventTimestamp) and (.lastEventTimestamp <= $UT_TO))" COND="$COND or ((.firstEventTimestamp <= $UT_FROM) and ($UT_TO <= .lastEventTimestamp))" # 指定ロググループ名のログストリーム一覧をげとして、指定期間に重複するものだけフィルタリング aws logs describe-log-streams --log-group-name $LOGGROUP --order-by LastEventTime --no-descending | jq -r ".logStreams[] | select($COND) | .logStreamName" | while read LOGSTREAM; do # ログストリームのログレコードを、タイムスタンプとメッセージのタブ区切りに整形して出力 aws logs get-log-events --log-group-name $LOGGROUP --log-stream-name $LOGSTREAM | jq -r '.events[] | [(.timestamp/1000+32400 | strftime("%Y-%m-%d %H:%M:%S")), .message] | @tsv' | sed 's/\\n$//' done
【註記】describe-log-streams ではページングを nextToken で制御するらしいのですが、今回要件では nextToken が返されることは無く、常にいちレスポンスで足りてしまっていたので、ページング処理はネグってあります。
もうひとつは、ロググループで一定期間後にイベント失効するように設定した時に、空のログストリームが残ってしまうので(大量に残るとかなりウザいw)、これを見つけて削除するスクリプト↓。
if [ $# -ne 1 ]; then echo "usage: "`basename $0`" <ロググループ名>" exit fi LOGGROUP=$1 # 指定ロググループ名のログストリーム一覧をげとして、開始タイムスタンプが無い(=ログレコードが無い)ものだけフィルタリング aws logs describe-log-streams --log-group-name $LOGGROUP --order-by LastEventTime | jq -r ".logStreams[] | select(.firstEventTimestamp == null) | .logStreamName" | while read LOGSTREAM ; do # ログストリーム削除 echo "delete "$LOGSTREAM aws logs delete-log-stream --log-group-name $LOGGROUP --log-stream-name $LOGSTREAM done
jq は今まで JSON の整形や要素の抜き取りくらいにしか使ってなかったのですが、今回初めてフィルタや演算・関数等についてちゃんと勉強しました。チョー便利っすね。クラスメソッドさんのマニュアル和訳が大助かりでした。