Maison > Article > interface Web > Node.js et MongoDB implémentent une analyse simple des journaux system_node.js
Dans un projet récent, les journaux du projet ont été enregistrés au format JSON pour une analyse facile. Auparavant, les journaux étaient stockés directement dans des fichiers, mais MongoDB est apparu au bon moment, j'ai donc enregistré les journaux dans MongoDB. Cela n'a aucun sens de simplement sauvegarder les journaux. Le plus important est de découvrir les tendances commerciales et les failles de performances du système à partir des journaux. Auparavant, il existait un module d'analyse écrit en Java et fonctionnant sous Tomcat. La mise en œuvre est assez lourde, le processus d'ajout d'un nouvel indicateur est également fastidieux et l'analyse échoue à cause du NFS. J'ai toujours voulu le réécrire, et au départ je voulais utiliser Ruby On Rails, mais je n'ai jamais eu le temps d'apprendre et de développer (je cherche des excuses !). J'ai rencontré à nouveau Node.js au QCon 2011 à Hangzhou. Même si j'en avais déjà entendu parler, je ne l'ai pas étudié en profondeur. Après avoir écouté le discours de Taobao Su Qian, j'ai immédiatement eu l'idée d'utiliser Node.js pour. mettre en œuvre ce système d’analyse des journaux. Le front-end utilise JS, le serveur utilise JS et même le shell de la base de données est JS. C'est cool quand on y pense – bien sûr, le plus important est que la taille du code soit petite.
1. Utilisez Node.js pour implémenter le code côté serveur
Afin d'avoir un bon style et une écriture de code rapide, il est inévitable d'adopter un framework simple. Express implémente la plupart des fonctions, mais il faut un certain temps pour s'y familiariser, et cela semble un peu lourd pour ce projet. Il existe une Chat Demo sur le site officiel de Node.js. Ce code est simplement déplacé et encapsule le traitement des URL et le retour du JSON. J'ai donc utilisé fu.js directement et réécrit server.js :
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"));
N'est-ce pas trop simple ? ! Mais c'est bel et bien le cas, un serveur a été mis en place.
Regardons le code request_handler.js qui gère les requêtes :
// TOP 10 des actions des utilisateurs
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){
si(!err){
var action = [];
var count = [];
pour(var je = 0; je < docs.length; je ){
//console.log(docs[i]);
action.push(docs[i].value.action);
Count.push(docs[i].value.count);
}
res.simpleJSON(200, {action:action, count:count});
//N'oubliez pas de fermer la connexion à la base de données
conn.close();
>
});
});
});
});
2.Client
La chose la plus importante à propos du système de journalisation est l'affichage visuel. Un plug-in de JQuery jqPlot Chart est utilisé ici. Utilisez d’abord une page HTML statique comme conteneur pour l’affichage graphique :
几乎是jqPlot的示例中的完整拷贝,好吧,我承认我太懒了。
下面是看用来显示生成图形的chart.js:
/****************************** TOP 10 Action utilisateur Démarrer ******************* ***************/
document.write('
var drawUserActionTop10Chart = fonction(){
if(!$("#userActionTop10Chart").attr('class')){
$("#userActionTop10Chart").attr('class', 'small_chart');
>
$.ajax({
async: faux,
URL : '/userActionTop10',
Type de données : 'json',
cache : faux,
succès:fonction(données){
essayez{
$('#userActionTop10Chart').html('');
$.jqplot('userActionTop10Chart', [data.count], {
titre : "TOP 10 des actions utilisateur",
sériesPar défaut :{
moteur de rendu :$.jqplot.BarRenderer,
options de rendu : {fillToZero : true},
pointLabels : {
montrer : vrai,
ypadding :1
>
},
axesDefaults :{
tickRenderer : $.jqplot.CanvasAxisTickRenderer,
tickOptions : {
angle : -30,
Taille de la police : '12px'
>
},
axes : {
axe x : {
moteur de rendu : $.jqplot.CategoryAxisRenderer,
ticks : data.action
},
yaxis : {
tampon : 1,05
>
>
});
}attraper(e){
//alerte(e.message);
>
>
});
>
draws.push('drawUserActionTop10Chart');
/******************************* TOP 10 Action utilisateur Fin **************** ********************/
/*********** Début du graphique *****************/
//Mettez votre fonction de dessin de graphique ici
//1. insérez un div pour le graphique
//2. mettre en œuvre le tableau de dessin des fonctions
//3. poussez le nom de la fonction dans le tableau draws
/*********** Fin du graphique ******************/
//Dessinez tous les graphiques
var drawAllCharts = fonction(){
pour(var je = 0; je < draws.length; je ){
eval(dessine[i] "()");
>
// Se rappelle dans 5 minutes.
window.setTimeout(drawAllCharts, 5 * 60 * 1000);
>
//
$(fonction(){
drawAllCharts();
});
服务器端和客户端的代码都有了,那就跑起来看效果吧:
好像忘了什么?日志的分析代码。
三、使用MongoDB et MapReduce实现日志分析
Les applications MongoDB sont basées surIncremental MapReduce.的MapReduce。最后发现原来是我理解有误,文档里并没有写这一点,只是说明了如何设置才能增量执行MapReduce。
为了方便,我把MapReduce使用MongoDB的JavaScript写在了单独的js文件中,然后通过crontab定时执行。stats.js的代码:
var action_count_reduce = function(clé, valeurs){
var compte = 0;
valeurs.forEach(fonction(valeur){
Nombre = valeur.compte;
});
Renvoie {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);
L'idée est très simple :
1. Définissez le nombre d'accès pour chaque action dans la carte sur 1
2. En réduction, comptez le nombre de visites pour une même action
3. Exécutez mapReduce. La requête est spécifiée comme « action_count » n'est pas égal à 1, c'est-à-dire que les statistiques n'ont pas été exécutées ; les résultats sont stockés dans la collection « action_count » et l'option de réduction est utilisée pour indiquer que l'ensemble de résultats est utilisé comme l’entrée de la prochaine réduction.
4. Définissez la valeur de « action_count » sur 1 dans tous les enregistrements de journal actuels, indiquant que les statistiques ont été effectuées. Je me demande si cela entraînera la mise à jour des enregistrements qui n'ont pas encore été comptés ? ? J'espère que des héros expérimentés pourront me donner quelques conseils !
Exécution planifiée du shell stats.js :
D'accord, c'est tout le code, il n'y a rien de particulièrement mystérieux, mais Node.js est vraiment une bonne chose.