ようへいの日々精進XP

よかろうもん

CircleCI でワークフロージョブの処理時間を可視化する試み

これは

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 内で BashSECONDS 変数を用いて、愚直に処理時間を取得するように仕込んだ上で、シェルスクリプト内で 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 の中身は、以下のような感じ。

#!/bin/bash

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 変数を使った処理時間の計測

上記の例では、BashSECONDS 変数を使って、処理時間を計測しています。この変数は、シェルが起動されてからの秒数が格納されます。

$ cat test.sh
#!/bin/bash

SECONDS=0
sleep 3
duration_seconds=$SECONDS

echo $duration_seconds
$ ./test.sh
3

Datadog で可視化

そして、実際に Datadog で可視化したものは、下図の通りです。

f:id:inokara:20211209234333p:plain

ただし

今更気付きましたが、上記のアプローチだと、厳密なワークフロージョブの処理時間を計測出来ていません。ジョブの中の特定のステップの処理時間を計測しているだけになります。もう少し、ちゃんとやろうとすると、以下のように書くと良さそうです。

---
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 のお気持ちを感じます。

f:id:inokara:20211209234355p:plain

これをクリックすると、以下のように表示されます。

f:id:inokara:20211209234411p:plain

プロジェクトをクリックすると、以下のように表示されます。

f:id:inokara:20211209234427p:plain

そして、All Workflows プルダウンから、確認したい Workflow の名前をクリックすると、以下のように表示されます。

f:id:inokara:20211209234441p:plain

Y 軸が時間を示していて、全てのブランチのワークフロージョブ処理時間の推移を確認することが出来る棒グラフが表示されました。

まさに、これが欲しかった

以下のように、各ワークフロージョブの処理時間や、何のくらいのクレジットを消費しているかも表示されます。また、成功と失敗のについてもグリーンとレッドで表示されており一目瞭然です。

f:id:inokara:20211209234500p:plain

ただし

上記のグラフは、最新の 100 件の処理時間の結果しか表示されないので、継続的に処理時間の推移をモニタリングしたい場合には、冒頭に書いたように愚直に処理時間を計測する必要があると思います。(API で取得出来るかもしれませんが、まだ、試せていません)

後述の、Datadog の CircleCI Integration を利用することで、継続的に処理時間の推移をお手軽にモニタリングすることが可能です。

とは言え、こんな機能を提供してくださって Circle CI さん、有難うございます。

特定のワークフロージョブの処理を可視化する試み v3 (そう言えば、Datadog でも)

CircleCI Integration

ここまで書いておいて、Datadog に CircleCI Integration を利用することで、ワークフロージョブの時間を可視化することが出来ることを思い出しました。

f:id:inokara:20211210165841p:plain

こんな風に仕込んで

f:id:inokara:20211210170852p:plain

結果を待ちたいと思います。

いい感じじゃないですか!

とてもいい感じで可視化されました。

f:id:inokara:20211210175434p:plain

Datadog のクエリを駆使して、ワークフロージョブ毎の処理時間や、プロジェクト単位等を良い感じで可視化出来ています。

ということで

処理時間の改善は一日して成らず。継続的な観測が必要となります。