首頁  >  文章  >  web前端  >  Node.js和MongoDB實作簡單日誌分析系統_node.js

Node.js和MongoDB實作簡單日誌分析系統_node.js

WBOY
WBOY原創
2016-05-16 16:02:231589瀏覽

在最近的專案中,為了方便分析把專案的日誌都存成了JSON格式。之前日誌直接存在了文件中,而MongoDB適時闖入了我的視線,於是就把log存進了MongoDB中。 log只存起來是沒有意義的,最關鍵的是要從日誌中發現業務的趨勢、系統的效能漏洞等。之前有一個用Java寫的分析模組,運行在Tomcat下。實現相當的重量級,增加一個新指標的流程也比較繁瑣,而且由於NFS的原因還導致分析失敗。一直想改寫,最初想用Ruby On Rails,可是一直沒有時間學習和開發(在找藉口啊!)。在杭州QCon 2011上又遇到了Node.js,雖然之前也聽說過,但是沒有深入研究,聽了淘寶蘇千 的演講後,當時了就有要用Node.js實現這個日誌分析系統的想法。前端用JS,伺服器用JS,連資料庫的Shell都是JS,想想就夠酷的——當然最關鍵是程式碼量小。

一、用Node.js實作伺服器端程式碼

為了有良好的風格和快速的程式碼編寫,不可避免地應該採用一個簡單的框架。 Express實現了大部分的功能,可是好需要花一定時間熟悉,並且看起來對這個項目來說有些重量級。在Node.js的官網上有一個聊天的Demo ,這個程式碼簡單移動,封裝了對URL的處理和回傳JSON。於是我就直接使用了fu.js,重寫了server.js:

複製程式碼 程式碼如下:

HOST = null; // localhost
PORT = 8001;

var fu = require("./fu"),
    sys = require("util"),
    url = require("url"),
    mongo = require("./request_handler");

fu.listen(Number(process.env.PORT || PORT), HOST);

fu.get("/", fu.staticHandler("index.html"));

太簡單了吧? !不過的確是這樣,一個伺服器已經建立起來了。
下面看處理請求的request_handler.js程式碼:

複製程式碼 程式碼如下:

var mongodb = require("mongodb");
var fu = require("./fu");


// TOP 10 user Action
fu.get("/userActionTop10", function(req, res){
  mongodb.connect('mongodb://localhost:27017/log', function(err, conn){
    conn.collection('action_count', function(err, coll){
coll.find({"value.action":{$in:user_action}}).sort({"value.count":-1}).limit(10).toArray(function(err, docs){
        if(!err){
          var action = [];
          var count = [];
          for(var i = 0; i             //console.log(docs[i]);
            action.push(docs[i].value.action);
            count.push(docs[i].value.count);
          }
          res.simpleJSON(200, {action:action, count:count});
        
          // 務必記得關閉資料庫連線
          conn.close();
        }
      });
    });
  });
});

二、客戶端

日誌系統的最重要的是視覺化顯示,這裡使用了JQuery的一個插件jqPlot Chart 。首先使用靜態的HTML頁面,用來作為圖形顯示的容器:

複製程式碼 程式碼如下:



 
   
    交會監控系統
   
    腳本>
    腳本>
    腳本>
   
   
   
   
    腳本>
   
   
   
   
    腳本>
  頭>
 
  身體>

幾乎是jqPlot的範例中的完整拷貝,好吧,我承認我太懶了。 下面看一下用來顯示生成圖形的chart.js:

複製程式碼如下程式碼:

// すべてのチャート描画関数を保存します。1 つのチャートを無効にしたい場合は、
だけが必要です // 関数を配列に入れるときにプッシュ行をコメント化します。
var 描画 = [];

/****************************** トップ 10 ユーザーアクション開始 ***************** ****************/
document.write('

');


vardrawUserActionTop10Chart = function(){
  if(!$("#userActionTop10Chart").attr('class')){
    $("#userActionTop10Chart").attr('class', 'small_chart');
  }


  $.ajax({
    非同期:false,
    URL: '/userActionTop10',
    データ型:'json',
    キャッシュ: false、
    成功:関数(データ){
      試してみてください{
        $('#userActionTop10Chart').html('');


        $.jqplot('userActionTop10Chart', [data.count], {
          タイトル: "ユーザー アクション トップ 10",
          シリーズデフォルト:{
            レンダラー:$.jqplot.BarRenderer,
            rendererOptions: {fillToZero: true},
            pointLabels: {
              表示: true、
              ypadding:1
            }
          }、
          axesDefaults:{
            tinyRenderer:$.jqplot.CanvasAxisTickRenderer,
            ティックオプション: {
              角度: -30、
              フォントサイズ: '12px'
            }
          }、
          軸: {
            xaxis: {
              レンダラ: $.jqplot.CategoryAxisRenderer,
              ティック: data.action
            }、
            yaxis: {
              パッド:1.05
            }
          }
        });
      }キャッチ(e){
        //alert(e.message);
      }
    }
  });
}


draws.push('drawUserActionTop10Chart');


/******************************* トップ 10 ユーザーアクション終了 **************** ********************/

/*********** チャート開始 *****************/


//チャート描画関数をここに置きます
//1.チャートの div を挿入
//2.関数描画チャートを実装します
//3.関数名を配列にプッシュします。draws


/*********** チャート終了 *******************/

// すべてのチャートを描画します
vardrawAllCharts = function(){
  for(var i = 0; i     eval(draws[i] "()");
  }


 // 5 分後に呼び出します。
 window.setTimeout(drawAllCharts, 5 * 60 * 1000);
}


//
$(関数(){
  drawAllCharts();
});

サーバー端末とゲスト端末の代価都有了,那就跑起看看効果吧:

良い意味で何を忘れましたか?日志の分析コード。

三、MongoDB 增量式 MapReduce 实现日志分析を使用します

MongoDB のドキュメントには、増分 MapReduce に関するメディアが含まれています。MongoDB がストリーミング処理を実行するために開始され、自動で増量式の MapReduce が実行されます。これは、MapReduce を大量に実行できないように設定する方法を説明するだけです。

便宜上、MapReduce で MongoDB を使用する JavaScript を個別の js ファイルに書き込み、その後 crontab 経由で実行します。stats.js のコード:


复制代码代码如下:

/************** /etc/crontab 每 5 分鐘執行一次檔案。 *****************/
var action_count_map = function(){
  emit(this.action, {action:this.action, count:1});
}

var action_count_reduce = function(key, values){
  var count = 0;
  values.forEach(function(value){
    count = value.count;
  });
  return {action:key, count : count};
}


db.log.mapReduce(action_count_map, action_count_reduce, {query : {'action_count' : {$ne:1}},out: {reduce:'action_count'}});

db.log.update({'action_count':{$ne:1}}, {$set:{'action_count':1}}, false, true);

 思路很簡單:
1. 在map中將每個action訪問次數設為1
2. reduce中,統計相同action的造訪次數
3. 執行mapReduce。指定了查詢為‘action_count'不等於1,也就是沒有執行過該統計;將結果儲存在‘action_count'集合,並且使用reduce選項表示該結果集作為下次reduce的輸入。
4. 在目前所有日誌記錄設定'action_count'的值為1,表示已經執行過該統計。不知道這種是否會造成沒有還沒統計的紀錄也被更新? ?望有經驗的大俠賜教!

定時執行stats.js的shell:

複製程式碼 程式碼如下:

*/5 * * * * root cd /root/log; mongo localhost:27017/log stats.js

好了,這就是全部的程式碼,沒有什麼特別玄妙的地方,不過Node.js真的是個好東西。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn