見出し画像

Four Keys分析を始めました


ごあいさつ

こんにちは。カラクリ株式会社の芹沢です。
前回から少し時間が空いてしまいましたが、今回は弊社の開発・QAチームで行ったFour Keys分析の取り組みの概要を紹介したいと思います。
※前回は「datadogを活用したテスト自動化の取り組み」を紹介しました。ご興味ある方はご確認ください。

Four Keysとは?

概要を簡単にご説明しますと、「ソフトウェア開発チームのパフォーマンスを示すための4つの指標」のことです。Google CloudのDORAチーム(DevOps Research and Assessment)によって開発・公開されました。
Four Keysの指標は以下の4つです。

  • デプロイの頻度 - 組織による正常な本番環境へのリリースの頻度

  • 変更のリードタイム - commit から本番環境稼働までの所要時間

  • 変更障害率 - デプロイが原因で本番環境で障害が発生する割合(%)

  • サービス復元時間 - 組織が本番環境での障害から回復するのにかかる時間

ソフトウェアの開発〜提供におけるスピードや安全性を把握するための指標として使えます。

詳細は以下の記事をご確認ください。
https://cloud.google.com/blog/ja/products/gcp/using-the-four-keys-to-measure-your-devops-performance

Four Keys分析を始めた背景

以下の背景と方針で、Four Keys分析を始めることにしました。

背景

  • 開発プロセスのパフォーマンス、健全具合の可視化をしたい。要は、開発チームの「健康診断」を行っておきたい。

  • 改善ポイントを見つけるためのきっかけ作りをしておきたい。(直接的に目の前の課題を検知するためのものにはならないかもしれないが)

  • 将来的に組織が拡大した時でも見えるようにしておきたい。

方針

  • 標準的な計測方法に則る。カラクリのカスタマイズは基本的には行わない。厳密に同じ計測はできないかもだが、ベースは殆どずれないようにしておきたいというもの。

  • なぜなら、公開されている「指標の計算」マトリクスをそのまま利用できるようにしたいため。(比較できるようにするというもの)

(参考)指標の計算マトリクス

Four Keysの取得・分析

弊社では、Four Keysの各指標を以下の通りで取得・分析することにした。

  • 「デプロイの頻度」について

    • 集計式:GitHubのタグ(リリースバージョン)のpush頻度

      • リリースバージョン毎にタグを管理している。このタグ毎のmasterへのpush頻度にした。(デプロイで拾うと余分なゴミデータを集計してしまう背景があったため。push後〜デプロイまでは殆どタイムラグがないため問題なしと判断。)

  • 「変更のリードタイム」について

    • 集計式:commitが作成されてからmaster branchにpushされるまでの時間

      • 「デプロイの頻度」と合わせて、masterへのpushまでの時間にした。理由は同じ。

  • 「変更障害率」について

    • 集計式:障害が発生したリリース回数(分子)÷ masterへのリリース回数(分母)

      • 「障害が発生したリリース回数」の集計にはAsanaを活用した。弊社では障害発生時にAsanaチケットで障害管理(バグトラッキングの徹底)を行っている。また、このAsanaチケットを活用して障害振り返りも行っている。この振り返り情報のうち「いつから発生した障害か(どのバージョンからなのか)」をフィールドで管理しているため、この情報を抽出して集計することにした。

  • 「サービス復元時間」について

    • 集計式:不具合を検知した日時から復旧日時(Asana起票日時から修正バージョンのリリース日時)

      • 障害管理のAsanaチケットを活用。Asanaチケットのフィールドで修正プルリクのURLを管理しているため、この情報と紐付けて集計することにした。

Four Keys取得までの流れ

以下の流れでFour Keys指標を抽出しています。
参考に記載しておきます。

  1. fourkeysを取り込んでGitHubのログデータをBigQueryに流し込む(four_keysテーブルの作成)

  2. four_keysテーブルから必要データのビューテーブルを作成

  3. GASでビューテーブルのデータをスプレッドシートに取得(BigQueryサービスの活用)

  4. Asanaから障害管理情報をスプレッドシートに取得(Asana REST APIの活用)

  5. スプレッドシート上に取得したデータを分析・可視化

弊社の場合は、Asanaから取得したデータとの組み合わせでFour Keysを分析する必要があったため、このような独自の仕組みで分析をしています。

スプレッドシート上での分析の仕組みを紹介

データ取得と分析の仕組みにスプレッドシートを活用しましたので、この仕組みの概要を紹介したいと思います。

1.GCPデータ取得用のGASを作成(データを取得してスプシ上に出力)

  • データ取得用のSQLシートを作成
    ※取得先のプロジェクトIDとSQLを書く

例:「query」シートとする
  • GASのサービスを追加

参考:https://developers.google.com/apps-script/advanced/bigquery?authuser=0&hl=ja
  • GCPデータ取得用のScriptを書く
    ※Four Keysの各指標毎にシートを分けて取得するのがわかりやすくて良い。
    ※以下はサンプルコードです。

function getReleasedReleases() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const querySheet = spreadsheet.getSheetByName("query"); // クエリが記載されているシート
  const resultSheet = spreadsheet.getSheetByName("releasedReleases"); // 結果を出力するシート
  const projectId =  querySheet.getRange("A2").getValue(); // プロジェクトIDをqueryシート
  const query =  querySheet.getRange("B2").getValue(); // SQLをqueryシートから取得

  // Queryパラメータを作成
  let queryRequest = BigQuery.newQueryRequest();
  queryRequest.query = query;
  queryRequest.useLegacySql = false

  const result = BigQuery.Jobs.query(queryRequest, projectId);

  const rows = [];
  const numColumns = result.rows[0].f.length

  for (let i = 0; i < result.rows.length; i++) {
    let resultRow = result.rows[i];
    let row = [];
    for (let j = 0; j < resultRow.f.length; j++) {
      row.push(resultRow.f[j].v);
    }
    rows.push(row);
  }

  const startRow    = 2,
        startColumn = 1
        lastRow = resultSheet.getLastRow()
  resultSheet.getRange(startRow, startColumn, lastRow, numColumns).clearContent();
  resultSheet.getRange(startRow, startColumn, rows.length, numColumns).setValues(rows);
}
  • Asanaデータ取得用のScriptを書く
    ※以下はサンプルコードです。

//トークン取得  ※アクセストークンを書く
var accessToken = "x/xxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

//データ出力先のスプシ  ※データの出力先スプレッドシートIDを書く
var ssid = "xxxxxxxxxxxxxxxxxxxxxxxxx";
var ss = SpreadsheetApp.openById(ssid);

///////////////////////////////////////////////
//関数名:storeSpreadSheet()
//機能:Asanaから取得したデータをスプレッドシートに取得する
//戻り値:無し
///////////////////////////////////////////////
function storeSpreadSheet() {
  var sheet = ss.getSheetByName("xxxxxxxxxxx");
  
  //Bug Trackingデータの取得
  var asana_list = getBugTrackingTasks();
  var column_num = asana_list[0].length;
  
  //スプレッドシートに取得
  sheet.getRange(2, 1, asana_list.length, column_num).setValues(asana_list);
  last_row = sheet.getRange(1, 1).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
  console.log(last_row);
  
  //スプレッドシートにセットされたデータを取得
  var ss_task_list = sheet.getRange(2, 1, 2 + asana_list.length, sheet.getLastColumn()).getValues();
  
  //チケットIDを取得
  var gid_list = [];
  for (var i=0;i<ss_task_list.length;i++) {
    gid_list.push(String(ss_task_list[i][0]));
  }

}

//////////////////////////////////////////
//関数名:getBugTrackingTasks(get_data_num)
//機能:Asanaから必要なデータを取ってくる
//戻り値:Asanaのデータリスト
//////////////////////////////////////////
function getBugTrackingTasks() {
  var options = {
    "method": "get",
    "contentType": "application/json",
    "headers": {
    "Authorization": "Bearer " + accessToken
    }
  };
  
  //チケット一覧情報の取得  ※あくまでサンプルなので、取得したいデータに合わせてカスタマイズしてください。
  var response = UrlFetchApp.fetch("https://app.asana.com/api/1.0/projects/xxxxxxxxxxxxxxxx/tasks?opt_fields=created_at,completed_at,custom_fields", options);
  var results = JSON.parse(response);
  var list = [];
  
  if (results.data) {
    for (var i=0; i < results.data.length; i++) {
      var field = [];
      
      //チケットIDの取得
      field[0] = String(results.data[i].gid);
      
      //タイトルの取得
      field[1] = results.data[i].name;
      
      //作成日の取得
      field[2] = new Date(results.data[i].created_at);
      
      //完了日の取得
      field[3] = results.data[i].completed;
      
      //カスタムフィールドデータの取得
      for (var j=0; j < results.data[i].custom_fields.length; j++) {
        
        //「発生バージョン」の取得
        else if (results.data[i].custom_fields[j].name === "発生バージョン") {
          field[4] = results.data[i].custom_fields[j].display_value;
        }
        
        //「修正プルリクエスト」の取得
        else if (results.data[i].custom_fields[j].name === "修正プルリクエスト") {
          field[5] = results.data[i].custom_fields[j].display_value;
        }
      }
      list.push(field);
    }
  }
  return list;
}
  • トリガーを作成(データ取得を定期実行化)
    ※以下はトリガーイメージです。


2.取得したデータを分析(スプレッドシート関数を利用)
※スプレッドシート関数を活用してFour Keysを抽出。
※以下画像ではF列で「変更のリードタイム」を抽出している。

Four Keys毎の分析結果シートを作成して抽出

4.Four Keys分析の結果を週次でタイムスタンプ(履歴データを蓄積)

分析データを週次でタイムスタンプして蓄積・可視化


いかがでしょうか。
弊社でのFour Keys分析のやり方を一例として紹介させていただきました。
品質管理活動の参考になれば幸いです。

「分析の仕組みをどうするか」は、開発における運用の仕組みや利用しているツールによって変わると思います。

Four Keys分析に興味がありましたら、導入を検討してみるのはいかがでしょうか。

以上


この記事が気に入ったらサポートをしてみませんか?