2012年11月28日水曜日

Google Apps Scriptでサービスを監視する

このエントリーをはてなブックマークに追加
Google Apps Script でゆるく自分のサービスを監視します。

  • レスポンスコードの確認
    2012-07-26 - 愛と勇気と缶ビール
    GASでは、cronタスクのような定期的な処理が簡単に書けます。このスクリプトは、外部からページアクセスをして、レスポンスコードが正しく返ってくるかをチェックし、正しく返ってこない場合には、メールを飛ばします。
    地味に面倒な作業なのですが、GASで数行スクリプトを書くだけで代替しています。
  • ツイートの保存
    Google Apps Script でツイートを集める | rockf.es blog
    自社サービスがオンライン上でどれだけバズっているかを知るために、Twitter検索をすることがあるかと思います。このスクリプトは、検索単語を仕掛けて定期的にツイートをスプレッドシートに保存します。
  •  Mixpanelのイベントチェック
    突然話の対象が、特定サービスに限定されてしまいますが、イベントログの解析ツールであるMixpanelのAPIを叩き、異常値が出ていないかをチェックします。例えば、「過去の数日間の平均に比べて、本日のページアクセス数が異常に多い」or「今日はサインアップが1件もない(どこかでエラーが発生している可能性がある)」などです。ここでは、「過去の数日間の平均に比べて、本日のページアクセス数が異常に多い」をチェックするスクリプトを記載します。
API_KEY      = "YOUR_MIXPANEL_API_KEY";
API_SECRET   = "YOUR_MIXPANEL_API_SECRET";
MAIL_ADDRESS = "YOUR_MAIL_ADDRESS";
EVENTS       = ["EVENT_NAME1", "EVENT_NAME2", "EVNET_NAME3"];
RATIO        = 1.5;

data = {
  'unit'     : "day",
  'interval' : 15,
  'type'     : "general"
}

function main() {
  for(var i = 0; i < EVENTS.length; i++) {
    check(EVENTS[i]);
  }
}

function check(event) {
  var API_URL = "http://mixpanel.com/api/2.0/events/?";
  var response, jsonString, object, series = [], values = [], i = 0, ave = 0;

  try {
    data['event'] = '["' + event + '"]';
    data['sig']   = getSig(data);
    data['event'] = encodeURIComponent(data['event']);

    response = UrlFetchApp.fetch(API_URL + makeParam(data));
    if (!response) {
      Logger.log("no response");
      return;
    }

    jsonString = response.getContentText();
    object     = Utilities.jsonParse(jsonString);
    series     = object.data.series;
    values     = object.data.values[event];

    for(i = 0; i < series.length - 1; i++) {
      ave += values[series[i]];
    }
    ave /= (series.length - 1);
    ave = Math.floor(ave);
    lastValue = values[series[series.length - 1]];

    if (lastValue >= ave * RATIO && !exist(event, ave)) {
      write(event, ave, lastValue);
      sendMail(event, ave, lastValue);
    }
    Logger.log("done!");
  } catch(e) {
    Logger.log(e);
    response = null;
  }
}

function getSig(hash) {
  var keys = [];
  var kv   = "";

  var currentDate = new Date;
  var expire = Math.floor(currentDate.getTime() / 1000) + 600;

  delete hash['sig'];
  hash['api_key'] = API_KEY;
  hash['expire'] = expire;
  hash['format'] = "json";
  
  for (var k in hash) keys.push(k);
  keys.sort();
  var length = keys.length;
  for(var i = 0; i < length; i++){
    kv += keys[i] + "=" + hash[keys[i]];
  }
  return getMD5Hash(kv + API_SECRET);
}

function getMD5Hash(input) {
  var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
  var txtHash = '';
  for (j = 0; j < rawHash.length; j++) {
    var hashVal = rawHash[j];
    if (hashVal < 0)
      hashVal += 256; 
    if (hashVal.toString(16).length == 1)
      txtHash += "0";
    txtHash += hashVal.toString(16);
  }
  return txtHash;
}

function makeParam(hash) {
  var param = "";
  for(var key in hash) {
    param += key + "=" + hash[key] + "&";
  }
  param = param.substring(0, param.length-1);
  return param;
}

function exist(event, ave) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var row   = sheet.getLastRow();
  var cell, i, _event, _ave, _date;

  for(i = 1; i <= row; i++) {
    _event = sheet.getRange('A'+ i).getValue();
    _ave   = sheet.getRange('B'+ i).getValue();
    _date  = sheet.getRange('D'+ i).getValue();
    if(event == _event && ave == _ave && getDateWithFormat() == _date) {
      return true;
    }
  }
  return false;
}

function write(event, ave, lastValue) {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.appendRow([event, ave, lastValue, getDateWithFormat()]);
}

function sendMail(event, ave, lastValue) {
  MailApp.sendEmail(
    MAIL_ADDRESS,
    "#alert " + event + " event is greather than the average value",
    "event name: " + event + ", average: " + ave + ", lastValue: " + lastValue
  );
}

function getDateWithFormat() {
  var date = Utilities.formatDate(new Date(), "JST", "yyyy/MM/dd");
  return '"' + date + '"';
} 

このスクリプトは、イベント、EVENT_NAME1,2,3について、過去2週間の平均よりも本日の値が1.5倍よりも多い場合、スプレッドシートに内容を記録し、アラートメールを飛ばします。