在Node.js中将log4j错误streamparsing为JSON

我正在使用以下shell命令(由我的node.js程序产生)来parsinglog4j日志文件中的错误:

tail -F -n +0 LOGFILE.log | grep 'ERROR\|^[[:space:]]*at' --before-context=2

这将拾取所有行中包含“错误”的行,以及所有堆栈跟踪,前面两行用于上下文。

错误如下所示:

 2014-10-15 01:55:12,402 [fault (self-tuning)'] [TABTHREAD7] [App:01.01.01] (Classinfo.Action) ERROR stageinfo.company.com|11.222.33.444 userName - Error message telling us what went wrong From: (unknown) at ExceptionThrower.main(ExceptionThrower.java:21) at ExceptionThrower.main(ExceptionThrower.java:22) at ExceptionThrower.main(ExceptionThrower.java:23) at ExceptionThrower.main(ExceptionThrower.java:24) at ExceptionThrower.main(ExceptionThrower.java:25) 

我想要获取这个数据stream并parsing它,以便最终生成如下的JSON对象:

 JSONErrorObject = { "Date" : "2014-10-15", "Timestamp" : "01:55:12,402", "Error" : "Error message telling us what went wrong", "Stack Trace" : "at ExceptionThrower.main(ExceptionThrower.java:21) at ExceptionThrower.main(ExceptionThrower.java:22) at ExceptionThrower.main(ExceptionThrower.java:23) at ExceptionThrower.main(ExceptionThrower.java:24) at ExceptionThrower.main(ExceptionThrower.java:25)" }; 

我正在读取grep命令的stdout(stream),并想分析传入的行,以便它们转换为上面的JSON格式。 从我读过的任何东西,似乎我应该在我的节点程序中编写一个处理器/parsing器,它可以string.match(正则expression式),并使用类似于下面的概念将这些块拉到我需要的属性下:

 var re = /(\w+)\s(\w+)/; var str = "Shant Want"; var myArray = str.match(re); var JSONStr = { "First name" : myArray[1], "Last name" : myArray[2] }; console.log(JSON.stringify(JSONStr)); // Output is {"First name":"Shant","Last name":"Want"} 

正在使用的正则expression式是:

 /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2},\d{3}) (\[(.*)\]) \((.*)\)\s+([^ ]*) ([^ ]*) ([^ ]*) - (.*)$/g 

我的节点代码在下面(将数据写入文件现在只是为了testing):

 var spawn = require('child_process').spawn; var net = require('fs'); var parseSh = spawn('sh', [ 'errorParser.sh' ]); //errorParser.sh has the one line parser - tail -F -n +0 LOGFILE.log | grep 'ERROR\|^[[:space:]]*at' --before-context=2 console.log("start tailing"); parseSh.stdout.on("data", function (data) { var str = data.toString(); var re = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2},\d{3}) (\[(.*)\]) \((.*)\)\s+([^ ]*) ([^ ]*) ([^ ]*) - (.*)$/g; var myArray = str.match(re); fs.appendFile('myArray.txt', myArray, function (err) { if (err) throw err; console.log("It's saved!"); }); }); 

这个工作正常,当文件有一个单行,并填写myArray所需的值。 但是,在处理一个stream时,它会失败。 它给了我一堆随机的“nullnullnullnullnullnull”值之间。 在处理stream时,我怎样才能达到同样的效果? 我正在尝试传输巨大的日志文件(> 1GB)。

UPDATE

我只是使用“readline”模块( http://nodejs.org/api/readline.html )并从中间文件中一次读取一行。 从性能angular度来看,这是不理想的,但这是我现在最好的。 下面的代码似乎工作得很好。

  rl.on('line', function(line) { console.log(line); var str = line.toString(); var re = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2},\d{3}) (.*ERROR) (.*) - (.*)/; if(str.search(re) != -1){ var myArray = str.match(re); var JSONErr = { "Date": myArray[1], "Time": myArray[2], "Error": myArray[5] }; client.write(JSON.stringify(JSONErr)); } }); 

使用“readline”模块( http://nodejs.org/api/readline.html ),从中间文件一次读取一行。 从性能angular度来看,这并不理想,但现在是最好的select。 下面的代码似乎工作得很好:

 rl.on('line', function(line) { console.log(line); var str = line.toString(); var re = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2},\d{3}) (.*ERROR) (.*) - (.*)/; if(str.search(re) != -1){ var myArray = str.match(re); var JSONErr = { "Date": myArray[1], "Time": myArray[2], "Error": myArray[5] }; client.write(JSON.stringify(JSONErr)); } 

});