MongoDB
Fluentd

Fluentdで集めた、Nginxのログを、MongoDBのMapReduceを使ってアクセス解析入門!!

More than 5 years have passed since last update.

キーワード入れ込みまくった感がすごいですが

やりたかったことは、Nginxのログを、mongoに格納

そしてそのデータをmongoのMapReduceを使って解析するという事です。

今回はサンプルに、http status codeの集計をします。


前提として

MongoDB導入済み

Nginxのログ格納済み

database: nginx

collection: access

なので、Fluentdとかは今回話題に出て来ません。むしろnginxも不要かも知れません。

・・・よし、一旦不要にします。


改めて前提として

Mongodb導入済み

use nginx

db.access.save({status:200});
db.access.save({status:200});
db.access.save({status:200});
db.access.save({status:200});
db.access.save({status:300});
db.access.save({status:400});
db.access.save({test:123});

db.access.find();
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f2"), "status" : 200 }
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f3"), "status" : 200 }
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f4"), "status" : 200 }
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f5"), "status" : 200 }
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f6"), "status" : 300 }
{ "_id" : ObjectId("51b9ffe092e0e471137ad2f7"), "status" : 400 }
{ "_id" : ObjectId("51b9ffe192e0e471137ad2f8"), "test" : 123 }

こんな状況です。この量のままだと見てわかるけど、増えたら面倒

では、コード毎にカウントしようそうしよう

{200:4},{300:1},{400:1}とかだと嬉しいな

では、進めます。

mongoには外部ファイル実行する機能がありますので


log.js

var colName = 'access.status';

var map = function() {
var label = String(this.status);

emit(
label,
{count: 1}
);
}

//簡単に言うと、
//keyには200
//valuesには[{count:1},{count:1},{count:1}]
//と言った感じでデータが渡ってきてカウントアップしてる感じです。
var reduce = function(key, values) {
var result = {count: 0};

values.forEach(function(value) {
result.count += value.count;
});

return result;
}

mongo = new Mongo('localhost');
mydb = mongo.getDB('nginx');

var res = mydb.access.mapReduce(map, reduce, {out: colName});

shellPrint(res);



Map MapReduceを登録

$ mongo log.js

MongoDB shell version: 2.4.0
connecting to: test
{
"result" : "access.status",
"timeMillis" : 1080,
"counts" : {
"input" : 7,
"emit" : 7,
"reduce" : 1,
"output" : 4
},
"ok" : 1,
}


では、処理を実行してみましょう!!

$ mongo

MongoDB shell version: 2.4.0
connecting to: test
> use nginx
switched to db nginx
> db.access.status.find();
{ "_id" : "200", "value" : { "count" : 4 } }
{ "_id" : "300", "value" : { "count" : 1 } }
{ "_id" : "400", "value" : { "count" : 1 } }
{ "_id" : "undefined", "value" : { "count" : 1 } }

このような感じで、

200が4

300が1

400が1

statusなしが1

という結果を得る事ができました。