diff --git a/lib/appenders/dateFile.js b/lib/appenders/dateFile.js index 317c4e8..6317c68 100644 --- a/lib/appenders/dateFile.js +++ b/lib/appenders/dateFile.js @@ -1,15 +1,16 @@ -var streams = require('../streams'), - layouts = require('../layouts'), - path = require('path'), - os = require('os'), - eol = os.EOL || '\n', - openFiles = []; +"use strict"; +var streams = require('../streams') +, layouts = require('../layouts') +, path = require('path') +, os = require('os') +, eol = os.EOL || '\n' +, openFiles = []; //close open files on process exit. process.on('exit', function() { - openFiles.forEach(function (file) { - file.end(); - }); + openFiles.forEach(function (file) { + file.end(); + }); }); /** @@ -20,33 +21,37 @@ process.on('exit', function() { * @layout layout function for log messages - defaults to basicLayout */ function appender(filename, pattern, alwaysIncludePattern, layout) { - layout = layout || layouts.basicLayout; + layout = layout || layouts.basicLayout; - var logFile = new streams.DateRollingFileStream(filename, pattern, { alwaysIncludePattern: alwaysIncludePattern }); - openFiles.push(logFile); - - return function(logEvent) { - logFile.write(layout(logEvent) + eol, "utf8"); - }; + var logFile = new streams.DateRollingFileStream( + filename, + pattern, + { alwaysIncludePattern: alwaysIncludePattern } + ); + openFiles.push(logFile); + + return function(logEvent) { + logFile.write(layout(logEvent) + eol, "utf8"); + }; } function configure(config, options) { - var layout; + var layout; + + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + + if (!config.alwaysIncludePattern) { + config.alwaysIncludePattern = false; + } + + if (options && options.cwd && !config.absolute) { + config.filename = path.join(options.cwd, config.filename); + } - if (config.layout) { - layout = layouts.layout(config.layout.type, config.layout); - } - - if (!config.alwaysIncludePattern) { - config.alwaysIncludePattern = false; - } - - if (options && options.cwd && !config.absolute) { - config.filename = path.join(options.cwd, config.filename); - } - - return appender(config.filename, config.pattern, config.alwaysIncludePattern, layout); + return appender(config.filename, config.pattern, config.alwaysIncludePattern, layout); } exports.appender = appender; diff --git a/lib/appenders/file.js b/lib/appenders/file.js index d7cfe0e..da0e80b 100644 --- a/lib/appenders/file.js +++ b/lib/appenders/file.js @@ -1,25 +1,29 @@ +"use strict"; var layouts = require('../layouts') - , path = require('path') - , fs = require('fs') - , streams = require('../streams') - , os = require('os') - , eol = os.EOL || '\n' - , openFiles = []; +, path = require('path') +, fs = require('fs') +, streams = require('../streams') +, os = require('os') +, eol = os.EOL || '\n' +, openFiles = []; //close open files on process exit. process.on('exit', function() { - openFiles.forEach(function (file) { - file.end(); - }); + openFiles.forEach(function (file) { + file.end(); + }); }); /** * File Appender writing the logs to a text file. Supports rolling of logs by size. * * @param file file log messages will be written to - * @param layout a function that takes a logevent and returns a string (defaults to basicLayout). - * @param logSize - the maximum size (in bytes) for a log file, if not provided then logs won't be rotated. - * @param numBackups - the number of log files to keep after logSize has been reached (default 5) + * @param layout a function that takes a logevent and returns a string + * (defaults to basicLayout). + * @param logSize - the maximum size (in bytes) for a log file, + * if not provided then logs won't be rotated. + * @param numBackups - the number of log files to keep after logSize + * has been reached (default 5) */ function fileAppender (file, layout, logSize, numBackups) { var bytesWritten = 0; @@ -38,7 +42,12 @@ function fileAppender (file, layout, logSize, numBackups) { numFiles ); } else { - stream = fs.createWriteStream(file, { encoding: "utf8", mode: 0644, flags: 'a' }); + stream = fs.createWriteStream( + file, + { encoding: "utf8", + mode: parseInt('0644', 8), + flags: 'a' } + ); } stream.on("error", function (err) { console.error("log4js.fileAppender - Writing to file %s, error happened ", file, err); diff --git a/lib/appenders/gelf.js b/lib/appenders/gelf.js index 74089be..69a18b7 100644 --- a/lib/appenders/gelf.js +++ b/lib/appenders/gelf.js @@ -1,3 +1,4 @@ +"use strict"; var zlib = require('zlib'); var layouts = require('../layouts'); var levels = require('../levels'); @@ -23,6 +24,13 @@ levelMapping[levels.WARN] = LOG_WARNING; levelMapping[levels.ERROR] = LOG_ERR; levelMapping[levels.FATAL] = LOG_CRIT; +var debug; +if (process.env.NODE_DEBUG && /\blog4js\b/.test(process.env.NODE_DEBUG)) { + debug = function(message) { console.error('LOG4JS: (GELF Appender) %s', message); }; +} else { + debug = function() { }; +} + /** * GELF appender that supports sending UDP packets to a GELF compatible server such as Graylog * @@ -33,60 +41,60 @@ levelMapping[levels.FATAL] = LOG_CRIT; * @param facility - facility to log to (default:nodejs-server) */ function gelfAppender (layout, host, port, hostname, facility) { + + host = host || 'localhost'; + port = port || 12201; + hostname = hostname || require('os').hostname(); + facility = facility || 'nodejs-server'; + layout = layout || layouts.messagePassThroughLayout; + + var client = dgram.createSocket("udp4"); + + process.on('exit', function() { + if (client) client.close(); + }); + + function preparePacket(loggingEvent) { + var msg = {}; + msg.full_message = layout(loggingEvent); + msg.short_message = msg.full_message; + + msg.version="1.0"; + msg.timestamp = msg.timestamp || new Date().getTime() / 1000 >> 0; + msg.host = hostname; + msg.level = levelMapping[loggingEvent.level || levels.DEBUG]; + msg.facility = facility; + return msg; + } + + function sendPacket(packet) { + try { + client.send(packet, 0, packet.length, port, host); + } catch(e) {} + } - host = host || 'localhost'; - port = port || 12201; - hostname = hostname || require('os').hostname(); - facility = facility || 'nodejs-server'; - layout = layout || layouts.messagePassThroughLayout; - - var client = dgram.createSocket("udp4"); - - process.on('exit', function() { - if (client) client.close(); + return function(loggingEvent) { + var message = preparePacket(loggingEvent); + zlib.gzip(new Buffer(JSON.stringify(message)), function(err, packet) { + if (err) { + console.error(err.stack); + } else { + if (packet.length > 8192) { + debug("Message packet length (" + packet.length + ") is larger than 8k. Not sending"); + } else { + sendPacket(packet); + } + } }); - - function preparePacket(loggingEvent) { - var msg = {}; - msg.full_message = layout(loggingEvent); - msg.short_message = msg.full_message; - - msg.version="1.0"; - msg.timestamp = msg.timestamp || new Date().getTime() / 1000 >> 0; - msg.host = hostname; - msg.level = levelMapping[loggingEvent.level || levels.DEBUG]; - msg.facility = facility; - return msg; - } - - function sendPacket(packet) { - try { - client.send(packet, 0, packet.length, port, host); - } catch(e) {} - } - - return function(loggingEvent) { - var message = preparePacket(loggingEvent); - zlib.gzip(new Buffer(JSON.stringify(message)), function(err, packet) { - if (err) { - console.error(err.stack); - } else { - if (packet.length > 8192) { - util.debug("Message packet length (" + packet.length + ") is larger than 8k. Not sending"); - } else { - sendPacket(packet); - } - } - }); - }; + }; } function configure(config) { - var layout; - if (config.layout) { - layout = layouts.layout(config.layout.type, config.layout); - } - return gelfAppender(layout, config.host, config.port, config.hostname, config.facility); + var layout; + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + return gelfAppender(layout, config.host, config.port, config.hostname, config.facility); } exports.appender = gelfAppender; diff --git a/lib/appenders/hookio.js b/lib/appenders/hookio.js index 4f2dfe2..7821d79 100644 --- a/lib/appenders/hookio.js +++ b/lib/appenders/hookio.js @@ -1,7 +1,8 @@ -var log4js = require('../log4js'); -var layouts = require('../layouts'); -var Hook = require('hook.io').Hook; -var util = require('util'); +"use strict"; +var log4js = require('../log4js') +, layouts = require('../layouts') +, Hook = require('hook.io').Hook +, util = require('util'); var Logger = function createLogger(options) { var self = this; @@ -13,7 +14,7 @@ var Logger = function createLogger(options) { actualAppender(loggingEvent); }); }); -} +}; util.inherits(Logger, Hook); function deserializeLoggingEvent(loggingEvent) { @@ -42,7 +43,7 @@ function getBufferedHook(hook, eventName) { hook.on('hook::ready', function emptyBuffer() { hookBuffer.forEach(function logBufferItem(loggingEvent) { hook.emit(eventName, loggingEvent); - }) + }); hookReady = true; }); @@ -52,7 +53,7 @@ function getBufferedHook(hook, eventName) { } else { hookBuffer.push(loggingEvent); } - } + }; } function createAppender(hookioOptions) { diff --git a/lib/appenders/logLevelFilter.js b/lib/appenders/logLevelFilter.js index 8904094..ddbb61c 100644 --- a/lib/appenders/logLevelFilter.js +++ b/lib/appenders/logLevelFilter.js @@ -1,19 +1,20 @@ -var levels = require('../levels'); -var log4js = require('../log4js'); +"use strict"; +var levels = require('../levels') +, log4js = require('../log4js'); function logLevelFilter (levelString, appender) { - var level = levels.toLevel(levelString); - return function(logEvent) { - if (logEvent.level.isGreaterThanOrEqualTo(level)) { - appender(logEvent); - } + var level = levels.toLevel(levelString); + return function(logEvent) { + if (logEvent.level.isGreaterThanOrEqualTo(level)) { + appender(logEvent); } + }; } function configure(config) { - log4js.loadAppender(config.appender.type); - var appender = log4js.appenderMakers[config.appender.type](config.appender); - return logLevelFilter(config.level, appender); + log4js.loadAppender(config.appender.type); + var appender = log4js.appenderMakers[config.appender.type](config.appender); + return logLevelFilter(config.level, appender); } exports.appender = logLevelFilter; diff --git a/lib/appenders/multiprocess.js b/lib/appenders/multiprocess.js index 3d0f2bf..2a1d56f 100644 --- a/lib/appenders/multiprocess.js +++ b/lib/appenders/multiprocess.js @@ -1,6 +1,7 @@ -var log4js = require('../log4js'), - net = require('net'), - END_MSG = '__LOG4JS__'; +"use strict"; +var log4js = require('../log4js') +, net = require('net') +, END_MSG = '__LOG4JS__'; /** * Creates a server, listening on config.loggerPort, config.loggerHost. @@ -8,120 +9,120 @@ var log4js = require('../log4js'), * set up that appender). */ function logServer(config) { - - /** - * Takes a utf-8 string, returns an object with - * the correct log properties. - */ - function deserializeLoggingEvent(clientSocket, msg) { - var loggingEvent; - try { - loggingEvent = JSON.parse(msg); - loggingEvent.startTime = new Date(loggingEvent.startTime); - loggingEvent.level = log4js.levels.toLevel(loggingEvent.level.levelStr); - } catch (e) { - // JSON.parse failed, just log the contents probably a naughty. - loggingEvent = { - startTime: new Date(), - categoryName: 'log4js', - level: log4js.levels.ERROR, - data: [ 'Unable to parse log:', msg ] - }; - } - - loggingEvent.remoteAddress = clientSocket.remoteAddress; - loggingEvent.remotePort = clientSocket.remotePort; - - return loggingEvent; + + /** + * Takes a utf-8 string, returns an object with + * the correct log properties. + */ + function deserializeLoggingEvent(clientSocket, msg) { + var loggingEvent; + try { + loggingEvent = JSON.parse(msg); + loggingEvent.startTime = new Date(loggingEvent.startTime); + loggingEvent.level = log4js.levels.toLevel(loggingEvent.level.levelStr); + } catch (e) { + // JSON.parse failed, just log the contents probably a naughty. + loggingEvent = { + startTime: new Date(), + categoryName: 'log4js', + level: log4js.levels.ERROR, + data: [ 'Unable to parse log:', msg ] + }; } - var actualAppender = config.actualAppender, - server = net.createServer(function serverCreated(clientSocket) { - clientSocket.setEncoding('utf8'); - var logMessage = ''; - - function logTheMessage(msg) { - if (logMessage.length > 0) { - actualAppender(deserializeLoggingEvent(clientSocket, msg)); - } - } - - function chunkReceived(chunk) { - var event; - logMessage += chunk || ''; - if (logMessage.indexOf(END_MSG) > -1) { - event = logMessage.substring(0, logMessage.indexOf(END_MSG)); - logTheMessage(event); - logMessage = logMessage.substring(event.length + END_MSG.length) || ''; - //check for more, maybe it was a big chunk - chunkReceived(); - } - } - - clientSocket.on('data', chunkReceived); - clientSocket.on('end', chunkReceived); - }); - - server.listen(config.loggerPort || 5000, config.loggerHost || 'localhost'); - - return actualAppender; + loggingEvent.remoteAddress = clientSocket.remoteAddress; + loggingEvent.remotePort = clientSocket.remotePort; + + return loggingEvent; + } + + var actualAppender = config.actualAppender, + server = net.createServer(function serverCreated(clientSocket) { + clientSocket.setEncoding('utf8'); + var logMessage = ''; + + function logTheMessage(msg) { + if (logMessage.length > 0) { + actualAppender(deserializeLoggingEvent(clientSocket, msg)); + } + } + + function chunkReceived(chunk) { + var event; + logMessage += chunk || ''; + if (logMessage.indexOf(END_MSG) > -1) { + event = logMessage.substring(0, logMessage.indexOf(END_MSG)); + logTheMessage(event); + logMessage = logMessage.substring(event.length + END_MSG.length) || ''; + //check for more, maybe it was a big chunk + chunkReceived(); + } + } + + clientSocket.on('data', chunkReceived); + clientSocket.on('end', chunkReceived); + }); + + server.listen(config.loggerPort || 5000, config.loggerHost || 'localhost'); + + return actualAppender; } function workerAppender(config) { - var canWrite = false, - buffer = [], - socket; - - createSocket(); - - function createSocket() { - socket = net.createConnection(config.loggerPort || 5000, config.loggerHost || 'localhost'); - socket.on('connect', function() { - emptyBuffer(); - canWrite = true; - }); - socket.on('timeout', socket.end.bind(socket)); - //don't bother listening for 'error', 'close' gets called after that anyway - socket.on('close', createSocket); + var canWrite = false, + buffer = [], + socket; + + createSocket(); + + function createSocket() { + socket = net.createConnection(config.loggerPort || 5000, config.loggerHost || 'localhost'); + socket.on('connect', function() { + emptyBuffer(); + canWrite = true; + }); + socket.on('timeout', socket.end.bind(socket)); + //don't bother listening for 'error', 'close' gets called after that anyway + socket.on('close', createSocket); + } + + function emptyBuffer() { + var evt; + while ((evt = buffer.shift())) { + write(evt); } - - function emptyBuffer() { - var evt; - while ((evt = buffer.shift())) { - write(evt); - } + } + + function write(loggingEvent) { + socket.write(JSON.stringify(loggingEvent), 'utf8'); + socket.write(END_MSG, 'utf8'); + } + + return function log(loggingEvent) { + if (canWrite) { + write(loggingEvent); + } else { + buffer.push(loggingEvent); } - - function write(loggingEvent) { - socket.write(JSON.stringify(loggingEvent), 'utf8'); - socket.write(END_MSG, 'utf8'); - } - - return function log(loggingEvent) { - if (canWrite) { - write(loggingEvent); - } else { - buffer.push(loggingEvent); - } - }; + }; } function createAppender(config) { - if (config.mode === 'master') { - return logServer(config); - } else { - return workerAppender(config); - } + if (config.mode === 'master') { + return logServer(config); + } else { + return workerAppender(config); + } } function configure(config, options) { - var actualAppender; - if (config.appender && config.mode === 'master') { - log4js.loadAppender(config.appender.type); - actualAppender = log4js.appenderMakers[config.appender.type](config.appender, options); - config.actualAppender = actualAppender; - } - return createAppender(config); + var actualAppender; + if (config.appender && config.mode === 'master') { + log4js.loadAppender(config.appender.type); + actualAppender = log4js.appenderMakers[config.appender.type](config.appender, options); + config.actualAppender = actualAppender; + } + return createAppender(config); } exports.appender = createAppender; diff --git a/lib/appenders/smtp.js b/lib/appenders/smtp.js index 876508b..5cfd713 100644 --- a/lib/appenders/smtp.js +++ b/lib/appenders/smtp.js @@ -1,14 +1,17 @@ -var layouts = require("../layouts"), -mailer = require("nodemailer"), -os = require('os'); +"use strict"; +var layouts = require("../layouts") +, mailer = require("nodemailer") +, os = require('os'); /** * SMTP Appender. Sends logging events using SMTP protocol. -* It can either send an email on each event or group several logging events gathered during specified interval. +* It can either send an email on each event or group several +* logging events gathered during specified interval. * * @param config appender configuration data +* config.sendInterval time between log emails (in seconds), if 0 +* then every event sends an email * @param layout a function that takes a logevent and returns a string (defaults to basicLayout). -* all events are buffered and sent in one email during this time; if 0 than every event sends an email */ function smtpAppender(config, layout) { layout = layout || layouts.basicLayout; @@ -19,7 +22,7 @@ function smtpAppender(config, layout) { var sendTimer; function sendBuffer() { - if (logEventBuffer.length == 0) { + if (logEventBuffer.length === 0) { return; } @@ -31,11 +34,11 @@ function smtpAppender(config, layout) { } var msg = { - to: config.recipients, - subject: config.subject || subjectLayout(firstEvent), - text: body, - headers: {"Hostname": os.hostname()} - }; + to: config.recipients, + subject: config.subject || subjectLayout(firstEvent), + text: body, + headers: {"Hostname": os.hostname()} + }; if (config.sender) { msg.from = config.sender; } diff --git a/lib/connect-logger.js b/lib/connect-logger.js index 5b8a94a..454ee4a 100644 --- a/lib/connect-logger.js +++ b/lib/connect-logger.js @@ -1,4 +1,9 @@ +"use strict"; var levels = require("./levels"); +var DEFAULT_FORMAT = ':remote-addr - -' + + ' ":method :url HTTP/:http-version"' + + ' :status :content-length ":referrer"' + + ' ":user-agent"'; /** * Log requests with the given `options` or a `format` string. * @@ -26,7 +31,7 @@ var levels = require("./levels"); * @api public */ - function getLogger(logger4js, options) { +function getLogger(logger4js, options) { if ('object' == typeof options) { options = options || {}; } else if (options) { @@ -36,20 +41,19 @@ var levels = require("./levels"); } var thislogger = logger4js - , level = levels.toLevel(options.level, levels.INFO) - , fmt = options.format || ':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"' - , nolog = options.nolog ? createNoLogCondition(options.nolog) : null; + , level = levels.toLevel(options.level, levels.INFO) + , fmt = options.format || DEFAULT_FORMAT + , nolog = options.nolog ? createNoLogCondition(options.nolog) : null; - return function (req, res, next) { - - // mount safety - if (req._logging) return next(); + return function (req, res, next) { + // mount safety + if (req._logging) return next(); // nologs if (nolog && nolog.test(req.originalUrl)) return next(); if (thislogger.isLevelEnabled(level) || options.level === 'auto') { - - var start = +new Date + + var start = new Date() , statusCode , writeHead = res.writeHead , end = res.end @@ -57,7 +61,7 @@ var levels = require("./levels"); // flag as logging req._logging = true; - + // proxy for statusCode. res.writeHead = function(code, headers){ res.writeHead = writeHead; @@ -71,15 +75,15 @@ var levels = require("./levels"); if(code >= 300) level = levels.WARN; if(code >= 400) level = levels.ERROR; } else { - level = levels.toLevel(options.level, levels.INFO) + level = levels.toLevel(options.level, levels.INFO); } }; - + // proxy end to output a line to the provided logger. res.end = function(chunk, encoding) { res.end = end; res.end(chunk, encoding); - res.responseTime = +new Date - start; + res.responseTime = new Date() - start; if (thislogger.isLevelEnabled(level)) { if (typeof fmt === 'function') { var line = fmt(req, res, function(str){ return format(str, req, res); }); @@ -90,10 +94,10 @@ var levels = require("./levels"); } }; } - - //ensure next gets always called - next(); -}; + + //ensure next gets always called + next(); + }; } /** @@ -106,25 +110,34 @@ var levels = require("./levels"); * @api private */ - function format(str, req, res) { +function format(str, req, res) { return str - .replace(':url', req.originalUrl) - .replace(':method', req.method) - .replace(':status', res.__statusCode || res.statusCode) - .replace(':response-time', res.responseTime) - .replace(':date', new Date().toUTCString()) - .replace(':referrer', req.headers['referer'] || req.headers['referrer'] || '') - .replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor) - .replace(':remote-addr', req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress))) - .replace(':user-agent', req.headers['user-agent'] || '') - .replace(':content-length', (res._headers && res._headers['content-length']) || (res.__headers && res.__headers['Content-Length']) || '-') - .replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; }) - .replace(/:res\[([^\]]+)\]/g, function(_, field){ - return res._headers - ? (res._headers[field.toLowerCase()] || res.__headers[field]) - : (res.__headers && res.__headers[field]); - }); - } + .replace(':url', req.originalUrl) + .replace(':method', req.method) + .replace(':status', res.__statusCode || res.statusCode) + .replace(':response-time', res.responseTime) + .replace(':date', new Date().toUTCString()) + .replace(':referrer', req.headers.referer || req.headers.referrer || '') + .replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor) + .replace( + ':remote-addr', + req.socket && + (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)) + ) + .replace(':user-agent', req.headers['user-agent'] || '') + .replace( + ':content-length', + (res._headers && res._headers['content-length']) || + (res.__headers && res.__headers['Content-Length']) || + '-' + ) + .replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; }) + .replace(/:res\[([^\]]+)\]/g, function(_, field){ + return res._headers ? + (res._headers[field.toLowerCase()] || res.__headers[field]) + : (res.__headers && res.__headers[field]); + }); +} /** * Return RegExp Object about nolog @@ -141,8 +154,10 @@ var levels = require("./levels"); * NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.gif?fuga * LOGGING http://example.com/hoge.agif * 1.2 in "\\.gif|\\.jpg$" - * NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.gif?fuga and http://example.com/hoge.jpg?fuga - * LOGGING http://example.com/hoge.agif, http://example.com/hoge.ajpg and http://example.com/hoge.jpg?hoge + * NOT LOGGING http://example.com/hoge.gif and + * http://example.com/hoge.gif?fuga and http://example.com/hoge.jpg?fuga + * LOGGING http://example.com/hoge.agif, + * http://example.com/hoge.ajpg and http://example.com/hoge.jpg?hoge * 1.3 in "\\.(gif|jpe?g|png)$" * NOT LOGGING http://example.com/hoge.gif and http://example.com/hoge.jpeg * LOGGING http://example.com/hoge.gif?uid=2 and http://example.com/hoge.jpg?pid=3 @@ -153,26 +168,28 @@ var levels = require("./levels"); * 3.1 ["\\.jpg$", "\\.png", "\\.gif"] * SAME AS "\\.jpg|\\.png|\\.gif" */ - function createNoLogCondition(nolog, type) { - if(!nolog) return null; +function createNoLogCondition(nolog, type) { + if (!nolog) return null; type = type || ''; - - if(nolog instanceof RegExp){ - if(type === 'string') + + if (nolog instanceof RegExp) { + if (type === 'string') { return nolog.source; + } return nolog; - } else if(typeof nolog === 'string'){ - if(type === 'string') + } else if (typeof nolog === 'string') { + if (type === 'string') { return nolog; - try{ + } + try { return new RegExp(nolog); } catch (ex) { return null; } - } else if(nolog instanceof Array){ - var regexps = nolog.map(function(o){ return createNoLogCondition(o, 'string')}); + } else if (nolog instanceof Array) { + var regexps = nolog.map(function(o){ return createNoLogCondition(o, 'string'); }); return new RegExp(regexps.join('|')); } - } +} - exports.connectLogger = getLogger; +exports.connectLogger = getLogger; diff --git a/lib/layouts.js b/lib/layouts.js index 931fc48..5ab02a2 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -1,106 +1,110 @@ +"use strict"; var dateFormat = require('./date_format') - , os = require('os') - , eol = os.EOL || '\n' - , util = require('util') - , replacementRegExp = /%[sdj]/g - , layoutMakers = { - "messagePassThrough": function() { return messagePassThroughLayout; } - , "basic": function() { return basicLayout; } - , "colored": function() { return colouredLayout; } - , "coloured": function() { return colouredLayout; } - , "pattern": function (config) { - var pattern = config.pattern || undefined; - var tokens = config.tokens || undefined; - return patternLayout(pattern, tokens); +, os = require('os') +, eol = os.EOL || '\n' +, util = require('util') +, replacementRegExp = /%[sdj]/g +, layoutMakers = { + "messagePassThrough": function() { return messagePassThroughLayout; }, + "basic": function() { return basicLayout; }, + "colored": function() { return colouredLayout; }, + "coloured": function() { return colouredLayout; }, + "pattern": function (config) { + var pattern = config.pattern || undefined; + var tokens = config.tokens || undefined; + return patternLayout(pattern, tokens); } - } - , colours = { - ALL: "grey" - , TRACE: "blue" - , DEBUG: "cyan" - , INFO: "green" - , WARN: "yellow" - , ERROR: "red" - , FATAL: "magenta" - , OFF: "grey" - }; +} +, colours = { + ALL: "grey", + TRACE: "blue", + DEBUG: "cyan", + INFO: "green", + WARN: "yellow", + ERROR: "red", + FATAL: "magenta", + OFF: "grey" +}; function formatLogData(logData) { - var output = "" - , data = Array.isArray(logData) ? logData.slice() : Array.prototype.slice.call(arguments) - , format = data.shift(); - - if (typeof format === "string") { - output = format.replace(replacementRegExp, function(match) { - switch (match) { - case "%s": return new String(data.shift()); - case "%d": return new Number(data.shift()); - case "%j": return JSON.stringify(data.shift()); - default: - return match; - }; - }); - } else { - //put it back, it's not a format string - data.unshift(format); - } - - data.forEach(function (item) { - if (output) { - output += ' '; - } - output += util.inspect(item); - if (item && item.stack) { - output += "\n" + item.stack; - } + var output = "" + , data = Array.isArray(logData) ? logData.slice() : Array.prototype.slice.call(arguments) + , format = data.shift(); + + if (typeof format === "string") { + output = format.replace(replacementRegExp, function(match) { + switch (match) { + case "%s": + return data.shift().toString(); + case "%d": + return new Number(data.shift()); + case "%j": + return JSON.stringify(data.shift()); + default: + return match; + } }); + } else { + //put it back, it's not a format string + data.unshift(format); + } - return output; + data.forEach(function (item) { + if (output) { + output += ' '; + } + output += util.inspect(item); + if (item && item.stack) { + output += "\n" + item.stack; + } + }); + + return output; } var styles = { //styles - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - //grayscale - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [90, 39], - //colors - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + //grayscale + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [90, 39], + //colors + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] }; function colorizeStart(style) { - return style ? '\033[' + styles[style][0] + 'm' : ''; + return style ? '\x1B[' + styles[style][0] + 'm' : ''; } function colorizeEnd(style) { - return style ? '\033[' + styles[style][1] + 'm' : ''; + return style ? '\x1B[' + styles[style][1] + 'm' : ''; } /** * Taken from masylum's fork (https://github.com/masylum/log4js-node) */ function colorize (str, style) { - return colorizeStart(style) + str + colorizeEnd(style); + return colorizeStart(style) + str + colorizeEnd(style); } function timestampLevelAndCategory(loggingEvent, colour) { - var output = colorize( - formatLogData( - '[%s] [%s] %s - ' - , dateFormat.asString(loggingEvent.startTime) - , loggingEvent.level - , loggingEvent.categoryName - ) - , colour - ); - return output; + var output = colorize( + formatLogData( + '[%s] [%s] %s - ' + , dateFormat.asString(loggingEvent.startTime) + , loggingEvent.level + , loggingEvent.categoryName + ) + , colour + ); + return output; } /** @@ -113,7 +117,7 @@ function timestampLevelAndCategory(loggingEvent, colour) { * @author Stephan Strittmatter */ function basicLayout (loggingEvent) { - return timestampLevelAndCategory(loggingEvent) + formatLogData(loggingEvent.data); + return timestampLevelAndCategory(loggingEvent) + formatLogData(loggingEvent.data); } /** @@ -121,11 +125,14 @@ function basicLayout (loggingEvent) { * same as basicLayout, but with colours. */ function colouredLayout (loggingEvent) { - return timestampLevelAndCategory(loggingEvent, colours[loggingEvent.level.toString()]) + formatLogData(loggingEvent.data); + return timestampLevelAndCategory( + loggingEvent, + colours[loggingEvent.level.toString()] + ) + formatLogData(loggingEvent.data); } function messagePassThroughLayout (loggingEvent) { - return formatLogData(loggingEvent.data); + return formatLogData(loggingEvent.data); } /** @@ -158,140 +165,140 @@ function messagePassThroughLayout (loggingEvent) { * @author Jan Schmidle */ function patternLayout (pattern, tokens) { - var TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n"; - var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([\[\]cdmnprx%])(\{([^\}]+)\})?|([^%]+)/; + var TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n"; + var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([\[\]cdmnprx%])(\{([^\}]+)\})?|([^%]+)/; + + pattern = pattern || TTCC_CONVERSION_PATTERN; + + return function(loggingEvent) { + var formattedString = ""; + var result; + var searchString = pattern; + + while ((result = regex.exec(searchString))) { + var matchedString = result[0]; + var padding = result[1]; + var truncation = result[2]; + var conversionCharacter = result[3]; + var specifier = result[5]; + var text = result[6]; + + // Check if the pattern matched was just normal text + if (text) { + formattedString += "" + text; + } else { + // Create a raw replacement string based on the conversion + // character and specifier + var replacement = ""; + switch(conversionCharacter) { + case "c": + var loggerName = loggingEvent.categoryName; + if (specifier) { + var precision = parseInt(specifier, 10); + var loggerNameBits = loggingEvent.categoryName.split("."); + if (precision >= loggerNameBits.length) { + replacement = loggerName; + } else { + replacement = loggerNameBits.slice(loggerNameBits.length - precision).join("."); + } + } else { + replacement = loggerName; + } + break; + case "d": + var format = dateFormat.ISO8601_FORMAT; + if (specifier) { + format = specifier; + // Pick up special cases + if (format == "ISO8601") { + format = dateFormat.ISO8601_FORMAT; + } else if (format == "ABSOLUTE") { + format = dateFormat.ABSOLUTETIME_FORMAT; + } else if (format == "DATE") { + format = dateFormat.DATETIME_FORMAT; + } + } + // Format the date + replacement = dateFormat.asString(format, loggingEvent.startTime); + break; + case "m": + replacement = formatLogData(loggingEvent.data); + break; + case "n": + replacement = eol; + break; + case "p": + replacement = loggingEvent.level.toString(); + break; + case "r": + replacement = "" + loggingEvent.startTime.toLocaleTimeString(); + break; + case "[": + replacement = colorizeStart(colours[loggingEvent.level.toString()]); + break; + case "]": + replacement = colorizeEnd(colours[loggingEvent.level.toString()]); + break; + case "%": + replacement = "%"; + break; + case "x": + if(typeof(tokens[specifier]) !== 'undefined') { + if(typeof(tokens[specifier]) === 'function') { + replacement = tokens[specifier](); + } else { + replacement = tokens[specifier]; + } + } else { + replacement = matchedString; + } + break; + default: + replacement = matchedString; + break; + } + // Format the replacement according to any padding or + // truncation specified + + var len; + + // First, truncation + if (truncation) { + len = parseInt(truncation.substr(1), 10); + replacement = replacement.substring(0, len); + } + // Next, padding + if (padding) { + if (padding.charAt(0) == "-") { + len = parseInt(padding.substr(1), 10); + // Right pad with spaces + while (replacement.length < len) { + replacement += " "; + } + } else { + len = parseInt(padding, 10); + // Left pad with spaces + while (replacement.length < len) { + replacement = " " + replacement; + } + } + } + formattedString += replacement; + } + searchString = searchString.substr(result.index + result[0].length); + } + return formattedString; + }; - pattern = pattern || TTCC_CONVERSION_PATTERN; - - return function(loggingEvent) { - var formattedString = ""; - var result; - var searchString = pattern; - - while ((result = regex.exec(searchString))) { - var matchedString = result[0]; - var padding = result[1]; - var truncation = result[2]; - var conversionCharacter = result[3]; - var specifier = result[5]; - var text = result[6]; - - // Check if the pattern matched was just normal text - if (text) { - formattedString += "" + text; - } else { - // Create a raw replacement string based on the conversion - // character and specifier - var replacement = ""; - switch(conversionCharacter) { - case "c": - var loggerName = loggingEvent.categoryName; - if (specifier) { - var precision = parseInt(specifier, 10); - var loggerNameBits = loggingEvent.categoryName.split("."); - if (precision >= loggerNameBits.length) { - replacement = loggerName; - } else { - replacement = loggerNameBits.slice(loggerNameBits.length - precision).join("."); - } - } else { - replacement = loggerName; - } - break; - case "d": - var format = dateFormat.ISO8601_FORMAT; - if (specifier) { - format = specifier; - // Pick up special cases - if (format == "ISO8601") { - format = dateFormat.ISO8601_FORMAT; - } else if (format == "ABSOLUTE") { - format = dateFormat.ABSOLUTETIME_FORMAT; - } else if (format == "DATE") { - format = dateFormat.DATETIME_FORMAT; - } - } - // Format the date - replacement = dateFormat.asString(format, loggingEvent.startTime); - break; - case "m": - replacement = formatLogData(loggingEvent.data); - break; - case "n": - replacement = eol; - break; - case "p": - replacement = loggingEvent.level.toString(); - break; - case "r": - replacement = "" + loggingEvent.startTime.toLocaleTimeString(); - break; - case "[": - replacement = colorizeStart(colours[loggingEvent.level.toString()]); - break; - case "]": - replacement = colorizeEnd(colours[loggingEvent.level.toString()]); - break; - case "%": - replacement = "%"; - break; - case "x": - if(typeof(tokens[specifier]) !== 'undefined') { - if(typeof(tokens[specifier]) === 'function') { - replacement = tokens[specifier](); - } else { - replacement = tokens[specifier]; - } - } else { - replacement = matchedString; - } - break; - default: - replacement = matchedString; - break; - } - // Format the replacement according to any padding or - // truncation specified - - var len; - - // First, truncation - if (truncation) { - len = parseInt(truncation.substr(1), 10); - replacement = replacement.substring(0, len); - } - // Next, padding - if (padding) { - if (padding.charAt(0) == "-") { - len = parseInt(padding.substr(1), 10); - // Right pad with spaces - while (replacement.length < len) { - replacement += " "; - } - } else { - len = parseInt(padding, 10); - // Left pad with spaces - while (replacement.length < len) { - replacement = " " + replacement; - } - } - } - formattedString += replacement; - } - searchString = searchString.substr(result.index + result[0].length); - } - return formattedString; - }; - -}; +} module.exports = { - basicLayout: basicLayout - , messagePassThroughLayout: messagePassThroughLayout - , patternLayout: patternLayout - , colouredLayout: colouredLayout - , coloredLayout: colouredLayout - , layout: function(name, config) { - return layoutMakers[name] && layoutMakers[name](config); - } + basicLayout: basicLayout, + messagePassThroughLayout: messagePassThroughLayout, + patternLayout: patternLayout, + colouredLayout: colouredLayout, + coloredLayout: colouredLayout, + layout: function(name, config) { + return layoutMakers[name] && layoutMakers[name](config); + } }; diff --git a/lib/log4js.js b/lib/log4js.js index 6c3ce0d..3bda547 100644 --- a/lib/log4js.js +++ b/lib/log4js.js @@ -1,3 +1,4 @@ +"use strict"; /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +13,6 @@ * limitations under the License. */ -/*jsl:option explicit*/ - /** * @fileoverview log4js is a library to log in JavaScript in similar manner * than in log4j for Java. The API should be nearly the same. @@ -57,10 +56,10 @@ var events = require('events') , loggers = {} , appenderMakers = {} , defaultConfig = { - appenders: [ - { type: "console" } - ], - replaceConsole: false + appenders: [ + { type: "console" } + ], + replaceConsole: false }; /** @@ -71,102 +70,102 @@ var events = require('events') */ function getLogger (categoryName) { - // Use default logger if categoryName is not specified or invalid - if (!(typeof categoryName == "string")) { - categoryName = Logger.DEFAULT_CATEGORY; - } + // Use default logger if categoryName is not specified or invalid + if (typeof categoryName !== "string") { + categoryName = Logger.DEFAULT_CATEGORY; + } - var appenderList; - if (!loggers[categoryName]) { - // Create the logger for this name if it doesn't already exist - loggers[categoryName] = new Logger(categoryName); - if (appenders[categoryName]) { - appenderList = appenders[categoryName]; - appenderList.forEach(function(appender) { - loggers[categoryName].addListener("log", appender); - }); - } - if (appenders[ALL_CATEGORIES]) { - appenderList = appenders[ALL_CATEGORIES]; - appenderList.forEach(function(appender) { - loggers[categoryName].addListener("log", appender); - }); - } + var appenderList; + if (!loggers[categoryName]) { + // Create the logger for this name if it doesn't already exist + loggers[categoryName] = new Logger(categoryName); + if (appenders[categoryName]) { + appenderList = appenders[categoryName]; + appenderList.forEach(function(appender) { + loggers[categoryName].addListener("log", appender); + }); } - - return loggers[categoryName]; + if (appenders[ALL_CATEGORIES]) { + appenderList = appenders[ALL_CATEGORIES]; + appenderList.forEach(function(appender) { + loggers[categoryName].addListener("log", appender); + }); + } + } + + return loggers[categoryName]; } /** * args are appender, then zero or more categories */ function addAppender () { - var args = Array.prototype.slice.call(arguments); - var appender = args.shift(); - if (args.length == 0 || args[0] === undefined) { - args = [ ALL_CATEGORIES ]; + var args = Array.prototype.slice.call(arguments); + var appender = args.shift(); + if (args.length === 0 || args[0] === undefined) { + args = [ ALL_CATEGORIES ]; + } + //argument may already be an array + if (Array.isArray(args[0])) { + args = args[0]; + } + + args.forEach(function(category) { + if (!appenders[category]) { + appenders[category] = []; } - //argument may already be an array - if (Array.isArray(args[0])) { - args = args[0]; + appenders[category].push(appender); + + if (category === ALL_CATEGORIES) { + for (var logger in loggers) { + if (loggers.hasOwnProperty(logger)) { + loggers[logger].addListener("log", appender); + } + } + } else if (loggers[category]) { + loggers[category].addListener("log", appender); } - - args.forEach(function(category) { - if (!appenders[category]) { - appenders[category] = []; - } - appenders[category].push(appender); - - if (category === ALL_CATEGORIES) { - for (var logger in loggers) { - if (loggers.hasOwnProperty(logger)) { - loggers[logger].addListener("log", appender); - } - } - } else if (loggers[category]) { - loggers[category].addListener("log", appender); - } - }); + }); } function clearAppenders () { - appenders = {}; - for (var logger in loggers) { - if (loggers.hasOwnProperty(logger)) { - loggers[logger].removeAllListeners("log"); - } + appenders = {}; + for (var logger in loggers) { + if (loggers.hasOwnProperty(logger)) { + loggers[logger].removeAllListeners("log"); } + } } function configureAppenders(appenderList, options) { - clearAppenders(); - if (appenderList) { - appenderList.forEach(function(appenderConfig) { - loadAppender(appenderConfig.type); - var appender; - appenderConfig.makers = appenderMakers; - appender = appenderMakers[appenderConfig.type](appenderConfig, options); - if (appender) { - addAppender(appender, appenderConfig.category); - } else { - throw new Error("log4js configuration problem for "+util.inspect(appenderConfig)); - } - }); - } + clearAppenders(); + if (appenderList) { + appenderList.forEach(function(appenderConfig) { + loadAppender(appenderConfig.type); + var appender; + appenderConfig.makers = appenderMakers; + appender = appenderMakers[appenderConfig.type](appenderConfig, options); + if (appender) { + addAppender(appender, appenderConfig.category); + } else { + throw new Error("log4js configuration problem for "+util.inspect(appenderConfig)); + } + }); + } } function configureLevels(levels) { - if (levels) { - for (var category in levels) { - if (levels.hasOwnProperty(category)) { - getLogger(category).setLevel(levels[category]); - } - } + if (levels) { + for (var category in levels) { + if (levels.hasOwnProperty(category)) { + getLogger(category).setLevel(levels[category]); + } } + } } function setGlobalLogLevel(level) { - Logger.prototype.level = levels.toLevel(level, levels.TRACE); + Logger.prototype.level = levels.toLevel(level, levels.TRACE); } /** @@ -175,143 +174,152 @@ function setGlobalLogLevel(level) { * @static */ function getDefaultLogger () { - return getLogger(Logger.DEFAULT_CATEGORY); + return getLogger(Logger.DEFAULT_CATEGORY); } var configState = {}; function loadConfigurationFile(filename) { - if (filename && (!configState.lastFilename || filename !== configState.lastFilename || - !configState.lastMTime || fs.statSync(filename).mtime !== configState.lastMTime)) { - configState.lastFilename = filename; - configState.lastMTime = fs.statSync(filename).mtime; - return JSON.parse(fs.readFileSync(filename, "utf8")); - } - return undefined; + if (filename && + (!configState.lastFilename || + filename !== configState.lastFilename || + !configState.lastMTime || + fs.statSync(filename).mtime !== configState.lastMTime) + ) { + configState.lastFilename = filename; + configState.lastMTime = fs.statSync(filename).mtime; + return JSON.parse(fs.readFileSync(filename, "utf8")); + } + return undefined; } function configureOnceOff(config, options) { - if (config) { - try { - configureAppenders(config.appenders, options); - configureLevels(config.levels); - - if (config.replaceConsole) { - replaceConsole(); - } else { - restoreConsole(); - } - } catch (e) { - throw new Error("Problem reading log4js config " + util.inspect(config) + ". Error was \"" + e.message + "\" ("+e.stack+")"); - } + if (config) { + try { + configureAppenders(config.appenders, options); + configureLevels(config.levels); + + if (config.replaceConsole) { + replaceConsole(); + } else { + restoreConsole(); + } + } catch (e) { + throw new Error( + "Problem reading log4js config " + util.inspect(config) + + ". Error was \"" + e.message + "\" (" + e.stack + ")" + ); } + } } function reloadConfiguration() { - var filename = configState.filename, - mtime; - if (!filename) { - // can't find anything to reload - return; - } - try { - mtime = fs.statSync(filename).mtime; - } catch (e) { - getLogger('log4js').warn('Failed to load configuration file ' + filename); - return; - } - if (configState.lastFilename && configState.lastFilename === filename) { - if (mtime.getTime() > configState.lastMTime.getTime()) { - configureOnceOff(loadConfigurationFile(filename)); - } - } else { - configureOnceOff(loadConfigurationFile(filename)); + var filename = configState.filename, + mtime; + if (!filename) { + // can't find anything to reload + return; + } + try { + mtime = fs.statSync(filename).mtime; + } catch (e) { + getLogger('log4js').warn('Failed to load configuration file ' + filename); + return; + } + if (configState.lastFilename && configState.lastFilename === filename) { + if (mtime.getTime() > configState.lastMTime.getTime()) { + configureOnceOff(loadConfigurationFile(filename)); } + } else { + configureOnceOff(loadConfigurationFile(filename)); + } } function initReloadConfiguration(filename, options) { - if (configState.timerId) { - clearInterval(configState.timerId); - delete configState.timerId; - } - configState.filename = filename; - configState.timerId = setInterval(reloadConfiguration, options.reloadSecs*1000); + if (configState.timerId) { + clearInterval(configState.timerId); + delete configState.timerId; + } + configState.filename = filename; + configState.timerId = setInterval(reloadConfiguration, options.reloadSecs*1000); } function configure(configurationFileOrObject, options) { - var config = configurationFileOrObject; - config = config || process.env.LOG4JS_CONFIG; - options = options || {}; + var config = configurationFileOrObject; + config = config || process.env.LOG4JS_CONFIG; + options = options || {}; - if (config === undefined || config === null || typeof(config) === 'string') { - if (options.reloadSecs) { - initReloadConfiguration(config, options); - } - config = loadConfigurationFile(config) || defaultConfig; - } else { - if (options.reloadSecs) { - getLogger('log4js').warn('Ignoring configuration reload parameter for "object" configuration.'); - } + if (config === undefined || config === null || typeof(config) === 'string') { + if (options.reloadSecs) { + initReloadConfiguration(config, options); } - configureOnceOff(config, options); + config = loadConfigurationFile(config) || defaultConfig; + } else { + if (options.reloadSecs) { + getLogger('log4js').warn( + 'Ignoring configuration reload parameter for "object" configuration.' + ); + } + } + configureOnceOff(config, options); } var originalConsoleFunctions = { - log: console.log, - debug: console.debug, - info: console.info, - warn: console.warn, - error: console.error + log: console.log, + debug: console.debug, + info: console.info, + warn: console.warn, + error: console.error }; function replaceConsole(logger) { - function replaceWith(fn) { - return function() { - fn.apply(logger, arguments); - } - } - logger = logger || getLogger("console"); - ['log','debug','info','warn','error'].forEach(function (item) { - console[item] = replaceWith(item === 'log' ? logger.info : logger[item]); - }); + function replaceWith(fn) { + return function() { + fn.apply(logger, arguments); + }; + } + logger = logger || getLogger("console"); + ['log','debug','info','warn','error'].forEach(function (item) { + console[item] = replaceWith(item === 'log' ? logger.info : logger[item]); + }); } function restoreConsole() { - ['log', 'debug', 'info', 'warn', 'error'].forEach(function (item) { - console[item] = originalConsoleFunctions[item]; - }); + ['log', 'debug', 'info', 'warn', 'error'].forEach(function (item) { + console[item] = originalConsoleFunctions[item]; + }); } function loadAppender(appender) { - var appenderModule; - try { - appenderModule = require('./appenders/' + appender); - } catch (e) { - appenderModule = require(appender); - } - module.exports.appenders[appender] = appenderModule.appender.bind(appenderModule); - appenderMakers[appender] = appenderModule.configure.bind(appenderModule); + var appenderModule; + try { + appenderModule = require('./appenders/' + appender); + } catch (e) { + appenderModule = require(appender); + } + module.exports.appenders[appender] = appenderModule.appender.bind(appenderModule); + appenderMakers[appender] = appenderModule.configure.bind(appenderModule); } module.exports = { - getLogger: getLogger, - getDefaultLogger: getDefaultLogger, - - addAppender: addAppender, - loadAppender: loadAppender, - clearAppenders: clearAppenders, - configure: configure, - - replaceConsole: replaceConsole, - restoreConsole: restoreConsole, - - levels: levels, - setGlobalLogLevel: setGlobalLogLevel, - - layouts: layouts, - appenders: {}, - appenderMakers: appenderMakers, - connectLogger: require('./connect-logger').connectLogger + getLogger: getLogger, + getDefaultLogger: getDefaultLogger, + + addAppender: addAppender, + loadAppender: loadAppender, + clearAppenders: clearAppenders, + configure: configure, + + replaceConsole: replaceConsole, + restoreConsole: restoreConsole, + + levels: levels, + setGlobalLogLevel: setGlobalLogLevel, + + layouts: layouts, + appenders: {}, + appenderMakers: appenderMakers, + connectLogger: require('./connect-logger').connectLogger }; //set ourselves up diff --git a/test/configureNoLevels-test.js b/test/configureNoLevels-test.js index c2de2f6..b2f2d7a 100644 --- a/test/configureNoLevels-test.js +++ b/test/configureNoLevels-test.js @@ -1,7 +1,10 @@ +"use strict"; // This test shows unexpected behaviour for log4js.configure() in log4js-node@0.4.3 and earlier: -// 1) log4js.configure(), log4js.configure(null), log4js.configure({}), log4js.configure() +// 1) log4js.configure(), log4js.configure(null), +// log4js.configure({}), log4js.configure() // all set all loggers levels to trace, even if they were previously set to something else. -// 2) log4js.configure({levels:{}}), log4js.configure({levels: {foo: bar}}) leaves previously set logger levels intact. +// 2) log4js.configure({levels:{}}), log4js.configure({levels: {foo: +// bar}}) leaves previously set logger levels intact. // // Basic set up @@ -28,7 +31,7 @@ var configs = { 'has empty levels': {levels: {}}, 'has random levels': {levels: {foo: 'bar'}}, 'has some valid levels': {levels: {A: 'INFO'}} -} +}; // Set up the basic vows batches for this test var batches = []; @@ -60,13 +63,14 @@ function getTopLevelContext(nop, configToTest, name) { } return log4js; } - } -}; + }; +} showProgress('Populating batch object...'); -// Populating the batches programmatically, -// as there are (configs.length x strLevels.length x strLevels.length) = 324 possible test combinations +// Populating the batches programmatically, as there are +// (configs.length x strLevels.length x strLevels.length) = 324 +// possible test combinations for (var cfg in configs) { var configToTest = configs[cfg]; var nop = configToTest === 'nop'; @@ -84,43 +88,73 @@ for (var cfg in configs) { batch[context]= getTopLevelContext(nop, configToTest, context); batches.push(batch); - // each top-level context has strLevels sub-contexts, one per logger which has set to a specific level in the top-level context's topic + // each top-level context has strLevels sub-contexts, one per logger + // which has set to a specific level in the top-level context's topic strLevels.forEach(function (baseLevel) { var baseLevelSubContext = 'and checking the logger whose level was set to '+baseLevel ; - batch[context][baseLevelSubContext] = {topic: baseLevel}; + var subContext = { topic: baseLevel }; + batch[context][baseLevelSubContext] = subContext; // each logging level has strLevels sub-contexts, - // to exhaustively test all the combinations of setLevel(baseLevel) and isLevelEnabled(comparisonLevel) per config + // to exhaustively test all the combinations of + // setLevel(baseLevel) and isLevelEnabled(comparisonLevel) per config strLevels.forEach(function (comparisonLevel) { var comparisonLevelSubContext = 'with isLevelEnabled('+comparisonLevel+')'; - // calculate this independently of log4js, but we'll add a vow later on to check that we're not mismatched with log4js + // calculate this independently of log4js, but we'll add a vow + // later on to check that we're not mismatched with log4js var expectedResult = strLevels.indexOf(baseLevel) <= strLevels.indexOf(comparisonLevel); - // the topic simply gathers all the parameters for the vow into an object, to simplify the vow's work. - batch[context][baseLevelSubContext][comparisonLevelSubContext] = {topic: function(baseLevel, log4js){ - return {comparisonLevel: comparisonLevel, baseLevel: baseLevel, log4js: log4js, expectedResult: expectedResult}; - }}; - - var vow = 'should return '+expectedResult; - batch[context][baseLevelSubContext][comparisonLevelSubContext][vow] = function(topic){ - var result = topic.log4js.getLogger(getLoggerName(topic.baseLevel)).isLevelEnabled(topic.log4js.levels.toLevel(topic.comparisonLevel)); - assert.equal(result, topic.expectedResult, 'Failed: '+getLoggerName(topic.baseLevel)+'.isLevelEnabled( '+topic.comparisonLevel+' ) returned '+result); + // the topic simply gathers all the parameters for the vow + // into an object, to simplify the vow's work. + subContext[comparisonLevelSubContext] = { + topic: function(baseLevel, log4js) { + return { + comparisonLevel: comparisonLevel, + baseLevel: baseLevel, + log4js: log4js, + expectedResult: expectedResult + }; + } }; - // the extra vow to check the comparison between baseLevel and comparisonLevel we performed earlier matches log4js' comparison too - batch[context][baseLevelSubContext][comparisonLevelSubContext]['finally checking for comparison mismatch with log4js'] = function(topic){ - var er = topic.log4js.levels.toLevel(topic.baseLevel).isLessThanOrEqualTo(topic.log4js.levels.toLevel(topic.comparisonLevel)); - assert.equal(er, topic.expectedResult, 'Mismatch: for setLevel('+topic.baseLevel+') was expecting a comparison with '+topic.comparisonLevel+' to be '+topic.expectedResult); + var vow = 'should return '+expectedResult; + subContext[comparisonLevelSubContext][vow] = function(topic) { + var result = topic.log4js + .getLogger(getLoggerName(topic.baseLevel)) + .isLevelEnabled(topic.log4js.levels.toLevel(topic.comparisonLevel)); + + assert.equal( + result, + topic.expectedResult, + 'Failed: ' + getLoggerName(topic.baseLevel) + + '.isLevelEnabled( ' + topic.comparisonLevel + ' ) returned ' + result + ); + }; + + // the extra vow to check the comparison between baseLevel and + // comparisonLevel we performed earlier matches log4js' + // comparison too + var subSubContext = subContext[comparisonLevelSubContext]; + subSubContext['finally checking for comparison mismatch with log4js'] = function(topic) { + var er = topic.log4js.levels.toLevel(topic.baseLevel) + .isLessThanOrEqualTo(topic.log4js.levels.toLevel(topic.comparisonLevel)); + assert.equal( + er, + topic.expectedResult, + 'Mismatch: for setLevel(' + topic.baseLevel + + ') was expecting a comparison with ' + topic.comparisonLevel + + ' to be ' + topic.expectedResult + ); }; }); }); -}; +} showProgress('Running tests'); var v = vows.describe('log4js.configure(), with or without a "levels" property'); -batches.forEach(function(batch) {v=v.addBatch(batch)}); +batches.forEach(function(batch) {v=v.addBatch(batch);}); v.export(module); diff --git a/test/layouts-test.js b/test/layouts-test.js index 0d1fd99..d7da866 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -26,7 +26,7 @@ vows.describe('log4js layouts').addBatch({ toString: function() { return "ERROR"; } } }); - assert.equal(output, '\0x1B[31m[2010-12-05 14:18:30.045] [ERROR] cheese - \0x1B[39mnonsense'); + assert.equal(output, '\x1B[31m[2010-12-05 14:18:30.045] [ERROR] cheese - \x1B[39mnonsense'); }, 'should support the console.log format for the message': function(layout) { @@ -38,7 +38,7 @@ vows.describe('log4js layouts').addBatch({ toString: function() { return "ERROR"; } } }); - assert.equal(output, '\0x1B[31m[2010-12-05 14:18:30.045] [ERROR] cheese - \0x1B[39mthing 2'); + assert.equal(output, '\x1B[31m[2010-12-05 14:18:30.045] [ERROR] cheese - \x1B[39mthing 2'); } }, @@ -258,7 +258,7 @@ vows.describe('log4js layouts').addBatch({ test(args, '%-10p', 'DEBUG '); }, '%[%r%] should output colored time': function(args) { - test(args, '%[%r%]', '\0x1B[36m14:18:30\0x1B[39m'); + test(args, '%[%r%]', '\x1B[36m14:18:30\x1B[39m'); }, '%x{testString} should output the string stored in tokens': function(args) { test(args, '%x{testString}', 'testStringToken');