CircleCI のデータ活用 - Insights と Insights API

こんにちは。CircleCI カスタマーサクセスチームの Chisato です。
最近個人的に幸せを感じた出来事は、育てているレモンの花が咲いたことです。今年２回目の開花で、とても良い香りがします。


今回は、インサイト（以下 Insights）についてご紹介します。

最近お客様から、「不安定なテストの自動検知、いいですよね」などのコメントをいただく機会が増え、とても嬉しく思います。
Insights をご活用いただきありがとうございます。


# Insights とは

Insights は、CircleCIのご利用をデータとして可視化したページです。
お客様側で設定いただく必要なく、UIから簡単にデータを確認いただけます。

# ４つの指標（キー メトリクス）

CircleCI を最大限活用いただけるよう、CircleCI では Insights を利用して４つの指標を計測することを推奨しています。

### 実行時間/ Duration
**ワークフローの実行時間**です。CIの最終的な目標は「迅速なフィードバック」であるため、４つの中で最も重要な指標です。実行時間を短くすることにだけ専念するのではなく、失敗したビルドから意義のあるフィードバックを得ることが大切です。「実行スピードと価値のある情報を両立するワークフロー」を意識して、コミットサイズの最適化を進めましょう。


### スループット/ Throughput
**ワークフローの１日あたりの平均実行回数**です。実行回数にこだわるよりも、メインブランチにいつでもプルリクエストをマージできる状態を保つことを意識されることをおすすめします。

### 平均復旧時間/ Mean Time to Recovery
**ワークフローが失敗してから次に成功するまでの平均時間**です。チームが、失敗に対してどれだけ迅速に対応できるかを測るのに役立ちます。テストのカバレッジが上がるにつれて短縮される傾向にあります。

### 成功率/ Success Rate
特定の期間に**ワークフローが成功した回数を、合計実行回数で割った値**です。トピックブランチで「安全で価値ある失敗」をしながら、メインブランチには十分にテストされたコードだけをマージできているか確認するのに役立ちます。

これからデータを計測をスタートする場合、まずは実行時間、または平均復旧時間を計測することが推奨されます。

# Insights のUI
実際の Insights を一緒に見てみましょう。ダッシュボードで Insights というタブをクリックしてアクセスします。
ページの画像中にピンク色の文字で説明を記載しています。

![Screen Shot 2022-07-10 at 14.38.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/ebf67374-4b33-326e-0a49-3f6a52f9c434.png)


![Screen Shot 2022-07-10 at 15.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/6c2fa993-32eb-8eb0-303d-0a9058534942.png)

![Screen Shot 2022-07-10 at 15.18.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/bdece5d0-1c8b-6418-5aa6-5ade6f5ad8bf.png)

上図の選択期間は7日間です。
矢印とその横のパーセンテージは、選択中の期間とその前の期間を比較した値です。
 Runs（実行回数）を見ると、「直近の7日間は、その前の7日間に比べて 16% 実行回数が多かった」のがわかります。

実行時間の横の P95 は、95パーセンタイルを表します。
選択期間の前の期間のなかで、最長の実行時間をベンチマークとしています。
（ P50 は中央値を表します）


# ４つの指標の活用事例

#### 実行時間/ Duration
* ある機能の利用前と後で実行時間を比較し、その機能が実行時間の高速化に貢献しているか確認する
* [リソースクラス](https://circleci.com/ja/product/features/resource-classes/ "resource-classes")のサイズ（スペック）を変更して、実行時間とクレジットの消費数の兼ね合いを見る
* スループットなど他の指標と組み合わせて、適切なコミットサイズを検討する
* 短時間で終了するテストがすべて成功した場合のみ、時間のかかるテストを実行するフローにする ("Fail fast")

#### スループット/ Throughput
* メインブランチにプルリクエストをいつでもマージできる状態にするための指標とする
* ワークフローの実行回数から、適切なコミットサイズを検討する

#### 平均復旧時間/ Mean Time to Recovery
* 失敗が発生した時のチームの対応スピードやフローについて改善点がないか検討する
* 失敗したビルドのフィードバックへの対応から、チームの生産性について考える

#### 成功率/ Success Rate
* 成功率が低く失敗の多いテストの改善、または削除をする。これにより、テスト最適化を進め、クレジットの無駄な消費を防ぐ
* 各プロジェクトのメインブランチの成功率を確認し、改善点を確認する

<br>


# Test Insights

テスト結果の分析には、Test Insights（[テストインサイト](https://circleci.com/docs/ja/insights-tests)）が便利です。
JUnit や RSpec などのテストフレームワークが生成するテストレポートのメタデータを config.yml 内 に記述する store_test_result ステップで CircleCI に保存することで利用できます。

"TEST"のタブをクリックすることでアクセスできます。
 
下記が主な表示項目です。
* 実行時間の遅いテストのランキング
* 失敗率の多いテストのランキング
* 不安定なテストの自動検知

不安定なテストの自動検知をもとにテスト最適化を進めていただくお客様がかなり増えています。


"JOBS"タブをクリックすると、ジョブごとのデータが確認できます。
指標やクレジット消費量のほか、CPUとRAMの使用率が確認できるため、リソースクラスのスペックの最適化に便利です。

![Screen Shot 2022-07-20 at 21.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/1eb2bdc6-ce2d-468a-71c7-536a12030e79.png)



<br>

# Insights API
Insights はAPIでもデータを取得可能です。
詳しくは[Insights API](https://circleci.com/docs/api/v2/index.html#tag/Insights)のページを参照ください。

### トークン作成のステップ
1. CircleCI の User Settings ページ（ダッシュボード左下のアイコン）から Personal API Token ページに移動します。
 URL：https://app.circleci.com/settings/user/tokens
1. Create New Tokenをクリックして、Personal API トークン（Personal API Tokens）を作成、保存します。


### Insights API 利用のステップ

1. CircleCI API Tokenを設定する
1. 下記コードのうち次の３項目を自身のものに変更する
　* "circle-farm": 組織名(VCS)
　* "pepper-deploy": プロジェクト名
　* "YOUR_TOKEN": ステップ1で作成したトークン
1. デスクトップのコマンドプロンプトにコードをペーストしてAPIを呼び出す

今回使用する指標（メトリクス）のデータは[こちらのページ](https://circleci.com/docs/api/v2/index.html#operation/getProjectWorkflowMetrics)の ”Shell + Curl” 欄で確認できます。

<br>

```
curl --request GET \
  --url 'https://circleci.com/api/v2/insights/gh/circle-farm/pepper-deploy/workflows?reporting-window=last-30-days' \
  --header 'circle-token: YOUR_TOKEN'
```

取得イメージ
![Screen Shot 2022-07-16 at 14.01.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/a930bd2f-2bfa-1d5b-3511-7da28e5caedb.png)

<br>

# Slackにデータを送信する
今回はAPIを使って、Insights のデータをSlackに送信する設定をご紹介します。
下記はサポートエンジニアのAaronさんが作成したプロジェクトです。
プロジェクトの [URLはこちら](https://github.com/ogii/circleci-insights-slack) 

次のデータが取得できるようになっています。
* ワークフローのURL
* ワークフロー名
* 消費クレジット数
* データの計測開始・終了時刻（UTC）
* ワークフローの成功数
* ワークフローの失敗数

Slack への通知は、[Slack orb](https://circleci.com/developer/orbs/orb/circleci/slack)を用いています。
コンテキストの設定方法は[こちら](https://circleci.com/docs/ja/contexts)を参照ください。


### 設定のステップ
1. Slack orbを設定する
1. 下記ソースコードについて、次の項目を変更する
　* CIRCLE_TOKEN: 自身のPersonal API トークン
　* project-name: プロジェクト名
　* org-name: VCS Organization名
　* vcs-name:  GitHubは "gh", Bitbucketは "bb"
　* workflow-names: ワークフロー名（複数設定したいときはカンマで区切る）
　* reporting-window: 希望するデータ取得期間
1. 定期的にSlackに通知する場合は、パイプラインのスケジュール実行 ([Scheduled pipelines](https://circleci.com/docs/ja/scheduled-pipelines)) を設定する

<br>

```
version: 2.1

orbs: 
  slack: circleci/slack@4.10.1

jobs:
  insightsdata:
    parameters:
      project-name:
        type: string
      org-name:
        type: string
      vcs-name:
        type: string
      workflow-names:
        type: string
      reporting-window:
        type: enum
        enum: ["24-hours","7-days","30-days","60-days","90-days"]
    docker:
      - image: cimg/base:stable
    resource_class: small
    steps:
      - run: 
          name: Get workflow insight data
          command: |
            # Strip whitespaces from list of workflows
            WORKFLOWS=$(echo "<< parameters.workflow-names >>" | sed 's/, /,/g' | sed 's/ ,/,/g' | xargs)
            
            # Generate project slug
            PROJECT_SLUG="<< parameters.vcs-name >>/<< parameters.org-name >>/<< parameters.project-name >>"
            
            # Get insight data from API
            INSIGHT_DATA=$(curl --request GET \
            --url "https://circleci.com/api/v2/insights/$PROJECT_SLUG/workflows?reporting-window=last-<< parameters.reporting-window >>&all-branches=true" \
            --header "circle-token: $CIRCLE_TOKEN")
            
            # Parse insight data and map to template
            INSIGHT_MAP=$(echo $INSIGHT_DATA | jq --arg workflows "$WORKFLOWS" '[.items[] | select(.name == ($workflows | split(",")[])) | {"type":"section","fields":[{"type":"mrkdwn","text":("*Workflow Name*: " + .name)},{"type":"mrkdwn","text":("*Credits Used*: " + (.metrics.total_credits_used|@sh))},{"type":"mrkdwn","text":("*First Run*: " + (.window_start|@sh))},{"type":"mrkdwn","text":("*Last Run*: " + (.window_end|@sh))},{"type":"mrkdwn","text":("*Successful Runs*: " + (.metrics.successful_runs|@sh))},{"type":"mrkdwn","text":("*Failed Runs*: " + (.metrics.failed_runs|@sh))}]},{"type":"divider"}]')
            
            # Create base template to append to
            echo '{"blocks":[{"type":"header","text":{"type":"plain_text","text":"Credit Usage Report for << parameters.org-name >>/<< parameters.project-name >>","emoji":true}},{"type":"context","elements":[{"type":"mrkdwn","text":"*Period:* << parameters.reporting-window >> <https://app.circleci.com/insights/<< parameters.vcs-name >>/<< parameters.org-name >>/<< parameters.project-name >>/?reporting-window=last-<< parameters.reporting-window >>|View on CircleCI>"}]}]}' > template.json
            
            # Append insight data to base template
            CUSTOM_SLACK_TEMPLATE="$(jq -r --argjson INSIGHT_MAP "$INSIGHT_MAP" '.blocks += $INSIGHT_MAP' template.json)"
            
            # Export complete template to .json file
            echo $CUSTOM_SLACK_TEMPLATE > template2.json
            # Make template available in later steps via the environment variable CUSTOM_SLACK_TEMPLATE
            echo 'export CUSTOM_SLACK_TEMPLATE=$(jq . template2.json)' >> $BASH_ENV
      - slack/notify:
          template: CUSTOM_SLACK_TEMPLATE
          event: always

workflows:
  insightdata:
    when:
      and:
        - equal: [ scheduled_pipeline, << pipeline.trigger_source >> ]
        - equal: [ "insight_schedule", << pipeline.schedule.name >> ]
    jobs:
      - insightsdata:
          project-name: "machine-executor-images"
          org-name: "circle-farm"
          vcs-name: "gh"
          workflow-names: "build_all_images,daily"
          reporting-window: "30-days"
          context:
            - Slack
```

<br>

シュットトト♫
Slackでデータを取得できました。![Screen Shot 2022-07-20 at 10.38.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/d4841a2e-85ac-9eb2-395d-a69a673a44fe.png)


パイプラインのスケジュール実行 (Scheduled Pipelines)は Project Settingsのページから設定できます。
![Screen Shot 2022-07-20 at 21.34.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101915/b13ed434-876d-8e1c-787f-3106ff465986.png)





# まとめ
Insights は今後ますます多くのお客様に利用いただくページになると思います。
お使いいただいているなかで、「こんな表示がほしい」などのリクエストがありましたら、ぜひ[機能リクエスト](https://circleci.canny.io/)を提出してください。他のユーザーのリクエストに投票することもできます。

今回、サポートエンジニアのAaronさんとNaoyaさんにご指導いただきながらブログを執筆しました。
いつもほんとうにありがとうございます。

技術的なご質問は[こちら](https://support.circleci.com/hc/ja "サポートセンター Home")から無料のサポートチケットを提出してお問い合わせください。日本語でお問い合わせいただけます。
→ [CircleCI サポートセンター](https://support.circleci.com/hc/ja "サポートセンター Home")

## 参考文献

[インサイトの使用](https://circleci.com/docs/ja/insights)

[Insights のメトリクスの用語集](https://circleci.com/docs/ja/insights-glossary?highlight=#totalCredits-organization-definition)

[Insights API](https://circleci.com/docs/api/v2/index.html#tag/Insights)

[Get summary metrics for a project's workflows](https://circleci.com/docs/api/v2/index.html#operation/getProjectWorkflowMetrics)

[パイプラインのスケジュール実行](https://circleci.com/docs/ja/scheduled-pipelines)

APIの例として挙げたプロジェクト: [https://github.com/ogii/circleci-insights-slack](https://github.com/ogii/circleci-insights-slack)

[The 2022 State of Software Delivery](https://circleci.com/resources/2022-state-of-software-delivery/)