Nodejs 一个简单的日志module
Nodejs 一个简单的日志module
<br/> <br/>一个简单的日志module, 功能如下 <br/><ul> <br/> <li>时间显示</li> <br/> <li>调用log的文件名与行号显示</li> <br/> <li>不同日志级别使用不同颜色输出</li> <br/> <li>支持stdout输出的同时写入文件日志</li> <br/> <li>文件日志使用缓存以降低io次数</li> <br/></ul> <br/>使用示例 <br/><pre escaped=“true” lang=“javascript”>var log = require(’./log’), <br/> logWithoutFile = log.create(); <br/> logWithFile = log.create(log.WARNING, ‘my.log’), <br/> <br/>logWithoutFile.info(‘info msg’); <br/>logWithoutFile.debug(‘debug msg’); <br/>logWithoutFile.warning(‘warning msg’); <br/>logWithoutFile.error(‘error msg’); <br/>logWithoutFile.trace(‘trace msg’); <br/> <br/>logWithFile.info(‘info msg’); <br/>logWithFile.debug(‘debug msg’); <br/>logWithFile.warning(‘warning msg’); <br/>logWithFile.error(‘error msg’); <br/>logWithFile.trace(‘trace msg’);</pre> <br/>输出效果 <br/> <br/><img title=“cnode-log-demo.jpg” src=“http://static.data.taobaocdn.com/up/nodeclub/2011/03/cnode-log-demo.jpg” border=“0” alt=“cnode-log-demo” width=“579” height=“159” /> <br/> <br/>源码如下 <br/><pre escaped=“true” lang=“javascript”>var fs = require(‘fs’); <br/> <br/>var cwd = process.cwd() + ‘/’, <br/> INFO = 0; <br/> DEBUG = 1; <br/> WARNING = 2; <br/> ERROR = 3; <br/> TRACE = 4; <br/> INIT = 6; <br/> type = [‘INFO’, ‘DEBUG’, ‘WARNING’, ‘ERROR’, ‘TRACE’, ‘’, ‘LOG_INIT’]; <br/> colors = [38, 34, 35, 31, 32, 36, 33]; <br/> bufferSize = 20000; <br/> writeSize = 16384; <br/> <br/>exports.INFO = INFO; <br/>exports.DEBUG = DEBUG; <br/>exports.WARNING = WARNING; <br/>exports.ERROR = ERROR; <br/>exports.TRACE = TRACE; <br/> <br/>function getPos() { <br/> try { <br/> throw new Error(); <br/> } catch(e) { <br/> var pos = e.stack.split(’\n’)[4].split(’(’)[1].split(’)’)[0].split(’:’); <br/> return pos[0].replace(cwd, ‘’) + ‘:’ + pos[1]; <br/> } <br/>} <br/> <br/>function pad2(num) { <br/> return num > 9 ? num : ‘0’ + num; <br/>} <br/> <br/>function getTime() { <br/> var t = new Date(); <br/> return [t.getFullYear(), ‘-’, pad2(t.getMonth() + 1) , ‘-’, pad2(t.getDate()), ’ ‘, <br/> pad2(t.getHours()), ‘:’, pad2(t.getMinutes()), ‘:’, pad2(t.getSeconds())].join(’’); <br/>} <br/> <br/>function formatLog(log, color) { <br/> var tag = head = foot = ‘’; <br/> if (color) { <br/> head = ‘\x1B[’; <br/> foot = ‘\x1B[0m’; <br/> tag = colors[5]+‘m’; <br/> color = colors[log.type]+‘m’; <br/> } <br/> <br/>return [log.time, ’ [’, head, color, type[log.type], foot, ‘] [’, head, tag, log.pos, foot, ‘] ‘, log.msg].join(’’); <br/>} <br/> <br/>exports.create = function(level, file) { <br/> if (!level) { <br/> level = INFO; <br/> } <br/> if (file) { <br/> var buffer = new Buffer(bufferSize); <br/> var pos = 0; <br/> var fd = fs.openSync(file, ‘a’); <br/> process.on(‘exit’, function(){ <br/> fs.writeSync(fd, buffer, 0, pos, null); <br/> }) <br/> } <br/> function log(type, msg) { <br/> if (type < level){ <br/> return; <br/> } <br/> var log = {type:type, msg:msg, time:getTime(), pos:getPos()}; <br/> console.log(formatLog(log, true)); <br/> if (file) { <br/> if (pos >= writeSize) { <br/> fs.writeSync(fd, buffer, 0, pos, null); <br/> pos = 0; <br/> } <br/> pos += buffer.write(formatLog(log) + “\r\n”, pos); <br/> } <br/> } <br/> console.log(formatLog({type:INIT, pos:file, time:getTime(), msg: 'log init with level ’ + type[level]}, true)); <br/> return { <br/> info : function(msg) {log(INFO, msg);}, <br/> debug : function(msg) {log(DEBUG, msg);}, <br/> warning : function(msg) {log(WARNING, msg);}, <br/> error : function(msg) {log(ERROR, msg);}, <br/> trace : function(msg) {log(TRACE, msg);}, <br/> }; <br/>}</pre>
好的,下面是关于“Node.js 一个简单的日志模块”的详细内容:
Node.js 一个简单的日志模块
功能概述
该模块提供了一个简单的日志功能,包含以下特性:
- 显示时间戳
- 显示调用
log
函数的文件名和行号 - 不同的日志级别使用不同的颜色输出
- 支持标准输出(stdout)的同时写入文件日志
- 文件日志使用缓存以降低IO次数
使用示例
var log = require('./log');
var logWithoutFile = log.create();
var 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');
输出效果
源码
var fs = require('fs');
var cwd = process.cwd() + '/';
var INFO = 0;
var DEBUG = 1;
var WARNING = 2;
var ERROR = 3;
var TRACE = 4;
var INIT = 6;
var type = ['INFO', 'DEBUG', 'WARNING', 'ERROR', 'TRACE', '', 'LOG_INIT'];
var colors = [38, 34, 35, 31, 32, 36, 33];
var bufferSize = 20000;
var 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); },
};
}
解释
- 定义常量:定义了不同日志级别的常量。
- 获取位置信息:通过抛出错误来获取调用者的文件名和行号。
- 格式化时间:将当前时间格式化为字符串。
- 格式化日志:根据日志级别添加颜色,并将日志信息格式化为字符串。
- 创建日志对象:创建一个日志对象,可以指定日志级别和日志文件。如果指定了日志文件,则会使用缓冲区来减少IO操作。
希望这些内容能帮助你理解和使用这个简单的日志模块。
实用小模块。buffer是细节,细节体现专业!
buffer的值设置得不专业,清爷迷糊了
偷了个懒而已…
长过3k的单条log毕竟是少数, 这样少做一次bytelength…可以提高点性能
那倒是。如果这个log非常重要,比如计费系统的log,就不能这么搞了
一般来说,INFO和WARNING的日志级别不应该输出DEBUG级别的log <br/>all < debug < info < waring < error < trace
适当的去做一些偷懒来提高性能,对于某些情况还是必要的( 比如:log长度不可能超过3K)。
求server及client完整代码。
var pos = e.stack.split(’\n’)[4].split(’(’)[1].split(’)’)[0].split(’:’); <br/> <br/>有些情况下 是没有()会导致一个错误 <br/> <br/>某种情况我猜测是在不同的文件夹下的原因. <br/> <br/>这是我的修改 <br/> var pos = e.stack.split(/\n/)[4].split(‘at’)[1].replace(’)’, ‘’).replace(’(’, ‘’).replace(’ ', ‘’); <br/> pos = cwd + pos.split(":")[1]; <br/> return pos.replace("\/", ‘’);
你好 , 初学nodeJS <br/>我试了下…… 不知道为什么 <br/>info : function(msg) {log(INFO, msg);}, <br/>这个位置报语法错误% 求详解
如果是计费log,具体需要考虑那些东西呢。能给个思路吗?TX
为了实现一个简单的日志模块,我们可以根据上述描述编写一个Node.js模块。这个模块将提供时间戳、调用文件名和行号、不同日志级别的颜色输出、同时输出到标准输出和文件,并且通过缓存减少IO操作。
以下是根据上述描述编写的日志模块的简化版本:
// log.js
const fs = require('fs');
const util = require('util');
const INFO = 0;
const DEBUG = 1;
const WARNING = 2;
const ERROR = 3;
const TRACE = 4;
const type = ['INFO', 'DEBUG', 'WARNING', 'ERROR', 'TRACE'];
const colors = ['', '\x1b[34m', '\x1b[35m', '\x1b[31m', '\x1b[32m'];
function getPos() {
try {
throw new Error();
} catch (e) {
const stack = e.stack.split('\n')[4];
const matches = stack.match(/\((.+):(\d+)\)$/);
return matches ? `${matches[1]}:${matches[2]}` : '';
}
}
function getTime() {
const date = new Date();
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
}
function formatLog(log, color) {
const tag = colors[log.type];
return `${tag}[${log.time}] [${log.pos}] ${log.msg}\x1b[0m`;
}
exports.create = function (level = INFO, file) {
let buffer = '';
let bufferSize = 1024 * 1024; // 1MB
if (file) {
const fd = fs.openSync(file, 'a');
process.on('exit', () => {
if (buffer) {
fs.writeSync(fd, buffer);
buffer = '';
}
});
}
function log(type, msg) {
if (type < level) return;
const logEntry = {
type,
msg,
time: getTime(),
pos: getPos()
};
console.log(formatLog(logEntry, colors[type]));
if (file) {
buffer += formatLog(logEntry) + '\n';
if (buffer.length > bufferSize) {
fs.writeSync(fd, buffer);
buffer = '';
}
}
}
return {
info: msg => log(INFO, msg),
debug: msg => log(DEBUG, msg),
warning: msg => log(WARNING, msg),
error: msg => log(ERROR, msg),
trace: msg => log(TRACE, msg),
};
};
使用示例:
const log = require('./log');
const logWithoutFile = log.create();
const logWithFile = log.create(log.WARNING, 'app.log');
logWithoutFile.info('info message');
logWithoutFile.debug('debug message');
logWithoutFile.warning('warning message');
logWithoutFile.error('error message');
logWithoutFile.trace('trace message');
logWithFile.info('info message');
logWithFile.debug('debug message');
logWithFile.warning('warning message');
logWithFile.error('error message');
logWithFile.trace('trace message');
这个模块提供了时间戳、调用文件名和行号以及不同日志级别的颜色输出。它还支持将日志同时输出到标准输出和文件,并使用缓冲区来减少IO操作。