毎回調べるのが面倒なので、自分用の雑メモです。
最近は GPT とか warp とかも出てきているので、こういうメモも不要になりそうですね👌
やりたいこと
私の職場では ECS のログを CloudWatch Logs に送信して保存しています。
(ここはケースによって異なると思いますが) 下記の様なログを想定します。
- CloudWatch Logs の JSON 形式ログ。
message
キー値にログ本文が入る - ログ本文は ECS の JSON 形式ログで、エスケープされている。
log
キー値にアプリケーション (コンテナ・プロセス) の標準出力ログが入っている
{
"events": [
{
"logStreamName": "ログストリーム名",
"timestamp": 1718906470387,
"message": "{\"container_id\":\"xxxxxxxx\",\"container_name\":\"コンテナ名\",\"ec2_instance_id\":\"i-0xxx\",\"ecs_cluster\":\"クラスタ名\",\"ecs_task_arn\":\"arn:aws:ecs:ap-northeast-1:...\",\"ecs_task_definition\":\"タスク定義名\",\"log\":\"ログの本文\",\"source\":\"stdout\"}",
"ingestionTime": 1718906472835,
"eventId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
]
}
対象環境
- macOS 13 以降
- 事前に
brew install coreutils
でgdate
を入れる
filter-log-events コマンドには、開始/終了時間のパラメータとしてミリ秒単位の unittime を渡す必要があるのですが、Mac 標準の date
コマンドではこれが出来ないので、GNU coreutil の gdate
を入れます。
一括取得するコマンド
次のコマンド実行で、CloudWatch Logs からログをローカルファイル logs.json
に書き出します。
ロググループ名、開始時間、終了時間 は適宣変更してください。
aws logs filter-log-events \
--log-group-name 'ロググループ名' \
--start-time `TZ=Asia/Tokyo gdate --date='2024-06-21 03:00:00.000' +%s%3N` \
--end-time `TZ=Asia/Tokyo gdate --date='2024-06-21 03:00:10.000' +%s%3N` \
> logs.json
整形して1行ログにする
前工程でダウンロードしたログは CloudWatch Logs のログ形式 (json) になっており、大変見づらいです。
jq
を使うと2重構造の JSON も綺麗に整形できます。
cat logs.json | jq -r '.events[] | .message | fromjson | .log' > filtered.json
フィルタしたい場合は select(...)
文を。以下はワード aaa
を含むものにフィルタする例.
cat logs.json | jq -r '.events[] | select(.message | contains("aaa")) | .message | fromjson | .log' > filtered.json
最終的な出力はエスケープされた json の log
キーの値を一覧するので、こうなります。
ログの本文