40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

Fluentdでログ集約して、TitaniumMobile使ってiPhone上でグラフ表示

この前Fluentdの勉強会参加してお話を聞いたその翌日に

ということをつぶやいていました。折角妄想したので、ひとまず作ってみました。

f:id:h5y1m141:20120521163540p:plain

サーバ側でJSON生成

Fluentdの設定はこんな感じにしました。

<source>
type tail	
path /var/log/apache2/access.log
tag apache.access
format apache
</source>

<source>
type tail	
path /var/log/auth.log
tag syslog.access
format syslog
</source>

<match **.access>
# plugin type
type mongo

# mongodb db + collection
database apache
collection access

# mongodb host + port
host localhost
port 27017

# interval
flush_interval 10s

</match>

上記設定で、MongoDBにログが集約されたので、JSONを生成するSinatraアプリをこんな具合にしました。

require 'sinatra'
require 'mongo'
require 'json'

def connect_mongo(db,collection)
  db = Mongo::Connection.new("localhost", 27017).db(db)
  entries = db.collection(collection)
  return entries
end

def convert_to_json(items)
  items.each_with_index do |item,i|
    content_type :json
    body.push(item.to_json) 
  end
  result = '[' + body.join(',') + ']'
  return result
end
get '/mongo' do
  access = connect_mongo('apache','access')
  items = access.find()
  return convert_to_json(items)
end

Titanium Mobile+グラフモジュール使ってiPhone側でグラフ表示

以下2つをポイントに作成しました

  • @goando さんが作成されたグラフモジュール(詳しくはこちら)があるのでそれを活用
  • 取得したJSONに対してiPhone側であれこれ加工した方が使い勝手良さそう&勉強のためにunderscore.jsを使って条件抽出

出来たソースはこんな感じ

var win = Ti.UI.createWindow({backgroundColor:"#CCC"});
var _ = require('lib/underscore');
var Charts = require('com.gnddesign.prettycharts');

httpClient('http://website/mongo',function(result){
  var statusCode200 = _.chain(result)
      .filter(function(item){return item.code ==='200';}).value();

  var statusCode404 = _.chain(result)
      .filter(function(item){return item.code ==='404';}).value();

  var statusCode500 = _.chain(result)
      .filter(function(item){return item.code ==='500';}).value();

  var chartData = Charts.createChart({
    leftChartType:0,
    leftChartColor:2,
    leftDataTitle:"status code",
    leftDataUnit:'件',
    leftDataArray:[statusCode200.length,statusCode404.length,statusCode500.length],
    width:320,
    height:480,
    top:0,
    left:0
  });

  win.add(chartData);
  win.open();
});

function httpClient(url,callback){
  if(Titanium.Network.online===true){
    var xhr = Ti.Network.createHTTPClient();
    xhr.open('GET',url);
    xhr.onload = function(){
      var result = JSON.parse(this.responseText);
      callback(result);
    };
    xhr.error = function(){
      var dialog = Ti.UI.createAlertDialog({
        title: "ネットワーク接続エラー",
        message: "ネットワーク接続が確立されていません。再度お試しください"
      });
      dialog.show();
      myApps.ui.actInd.hide();
    };
    xhr.send();
  }else{
    var dialog = Ti.UI.createAlertDialog({
      title: "ネットワーク接続できていません"
    });
    dialog.show();
    myApps.ui.actInd.hide();
  }
}

作ってみた感想とか課題

  • あまり細かい条件抽出してないのでここまでは意外と簡単に出来た
  • 時間帯別でログの表示をしたいので、MongoDB側でdb.apache.find({time:{$gt:xxx}})みたいな処理を考えないとダメ
  • グラフをタッチした時に、関連の詳細情報を表示するView/TableViewへ画面遷移というようなことがprettychartsだと出来なそう?(間違っていたらゴメンナサイ)
  • MarketPlaceにCharts Moduleがあって、15日間試用出来るけど、$29.99 /Seat /Month となんとなく高く感じる

当面やらないといけないことが多いけど、気が向いたら続きのエントリ書くかも