dehio3’s diary

仕事、生活、趣味のメモ

CircleCIのビルドデータを収集する仕組みを作った

f:id:dehio3:20190711135531p:plain

はじめに

前回のCircleCI ユーザーコミュニティミートアップ にて「CircleCI Serverの利用状況を可視化した話」と言う題名でLTしてきました。

circleci.connpass.com

speakerdeck.com

その際に、Lambda + S3 +Athena を利用したビルド情報を収集する仕組みを紹介したのですが、CircleCI Server(オンプレ版のCircleCI)向けの仕組みで、SaaS版の方には対応してませんでした。

現場が変わってSaaS版にも対応する必要があり、SaaS版での制限を満たす為に仕組みも一部変えて作り直したので、こちらで紹介したいと思います。

目的

CircleCIを複数のチームで利用し始めると、利用料金をチームにどう振り分けるかの問題が発生してきます。

CircleCIには「Insights (インサイト)」 というビルド情報を可視化してくれるメニューがありますが、ここのリポジトリの利用情報で、管理目的で使うような全体的な情報は表示されません。

その為、CircleCIのAPIにて取得できるビルド情報から、チームを判断できるリポジトリ単位でのビルド状況を集計できるようにしたのが今回作ったツールです。

(ちなみにインサイトについては、改善を検討しているらしく、要望としてあることは中の人に認識いただけたので今後に期待!!)

circleci.com

機能概要

S3にビルド情報をJSON形式で保存し、Athenaでクエリによる参照をできるようにする事で、BIツールから可視化する部分は前回と変わらないので、スライドを参照してください。

前回はlambdaにて日毎のビルド情報のフィルタリングを実施し、S3に直接データを保存していましたが、SaaS版ではAPIで取得したビルド情報を、Dynamodbに保存する様に変更しました。

f:id:dehio3:20190923115413p:plain

SaaS版との違い

スライドでも触れていますが、ビルド情報を取得するAPIにて「limit」のパラメータが存在しており、オンレプ版ではこの値に制限がなかったのですが、SaaS版では「100」という上限があります。

circleci.com

オンプレ版では「limit=5000」で、日次で前日分のビルド情報を一気に取得する方式を取っていたのですが、SaaS版では100が上限なので、ビルド情報を取得する間隔を短くする必要がありました。

オンプレ版では日次で取得したビルド情報から、キューの日付が前日の情報を条件に一括で取得していましたが、取得間隔が短くなると、必然的に重複して取得したビルド情報の判断を実装する必要があります。

その重複したビルド情報の排除を実装する為にDynamodbを新たに利用しました。

Dynamodbでの対応1(重複排除)

Dynamodbにデータを保存する際に、キーが同じ項目の場合は自動で上書きをしてくれます。

条件式 - Amazon DynamoDB

既存の項目の上書きを防止

PutItem オペレーションはキーが同じ項目を上書します (存在する場合)。これを回避するには、条件式を使用します。これにより、問題の項目が同じキーを持っていない場合にのみ書き込みが続行されます。

この機能を利用して、lambdaではAPIで取得したビルド情報をそのままDynamodbに投げて、DynamoDB側で重複を排除する様にしました。

APIから取得したデータで、「リポジトリ名+ビルド番号」がビルド情報を一意に判断できる情報だった為

  • reponame :ハッシュキー
  • build_num:ソートキー

という設定で、二つのキーを使用してプライマリキーを設定しました。

Dynamodbでの対応2(グローバルセカンダリインデックス)

上記のプライマリキーの設定により重複データの排除は実装できたのですが、データを参照する際に問題が発覚しました。

ハッシュキーにリポジトリ名を設定した為、リポジトリを跨いだデータの参照ができません。

この問題を解決する為に、グローバルセカンダリインデックスを利用しました。

docs.aws.amazon.com

グローバルセカンダリインデックスでは、参照時に利用できるキーをプライマリキーとは別に設定できるので、リポジトリを跨いだデータをキーとして設定する事で、ビルド情報を参照できる様にしました。

全てのビルド情報にはオーガニゼーション名は必ず同一のものが含まれる為

  • username :ハッシュキー
  • queued_at:ソートキー

とういうグローバルセカンダリインデックスを作成し、参照時はこちらを利用するとこで、リポジトリを跨いだデータの参照を可能にしました。

ソースコード

以下に公開してます。

serverlessを利用してデプロイできるようにしている為、serverless.ymlの変数を環境に合わせて設定していただければ、そのまま利用できます。

github.com

(インフラエンジニアが書いたコードなので、改善点あればプルリクいただけると嬉しいです!!)

おわり

やってる事は大した事ないのですが、自分のアウトプットを兼ねて書いてみました。

同じ様な実装する必要がある方の少しでも参考になれば幸いです!

次回のミートアップでもLTをする予定なので、興味ある方は是非ご参加ください! circleci.connpass.com