ほんじゃらねっと

ダイエット中プログラマのブログ

ApacheのアクセスログをMongoDBコレクションにインポートするNode.jsスクリプト

MongoDBの勉強を兼ねて、Apacheアクセスログを後でログ分析や ビジュアライズに使えるようにMongoDBにインポートするスクリプトを書いた。

下記のスクリプトはログファイルを行単位で読み込んでMongoDBの 特定のコレクションに登録する。 行単位のファイル読み込み処理はNode.js標準で簡単にできる方法が用意されていない ようなので、node-bylineを使用している。

log_importer.js

var fs = require('fs');
var byline = require('byline');
var MongoClient = require('mongodb').MongoClient;

var dbUrl = 'mongodb://localhost:27017/<database name>';
var targetPath = '<path to access log>';

var logPattern = /(\S+) \- \- \[([^\]]+)\] '([^']+)' (\d+) (\S+) '([^']+)' '([^']*)'/;

var rs = fs.createReadStream(targetPath);
var stream = byline.createStream(rs);

MongoClient.connect(dbUrl, function (err, db) {
    if (err) {
        throw err;
    }   

    var apacheLogs = db.collection('apache_logs');

    var i = 0;
    stream.on('readable', function () {

        var line = null;
        while (null !== (line = stream.read())) {
            console.log(i + ':line start ' + line);
            var match = logPattern.exec(line);
            if (match != null) {
                var methodParams = match[3].split(' ');
                var method = methodParams[0];
                var path = methodParams[1];
                var http = methodParams[2];
                var log = {
                    host: match[1],
                    ts: match[2],
                    method: method,
                    path: path,
                    http: http,
                    status: match[4],
                    size: match[5],
                    agent: match[7]
                };
                apacheLogs.insert(log, function (err, result) {
                    if (err) {
                        console.log('log insert error:', err);
                    } else {
                        console.log(i + ':inserted');
                    }
                });
            } else {
                console.log(i + ':match error');
            }
            i++;
        }
    });
    stream.on('end', function () {
        db.close();
    });
});

参考にしたサイトや使用したライブラリ:

RegExp - Mdn https://developer.mozilla.org/ja/doc/Web/JavaScript/Reference/Global_Objects/RegExp

Read large text files in nodejs https://coderwall.com/p/ohjerg/read-large-text-files-in-nodejs

Node.js how to read one line of numbers from a file into an array http://stackoverflow.com/questions/7379310/node-js-how-to-read-one-line-of-numbers-from-a-file-into-an-array

npm line-reader https://github.com/nickewing/line-reader

npm node-byline https://github.com/jahewson/node-byline

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス