これは
YAMAP エンジニア Advent Calendar 2021 の第 11 日目と、CircleCI Advent Calendar 2021 の第 11 日目の記事になる予定です。
qiita.com
qiita.com
経緯
YAMAP では、CircleCI を使って CI/CD を回していますが、既存機能の改善や、新機能のリリースに伴って、テストやデプロイの時間が長くなってきており、継続的に処理時間の改善を模索しています。
改善にあたって、処理時間の計測方法について試行錯誤してきましたが、最近、CircleCI Insights のダッシュボードを確認したところ、ブランチを横断して、ワークフロージョブの処理時間の可視化することが出来るようになっていました。
circleci.com
今回は、このワークフロージョブの処理時間の可視化について、これまで YAMAP でやっていたことも含めて書いてみようと思います。
特定のワークフロージョブの処理を可視化する試み v1 (自前のシェルスクリプトでやっていた)
.circleci/config.yml
以下のように、.circleci/config.yml 内で Bash の SECONDS
変数を用いて、愚直に処理時間を取得するように仕込んだ上で、シェルスクリプト内で API (下記の例では、duration.sh
) を叩いて、AWS の CloudWatch や Datadog にメトリクスを放り込んでいました。
version: 2.1
orbs:
aws-cli: circleci/aws-cli@x.x.x
...
executors:
...
commands:
...
build:
executor:
name: default
steps:
- run:
name: Run Build
command: |
SECONDS=0
... 実際の処理 ...
duration_seconds=$SECONDS
bin/duration.sh dev build ${duration_seconds} ${CIRCLE_BRANCH}
workflows:
build:
jobs:
- build:
filters:
branches:
ignore:
- master
- develop
ちなみに、build.sh
の中身は、以下のような感じ。
environment=${1}
workflow=${2}
value=${3}
branch=${4}
now="$(date +%s)"
function put_to_aws {
aws cloudwatch \
put-metric-data \
--metric-name Duration \
--namespace "Custom/CircleCI/${workflow}" \
--value ${value} \
--dimensions Name=environment,Value=${environment} \
--timestamp=${now}
}
function put_to_datadog {
curl -X POST "https://api.datadoghq.com/api/v1/series?api_key=${DD_CLIENT_API_KEY}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
"series": [
{
"metric": "circleci.${workflow}",
"points": [
[
"${now}",
"${value}"
]
],
"tags": [
"${environment}",
"branch:${branch}"
]
}
]
}
EOF
}
put_to_aws &
put_to_datadog &
wait
CloudWatch メトリクスと Datadog の両方に経過時間を飛ばしている様子です。
SECONDS 変数を使った処理時間の計測
上記の例では、Bash の SECONDS
変数を使って、処理時間を計測しています。この変数は、シェルが起動されてからの秒数が格納されます。
$ cat test.sh
SECONDS=0
sleep 3
duration_seconds=$SECONDS
echo $duration_seconds
$ ./test.sh
3
Datadog で可視化
そして、実際に Datadog で可視化したものは、下図の通りです。
ただし
今更気付きましたが、上記のアプローチだと、厳密なワークフロージョブの処理時間を計測出来ていません。ジョブの中の特定のステップの処理時間を計測しているだけになります。もう少し、ちゃんとやろうとすると、以下のように書くと良さそうです。
---
version: 2.1
orbs:
aws-cli: circleci/aws-cli@1.3.1
jobs:
build:
docker:
- image: cimg/base:2020.01
steps:
- run:
name: Job Start!!
command: |
echo "export START_TIME=$(date +%s)" >> $BASH_ENV
- run:
name: Sleep 5
command: |
sleep 5
- aws-cli/install
... 省略 ...
- run:
name: Job Stop!!
command: |
END_TIME=$(date +%s)
DURATION_SECONDS=$((${END_TIME}-${START_TIME}))
echo "START_TIME=${START_TIME}"
echo "END_TIME=${END_TIME}"
echo "DURATION_TIME=${DURATION_SECONDS}"
bin/duration.sh dev build ${DURATION_SECONDS} ${CIRCLE_BRANCH}
特定のワークフロージョブの処理を可視化する試み v2 (CircleCI Insights)
お手軽 CircleCI Insights
左のメニューバーに Insights 機能が鎮座しています。トップメニューの中に名を連ねているあたり、お手軽に利用して欲しいという CircleCI のお気持ちを感じます。
これをクリックすると、以下のように表示されます。
プロジェクトをクリックすると、以下のように表示されます。
そして、All Workflows
プルダウンから、確認したい Workflow
の名前をクリックすると、以下のように表示されます。
Y 軸が時間を示していて、全てのブランチのワークフロージョブ処理時間の推移を確認することが出来る棒グラフが表示されました。
まさに、これが欲しかった
以下のように、各ワークフロージョブの処理時間や、何のくらいのクレジットを消費しているかも表示されます。また、成功と失敗のについてもグリーンとレッドで表示されており一目瞭然です。
ただし
上記のグラフは、最新の 100 件の処理時間の結果しか表示されないので、継続的に処理時間の推移をモニタリングしたい場合には、冒頭に書いたように愚直に処理時間を計測する必要があると思います。(API で取得出来るかもしれませんが、まだ、試せていません)
後述の、Datadog の CircleCI Integration を利用することで、継続的に処理時間の推移をお手軽にモニタリングすることが可能です。
とは言え、こんな機能を提供してくださって Circle CI さん、有難うございます。
特定のワークフロージョブの処理を可視化する試み v3 (そう言えば、Datadog でも)
CircleCI Integration
ここまで書いておいて、Datadog に CircleCI Integration を利用することで、ワークフロージョブの時間を可視化することが出来ることを思い出しました。
こんな風に仕込んで
結果を待ちたいと思います。
いい感じじゃないですか!
とてもいい感じで可視化されました。
Datadog のクエリを駆使して、ワークフロージョブ毎の処理時間や、プロジェクト単位等を良い感じで可視化出来ています。
ということで
処理時間の改善は一日して成らず。継続的な観測が必要となります。