[AWS] Kinesis Data Firehose経由でS3に送っているSendGridのイベントデータが、何割かこぼれていた
概要
SendGridのイベントデータを、API Gateway → Kinesis Data Firehose → S3 -> Athena -> Redash
という流れで分析できる機構が会社にあるのですが、最近Biz側から「メールのデータの数値がぜんぜん現実と違うよ〜」という話があがってきました。
調べると、どうやら、全イベントの中でも、ちゃんと取得できているものと、取得できていないものがあるようでした。
調査内容
下図がイベントデータの流れです。Sendgrid Event WebhookとAWSの各種サービスを使って組んでいます。
調べていくと、以下のことがわかりました。
- SendgridのGUI上では、ちゃんとここ1週間の全イベントデータが表示されている(SendGridはイベントデータを1週間だけ保持してくれる)
- しかし、S3にはその全データが保存されているわけではなく、何割か落ちている
そうなるとSendGridはシロです。そして、API Gatewayも、4xx, 5xxエラーなどはほぼ全く発生していないようだったので、ちゃんとWebhookのPostを受け取れているのだろうと判断しました。
この辺りで、じゃあFirehoseなんじゃない...?となんとなく当てをつけました。
しかし、Firehoseのバッファリングのサイズをいったん数倍にしてみても、何割かデータがこぼれているという状況は変わらなかったため、根本原因の特定には至らず。
でもたぶんここなんだよな〜となったので、次の手として以下をやりました。
対応したこと
FirehoseをLambdaに置き換えました。
仕事の内容はシンプルで、受け取ったイベントデータをS3にputするだけです。
Firehoseのように、一定時間経ったらまとめて保存、みたいな仕組みをやろうとすると別のDB機構を使う必要がある?と思ったので、素直な実装にしました。
また、Athenaの求める形式に合わせるため、受け取ったリクエスト内のjson(イベントデータ)が複数であれば、それぞれに改行を入れて、まとめて1つのファイルに保存にするようにしました。
また、jsonの項目として普通はtimestamp入っているのですが、たまにない場合があり、結果としてそのjsonに対してクエリが走るとエラーになっていたので、timestampがなければ現在時刻に相当する値を入れることで、直しました。
構成としては、先ほどの図のFirehoseが、Lambdaに変わっただけです。
結果、確認している限りでは、S3に全データが保存されるようになったようです。
原因については、もしかすると、FirehoseがS3に複数個のjsonを一気に流し込むときの形式が、Athenaが望む形になっていないケースがあったのかもしれません。
以下が似た事例かもしれない。
感想
putのデータ形式がよくなかったという真相だった場合、put直前に整形すればいいだけなので、FirehoseをLambdaにわざわざ変える意味があったのかは怪しい。なので、改善の余地はまだありそう。
しかし、まあひとまず直ったのでOK🙆♂️
あとAWS色々触れてよかった。インフラ楽しい。
追記・追加調査
よくよく調べると、Firehoseで、データ整形用ツールとして、内部的にLambdaを使えるようでした。
なので、上述した整形ロジックの内容を微修正したうえで、このFirehose + Lambdaの機構で再度様子を見たところ、Lambda単体の時と同様に、100%イベントデータがS3に保存されていることを確認しました🎉
やはり根本原因は、FirehoseからS3に投入する際の、ファイル内のデータ形式に不備があったことのようです。
Discussion