nasneの残量やGoogle Analyticsの情報をMackerelに監視させよう

Mackerelアドベントカレンダー6日目です。昨日はid:buty4649さんによるmackerelメタデータでパッケージ一覧を管理するCLIツールを作ったでした。

こんにちは、株式会社はてなでアプリケーションエンジニアをやっているid:syou6162です。10月にMackerelチームにjoinしました。今回は生活に関するあれこれをMackerelに監視させると便利!という軽い話を紹介します。

nasneの残量やjenkinsのjobの成功/失敗数をカスタムメトリックとして投稿/監視

私はライフログを集めるのが好きで、twitterの発言、歩いた歩数、預金残高などなど取れそうな情報をひたすら自宅のElasticSearchに保存しています。そのデータをkibanaで可視化したり検索すると、月や年単位での振り返りが簡単にできます。

ElasticSearchはこのように可視化や検索は得意なのですが、一点問題があって、数値がある閾値を越えたときの通知ができないという問題がありました。自分に関する多様なデータを貯め込んでいると通知して欲しくなる状況は結構あり、例えば「nasneの残量が減って、録画できなくない状況になる前に通知して欲しい」などの状況があります。最初はslackへの通知を自分で書いていたのですが、真面目に書くと割と面倒になってきたので(例えば60分おきの通知の再送など)、通知部分をmackerelに任せることにしました。

方法は色々ありますが、今回はホストのカスタムメトリックとして投稿するやり方でやってみます。

mackerel.io

agentの設定ファイルに指定されたフォーマットを吐くようなコマンド(スクリプト)を用意するだけなので簡単ですね。nasneの容量の場合、スクリプトを用意するまでもなく、こんな感じでワンライナーで投稿することができます。

[plugin.metrics.nasne]
command = "echo \"nasne.volumes.freeVolumeSizeRatio\t$(curl -s 'http://10.X.X.X:64210/status/HDDInfoGet?id=0' | /usr/local/bin/jq -r '.HDD | .freeVolumeSize / .totalVolumeSize')\t`date -u +%s`\""

これで1分置きにnasneの残り容量が分かり、監視設定をすれば容量が足りなくて「逃げるは恥だが役に立つ」が予約できなかった、という事態を防ぐことができます。slackへの通知も簡単にできるので、家庭内のslackに通知すればITにそれほど詳しくない妻も簡単に状況が分かります。実際の我が家のnasne残量の推移はこんな感じになっています(2-3日に1回は通知がくるような残量を推移しています...)。

f:id:syou6162:20161129195440p:plain

ライフログの取得にはjenkinsを活用しているのですが、ジョブの数が50個を越えてきたため、個別に通知されると見るのも大変です。そこで、成功/失敗の数もmackerelのカスタムメトリックで監視させています。nasneのときと同様にagentの設定ファイルに簡単なワンライナーを書けばOKです。

[plugin.metrics.jenkins_jobs_red]
command = "echo \"jenkins.jobs.red\t`curl -s http://localhost:3000/api/json | /usr/local/bin/jq -r '.jobs[] | .color' | grep -c red`\t`date -u +%s`\""

[plugin.metrics.jenkins_jobs_blue]
command = "echo \"jenkins.jobs.blue\t`curl -s http://localhost:3000/api/json | /usr/local/bin/jq -r '.jobs[] | .color' | grep -c blue`\t`date -u +%s`\""

成功/失敗の数のグラフは下の図で、安定していますが、瞬間停電でjenkinsを走らせている自宅macが落ちてしまったときにすぐ気づくことができ、長期間ライフログの失敗に取得していた、という事態を防ぐことができました(connectivityの通知でも気づくことができます)。

f:id:syou6162:20161129200442p:plain

Google Analyticsのユーザー数をサービスメトリックとして投稿/監視

Google Analyticsはリアルタイムに現在の訪問ユーザー数を知ることができるので見ているだけでも楽しいですが、「頻繁に見ていては仕事にならん、炎上しそうになってる(?)とき教えてくれ!」というのができると楽しそうと思ってやってみました(完全にネタです)。Google Analyticsから情報を取得するのは面倒そうですが、Google SpreadsheetのアドオンにGoogle Analyticsの情報を取得するものがあったのでそれを使います。

Google SpreadsheetにはGoogle App Script(javascriptと似たようなもの)を定期的に動かすことができる機能があるので、それを使って最近の訪問者数をmackerelに投稿させましょう。スクリプトはこんな感じです(ネタなので、かなり適当に書いています...)。

function postMackerelServiceMetric(apiKey, serviceName, payload) {
  return UrlFetchApp.fetch(
    "https://mackerel.io/api/v0/services/" + serviceName + "/tsdb",
    {
    "contentType" : "application/json",
    "method" : "post",
    "headers" : {
      "X-Api-Key" : apiKey
    },
    "payload" : JSON.stringify(payload),
    "muteHttpExceptions" : true
    }
  );
}

var epoch = Date.now() / 1000;
var mackerelApiKey = "YOUR_MACKEREL_API_KEY";
var serviceName = "Analytics";

function run(term, sheetName) {
  var ss =SpreadsheetApp.getActiveSpreadsheet()
  var mySheet = ss.getSheetByName(sheetName)
  SpreadsheetApp.setActiveSheet(mySheet);
  
  var row = mySheet.getLastRow();
  var users = mySheet.getRange(row, 2).getValue();
  var sessions = mySheet.getRange(row, 3).getValue();
  var pageviews = mySheet.getRange(row, 4).getValue();

  var payload = [
    {"name" : "analytics." + term + ".users", "time" : epoch, "value" : users},
    {"name" : "analytics." + term + ".sessions", "time" : epoch, "value" : sessions},
    {"name" : "analytics." + term + ".pageviews", "time" : epoch, "value" : pageviews}
  ];
  var mackerelPostRes = postMackerelServiceMetric(mackerelApiKey, serviceName, payload);
  Logger.log(mackerelPostRes)
}

function main_day() {
  run("day", "Google Analytics(Day)")
}

function main_hour() {
  run("hour", "Google Analytics(Hour)")
}

Google Spreadsheetで15分に一度くらい実行させておけばまぁよいでしょう。こんな感じで、炎上してそうかどうかも簡単に通知させることができます(実際はRTされてバズったとかですが)。

f:id:syou6162:20161129202636p:plain

機械学習の分類器の性能をサービスメトリックとして投稿/監視

ネタ要素を書いたので、最後は真面目なネタを書きます。最近は機械学習をサービスに導入する企業も大分増えてきたので、この分類器の性能はいい/悪いといった情報がどんどん流れてきます。Webサイトの訪問者数の増加によってサーバーのCPU率が上がっていないかどうかを(mackerelで!)監視したいのと同様に、機械学習の分類器(回帰も)の性能も刻々と追加/修正される教師データやチューニングの状況によって変化するため、これもmackerelで監視できるとうれしいでしょう。早速、サービスメトリックに投稿するようにしましょう。PerlやRuby、Goなど様々な言語からサービスメトリックの情報を簡単に取得/追加/更新/削除することができます。

例えばPerlで機械学習の分類器のF値などを投稿するスクリプトはこんな雰囲気です。簡単ですね。

use JSON::Types;
use WebService::Mackerel;

my $mackerel = WebService::Mackerel->new(
    api_key => $ENV{ML_STUDY_MACKEREL_API_KEY},
    service_name => 'ML-Study',
);

my $res = $mackerel->post_service_metrics(
    [
        {
            "name"  => "evaluation.precision",
            "time"  => time,
            "value" => JSON::Types::number $metrics->{precision},
        },
        {
            "name"  => "evaluation.recall",
            "time"  => time,
            "value" => JSON::Types::number $metrics->{recall},
        },
        {
            "name"  => "evaluation.f_value",
            "time"  => time,
            "value" => JSON::Types::number $metrics->{f_value},
        },
    ]
);

社内ではまだ導入していませんが、勉強会で雑談するときのエントリを推薦するbotを作ったので、この精度を投稿させています。こんな様子です。

f:id:syou6162:20161129204759p:plain

アノテーションの基準を特に決めていなかったために、教師データを増やしていっても精度がかえって落ちていっているという悲しい状況をmackerelは教えてくれます。

まとめ

今回は大まかに3つほどmackerelに様々なメトリックを投稿/監視させる方法を書きました。10行程度の簡単なスクリプト(あるいはワンライナー)、サーバーがなくてもGoogle Spreadsheetからメトリック投稿ができる、ということが分かっていただけたかと思います。このようにお手軽なところからmackerelを使っていただき、mackerelの本業であるサーバーの状態監視も体験してもらえるとうれしいです。

明日はhtnosmさんです。

参考情報

blog.sushi.money blog.a-know.me astj.hatenablog.com