サービスの数値目標に対する進捗を日次で通知する(AWS Lambda × kintone × Slack)

KPI進捗通知

こんにちは。エンジニアの飛岡です。

TimeCrowdは長い間どんぶり勘定というか、その場しのぎと言うか、勢いやノリで運営してしまっていました。
それが昨年ディレクターの元廣が加わり、だいぶサービスとして当たり前のことがいろいろとできるようになってきました。

サービスとして達成すべき数値目標がきちんと明示されたのも、その一例です。
今回はこの数値目標の1つである「有料ユーザー数」について、Slackに通知する仕組みを作りました。

目標値の取得

目標はkintoneに保存されています。kintoneはAPIトークンを用いてデータを取得することができるので、今回はそれをそのまま使いました。

JSのコードにすると以下のようになります。

function fetchGoal(cb) {
  var options = {
    host: process.env.KINTONE_HOST,
    path: process.env.KINTONE_PATH,
    method: 'GET',
    headers: {
      'X-Cybozu-API-Token': process.env.KINTONE_TOKEN,
    }
  };

  https.get(options, (res) => {
    var body = '';
    res.setEncoding('utf8');

    res.on('data', (chunk) => {
      body += chunk;
    });

    res.on('end', (res) => {
      var json = JSON.parse(body);
      var month = new Date().getMonth() + 1;
      var goal = json.record['人数_' + month].value;
      cb(goal);
    });
  }).on('error', (e) => {
    console.error(e)
  });
}

人数_◯というキーでその月の目標が取れるので、それをコールバックに渡しています。
アクセスするHOSTやPATH、TOKENはenvで渡しています。

実績値の取得

これはTimeCrowdの内部用のAPIに有料ユーザー数を返すものがあったので、そちらから取得しました。

function fetchPaidUsers(cb) {
  var options = {
    host: 'timecrowd.net',
    path: process.env.TIMECROWD_PATH,
    method: 'GET',
    headers: {
      'Authorization': 'Bearer ' + process.env.TIMECROWD_TOKEN,
    }
  };

  https.get(options, (res) => {
    var body = '';
    res.setEncoding('utf8');

    res.on('data', (chunk) => {
      body += chunk;
    });

    res.on('end', (res) => {
      var json = JSON.parse(body);
      var users = parseInt(json.result);
      cb(users);
    });
  }).on('error', (e) => {
    console.error(e)
  });
}

アクセスのAPIやTOKENをenvで指定しています。

進捗の通知

取得した目標値と実績値から、進捗を計算してSlackに通知します。

function notifySlack(text) {
  var body = JSON.stringify({
    text: text,
    username: 'KPI進捗確認マン',
    icon_emoji: ':turtle:',
  });
  console.log(process.env.SLACK_PATH)
  var options = {
    host: 'hooks.slack.com',
    path: process.env.SLACK_PATH,
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    }
  };

  var req = https.request(options, function (res) {
    res.on('data', function (chunk) {
  }).on('error', function (e) {
    console.error(e)
    });
  });

  req.write(body);
  req.end();
}

function handle(cb) {
  fetchGoal(function(goal) {
    fetchPaidUsers(function(users) {
      var remain = goal - users;
      var progress = Math.round(users / goal * 100);
      var text = [
        '今の有料ユーザー数は *', users, '人* :exclamation:\n',
        '今月の目標(', goal ,'人)まであと *', remain, '人* :upside_down_face:\n',
        ':chart_with_upwards_trend: ', progress, '%'
      ].join('')
      cb(text);
    });
  });
}

exports.handler = function(event, context) {
  handle(function(text) {
    notifySlack(text);
  })
};

AWS Lambdaから呼び出されるためhandlerとしてexportします。
SLACK_PATHにはIncoming WebhookのURLを渡しています。

なお、Lambdaは以下の記事でも使っていますのでご参照ください。

結果

こんな感じになりました。

KPI進捗通知

目標達成できるように引き続き頑張っていきますので、よろしくお願いします。

それでは。

TimeCrowdに戻る