前回の続き的なもの
前回はECSにあるログをAthenaから参照することを目的にした内容でしたが、
今回はLambdaから出力されるログもAthenaから参照することを目的にしています。
目的(背景)
- Lambdaのログも可能な限りリアルタイムで参照したい
- AthenaのテーブルをECSからのログとLambdaのログで分けることはしたくない
- ロググループは一つではなく多数
- ロググループ自体に入っているログの量の合計は月あたり1GBにも満たない
構成図
処理詳細
目的(背景)にも書いてあるように、ログの容量自体そこまで多くないためDataFirehoseを使ってます。
CloudWatchLogsのサブスクリプションフィルターからパターンにログレベルを指定(NOTICE WARN ERROR)して、FirehoseからS3にDIRECT PUTしています。
Firehoseの設定は下記を有効化しておきましょう。
JSON形式でログを出力していたのでメッセージデータのみにしないとAthenaでの参照がうまくいかなかったりします。
ただ、ここに仕様というなのハマりポイントがありました。
ハマりポイント
ハマったというのも自分ところの環境が悪いのか、それとも仕様なのか現状把握できていないんですが
ログイベントからのみメッセージデータを抽出した場合、下記のような出力がされていました。
{
"owner": "111111111111",
"logGroup": "CloudTrail/logs",
"logStream": "111111111111_CloudTrail/logs_us-east-1",
"subscriptionFilters": [
"Destination"
],
"messageType": "DATA_MESSAGE",
"logEvents": [
{
"id": "31953106606966983378809025079804211143289615424298221568",
"timestamp": 1432826855000,
"message": "{\"eventVersion\":\"1.03\",\"userIdentity\":{\"type\":\"Root1\"}"
},
{
"id": "31953106606966983378809025079804211143289615424298221569",
"timestamp": 1432826855000,
"message": "{\"eventVersion\":\"1.03\",\"userIdentity\":{\"type\":\"Root2\"}"
},
{
"id": "31953106606966983378809025079804211143289615424298221570",
"timestamp": 1432826855000,
"message": "{\"eventVersion\":\"1.03\",\"userIdentity\":{\"type\":\"Root3\"}"
}
]
}
こんな感じでLambdaのログ出力されているものに対して、メッセージデータ抽出した場合
{"eventVersion":"1.03","userIdentity":{"type":"Root1"}
\n
{"eventVersion":"1.03","userIdentity":{"type":"Root2"}
\n
{"eventVersion":"1.03","userIdentity":{"type":"Root3"}
\n
\nが入ってS3に格納されてました。
これがかなり厄介でAthenaから参照すると、この\nの行もレコードとして認識して1レコード毎に何も無いレコードが挟まるという状態です。
この1byteを除去するためにLambda挟むの本末転倒すぎるのもあって、結局Athenaのクエリで適当なカラムに対してis not null つけて有耶無耶にするしか思いつかないのが現状
動的パーティションの何かしらのオプション使うなり、ログ形式変えればうまくできるんですかね、
(改行入ってないやんけ)