一个简单的日志module
发布于 4年前 作者 qingdu 2553 次浏览 最后一次编辑是 3年前



一个简单的日志module, 功能如下


  • 时间显示

  • 调用log的文件名与行号显示

  • 不同日志级别使用不同颜色输出

  • 支持stdout输出的同时写入文件日志

  • 文件日志使用缓存以降低io次数


使用示例
var log = require(‘./log’),

logWithoutFile = log.create();
logWithFile = log.create(log.WARNING, ‘my.log’),

logWithoutFile.info(‘info msg’);
logWithoutFile.debug(‘debug msg’);
logWithoutFile.warning(‘warning msg’);
logWithoutFile.error(‘error msg’);
logWithoutFile.trace(‘trace msg’);

logWithFile.info(‘info msg’);
logWithFile.debug(‘debug msg’);
logWithFile.warning(‘warning msg’);
logWithFile.error(‘error msg’);
logWithFile.trace(‘trace msg’);

输出效果

cnode-log-demo

源码如下
var fs = require(‘fs’);


var cwd = process.cwd() + '/’,
INFO = 0;
DEBUG = 1;
WARNING = 2;
ERROR = 3;
TRACE = 4;
INIT = 6;
type = ['INFO’, 'DEBUG’, 'WARNING’, 'ERROR’, 'TRACE’, '’, ‘LOG_INIT’];
colors = [38, 34, 35, 31, 32, 36, 33];
bufferSize = 20000;
writeSize = 16384;

exports.INFO = INFO;
exports.DEBUG = DEBUG;
exports.WARNING = WARNING;
exports.ERROR = ERROR;
exports.TRACE = TRACE;

function getPos() {
try {
throw new Error();
} catch(e) {
var pos = e.stack.split(‘\n’)[4].split('(')[1].split(')')[0].split(‘:’);
return pos[0].replace(cwd, ‘’) + ‘:’ + pos[1];
}
}

function pad2(num) {
return num > 9 ? num : ‘0’ + num;
}

function getTime() {
var t = new Date();
return [t.getFullYear(), '-', pad2(t.getMonth() + 1) , '-', pad2(t.getDate()), ' ',
pad2(t.getHours()), ':’, pad2(t.getMinutes()), ':’, pad2(t.getSeconds())].join(‘’);
}

function formatLog(log, color) {
var tag = head = foot = '’;
if (color) {
head = '\x1B[';
foot = '\x1B[0m’;
tag = colors[5]+’m’;
color = colors[log.type]+’m’;
}

return [log.time, ' [', head, color, type[log.type], foot, '] [', head, tag, log.pos, foot, '] ', log.msg].join(‘’);
}

exports.create = function(level, file) {
if (!level) {
level = INFO;
}
if (file) {
var buffer = new Buffer(bufferSize);
var pos = 0;
var fd = fs.openSync(file, ‘a’);
process.on('exit’, function(){
fs.writeSync(fd, buffer, 0, pos, null);
})
}
function log(type, msg) {
if (type < level){
return;
}
var log = {type:type, msg:msg, time:getTime(), pos:getPos()};
console.log(formatLog(log, true));
if (file) {
if (pos >= writeSize) {
fs.writeSync(fd, buffer, 0, pos, null);
pos = 0;
}
pos += buffer.write(formatLog(log) + "\r\n", pos);
}
}
console.log(formatLog({type:INIT, pos:file, time:getTime(), msg: 'log init with level ' + type[level]}, true));
return {
info : function(msg) {log(INFO, msg);},
debug : function(msg) {log(DEBUG, msg);},
warning : function(msg) {log(WARNING, msg);},
error : function(msg) {log(ERROR, msg);},
trace : function(msg) {log(TRACE, msg);},
};
}

12 回复

实用小模块。buffer是细节,细节体现专业!

buffer的值设置得不专业,清爷迷糊了

偷了个懒而已…

长过3k的单条log毕竟是少数, 这样少做一次bytelength…可以提高点性能

那倒是。如果这个log非常重要,比如计费系统的log,就不能这么搞了

顶个~~不错的东东。。

一般来说,INFO和WARNING的日志级别不应该输出DEBUG级别的log
all < debug < info < waring < error < trace

适当的去做一些偷懒来提高性能,对于某些情况还是必要的( 比如:log长度不可能超过3K)。

求server及client完整代码。

var pos = e.stack.split(‘\n’)[4].split('(')[1].split(')')[0].split(‘:’);

有些情况下 是没有()会导致一个错误

某种情况我猜测是在不同的文件夹下的原因.

这是我的修改
var pos = e.stack.split(/\n/)[4].split(‘at’)[1].replace(')', ‘’).replace('(', ‘’).replace(' ', ‘’);
pos = cwd + pos.split(“:”)[1];
return pos.replace("\/", ‘’);

你好 , 初学nodeJS
我试了下…… 不知道为什么
info : function(msg) {log(INFO, msg);},
这个位置报语法错误% 求详解

如果是计费log,具体需要考虑那些东西呢。能给个思路吗?TX

回到顶部