🚿

[AWS] Kinesis Data Firehose経由でS3に送っているSendGridのイベントデータが、何割かこぼれていた

2024/02/11に公開

概要

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つのファイルに保存にするようにしました。

https://repost.aws/ja/knowledge-center/error-json-athena

また、jsonの項目として普通はtimestamp入っているのですが、たまにない場合があり、結果としてそのjsonに対してクエリが走るとエラーになっていたので、timestampがなければ現在時刻に相当する値を入れることで、直しました。

構成としては、先ほどの図のFirehoseが、Lambdaに変わっただけです。

結果、確認している限りでは、S3に全データが保存されるようになったようです。

原因については、もしかすると、FirehoseがS3に複数個のjsonを一気に流し込むときの形式が、Athenaが望む形になっていないケースがあったのかもしれません。

以下が似た事例かもしれない。

https://dev.classmethod.jp/articles/kinesis-data-firehose-json-parse-glue-jobs/
https://dev.classmethod.jp/articles/convert-records-in-json-format-from-kinesis-data-firehose-to-json-lines-format-and-output-them-nodejs/

感想

putのデータ形式がよくなかったという真相だった場合、put直前に整形すればいいだけなので、FirehoseをLambdaにわざわざ変える意味があったのかは怪しい。なので、改善の余地はまだありそう。

しかし、まあひとまず直ったのでOK🙆‍♂️

あとAWS色々触れてよかった。インフラ楽しい。

追記・追加調査

よくよく調べると、Firehoseで、データ整形用ツールとして、内部的にLambdaを使えるようでした。

https://dev.classmethod.jp/articles/amazon-kinesis-firehose-data-transform/

なので、上述した整形ロジックの内容を微修正したうえで、このFirehose + Lambdaの機構で再度様子を見たところ、Lambda単体の時と同様に、100%イベントデータがS3に保存されていることを確認しました🎉

やはり根本原因は、FirehoseからS3に投入する際の、ファイル内のデータ形式に不備があったことのようです。

Discussion