diff --git a/README.md b/README.md index 6815f57..eaf9851 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # log4js-node [![Build Status](https://secure.travis-ci.org/nomiddlename/log4js-node.png?branch=master)](http://travis-ci.org/nomiddlename/log4js-node) [![NPM](https://nodei.co/npm/log4js.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/log4js/) - + This is a conversion of the [log4js](https://github.com/stritti/log4js) framework to work with [node](http://nodejs.org). I've mainly stripped out the browser-specific code and tidied up some of the javascript. diff --git a/lib/levels.js b/lib/levels.js index c2816fc..cb9243a 100644 --- a/lib/levels.js +++ b/lib/levels.js @@ -16,6 +16,10 @@ function toLevel(sArg, defaultLevel) { if (!sArg) { return defaultLevel; } + if (sArg instanceof Level) { + module.exports[sArg.toString()] = sArg; + return sArg; + } if (typeof sArg === "string") { return module.exports[sArg.toUpperCase()] || defaultLevel; } @@ -41,7 +45,7 @@ Level.prototype.isGreaterThanOrEqualTo = function(otherLevel) { }; Level.prototype.isEqualTo = function(otherLevel) { - if (typeof otherLevel == "string") { + if (typeof otherLevel === "string") { otherLevel = toLevel(otherLevel); } return this.level === otherLevel.level; @@ -57,5 +61,6 @@ module.exports = { FATAL: new Level(50000, "FATAL"), MARK: new Level(9007199254740992, "MARK"), // 2^53 OFF: new Level(Number.MAX_VALUE, "OFF"), - toLevel: toLevel + toLevel: toLevel, + Level: Level }; diff --git a/lib/log4js.js b/lib/log4js.js index 8ad03f6..629aed5 100644 --- a/lib/log4js.js +++ b/lib/log4js.js @@ -70,6 +70,24 @@ function hasLogger(logger) { return loggers.hasOwnProperty(logger); } +levels.forName = function(levelStr, levelVal) { + var level; + if (typeof levelStr === "string" && typeof levelVal === "number") { + var levelUpper = levelStr.toUpperCase(); + level = new levels.Level(levelVal, levelUpper); + loggerModule.addLevelMethods(level); + } + return level; +}; + +levels.getLevel = function(levelStr) { + var level; + if (typeof levelStr === "string") { + var levelUpper = levelStr.toUpperCase(); + level = levels.toLevel(levelStr); + } + return level; +}; function getBufferedLogger(categoryName) { var base_logger = getLogger(categoryName); @@ -97,7 +115,7 @@ function normalizeCategory (category) { return category + '.'; } -function doesLevelEntryContainsLogger (levelCategory, loggerCategory) { +function doesLevelEntryContainsLogger (levelCategory, loggerCategory) { var normalizedLevelCategory = normalizeCategory(levelCategory); var normalizedLoggerCategory = normalizeCategory(loggerCategory); return normalizedLoggerCategory.substring(0, normalizedLevelCategory.length) == normalizedLevelCategory; //jshint ignore:line @@ -142,7 +160,7 @@ function getLogger (loggerCategoryName) { } } /* jshint +W073 */ - + // Create the logger for this name if it doesn't already exist loggers[loggerCategoryName] = new Logger(loggerCategoryName, level); @@ -165,7 +183,7 @@ function getLogger (loggerCategoryName) { }); } } - + return loggers[loggerCategoryName]; } @@ -182,10 +200,10 @@ function addAppender () { if (Array.isArray(args[0])) { args = args[0]; } - + args.forEach(function(appenderCategory) { addAppenderToCategory(appender, appenderCategory); - + if (appenderCategory === ALL_CATEGORIES) { addAppenderToAllLoggers(appender); } else { @@ -195,7 +213,7 @@ function addAppender () { loggers[loggerCategory].addListener("log", appender); } } - + } }); } @@ -288,7 +306,7 @@ function configureOnceOff(config, options) { try { configureLevels(config.levels); configureAppenders(config.appenders, options); - + if (config.replaceConsole) { replaceConsole(); } else { @@ -296,7 +314,7 @@ function configureOnceOff(config, options) { } } catch (e) { throw new Error( - "Problem reading log4js config " + util.inspect(config) + + "Problem reading log4js config " + util.inspect(config) + ". Error was \"" + e.message + "\" (" + e.stack + ")" ); } @@ -306,7 +324,7 @@ function configureOnceOff(config, options) { function reloadConfiguration(options) { var mtime = getMTime(configState.filename); if (!mtime) return; - + if (configState.lastMTime && (mtime.getTime() > configState.lastMTime.getTime())) { configureOnceOff(loadConfigurationFile(configState.filename), options); } @@ -337,7 +355,7 @@ function configure(configurationFileOrObject, 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); @@ -463,19 +481,19 @@ module.exports = { getLogger: getLogger, getDefaultLogger: getDefaultLogger, hasLogger: hasLogger, - + addAppender: addAppender, loadAppender: loadAppender, clearAppenders: clearAppenders, configure: configure, shutdown: shutdown, - + replaceConsole: replaceConsole, restoreConsole: restoreConsole, - + levels: levels, setGlobalLogLevel: setGlobalLogLevel, - + layouts: layouts, appenders: {}, appenderMakers: appenderMakers, diff --git a/lib/logger.js b/lib/logger.js index 2128312..984bd38 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -68,24 +68,33 @@ Logger.prototype.isLevelEnabled = function(otherLevel) { ['Trace','Debug','Info','Warn','Error','Fatal', 'Mark'].forEach( function(levelString) { - var level = levels.toLevel(levelString); - Logger.prototype['is'+levelString+'Enabled'] = function() { - return this.isLevelEnabled(level); - }; - - Logger.prototype[levelString.toLowerCase()] = function () { - if (logWritesEnabled && this.isLevelEnabled(level)) { - var numArgs = arguments.length; - var args = new Array(numArgs); - for (var i = 0; i < numArgs; i++) { - args[i] = arguments[i]; - } - this._log(level, args); - } - }; + addLevelMethods(levelString); } ); +function addLevelMethods(level) { + level = levels.toLevel(level); + + var levelStrLower = level.toString().toLowerCase(); + var levelMethod = levelStrLower.replace(/_([a-z])/g, function(g) { return g[1].toUpperCase(); } ); + var isLevelMethod = levelMethod[0].toUpperCase() + levelMethod.slice(1); + + Logger.prototype['is'+isLevelMethod+'Enabled'] = function() { + return this.isLevelEnabled(level.toString()); + }; + + Logger.prototype[levelMethod] = function () { + if (logWritesEnabled && this.isLevelEnabled(level)) { + var numArgs = arguments.length; + var args = new Array(numArgs); + for (var i = 0; i < numArgs; i++) { + args[i] = arguments[i]; + } + this._log(level, args); + } + }; +} + Logger.prototype._log = function(level, data) { var loggingEvent = new LoggingEvent(this.category, level, data, this); this.emit('log', loggingEvent); @@ -111,3 +120,4 @@ exports.LoggingEvent = LoggingEvent; exports.Logger = Logger; exports.disableAllLogWrites = disableAllLogWrites; exports.enableAllLogWrites = enableAllLogWrites; +exports.addLevelMethods = addLevelMethods; \ No newline at end of file diff --git a/test/newLevel-test.js b/test/newLevel-test.js new file mode 100644 index 0000000..72dece9 --- /dev/null +++ b/test/newLevel-test.js @@ -0,0 +1,138 @@ +"use strict"; +var vows = require('vows') + , assert = require('assert') + , Level = require('../lib/levels') + , log4js = require('../lib/log4js') + , loggerModule = require('../lib/logger') + , Logger = loggerModule.Logger; + +vows.describe('../lib/logger').addBatch({ + 'creating a new log level': { + topic: function () { + Level.forName("DIAG", 6000); + return new Logger(); + }, + + 'should export new log level in levels module': function (logger) { + assert.isDefined(Level.DIAG); + assert.equal(Level.DIAG.levelStr, "DIAG"); + assert.equal(Level.DIAG.level, 6000); + }, + + 'should create named function on logger prototype': function(logger) { + assert.isFunction(logger.diag); + }, + + 'should create isLevelEnabled function on logger prototype': function(logger) { + assert.isFunction(logger.isDiagEnabled); + }, + }, + + 'creating a new log level with underscores': { + topic: function () { + Level.forName("NEW_LEVEL_OTHER", 6000); + return new Logger(); + }, + + 'should export new log level to levels module': function (logger) { + assert.isDefined(Level.NEW_LEVEL_OTHER); + assert.equal(Level.NEW_LEVEL_OTHER.levelStr, "NEW_LEVEL_OTHER"); + assert.equal(Level.NEW_LEVEL_OTHER.level, 6000); + }, + + 'should create named function on logger prototype in camel case': function(logger) { + assert.isFunction(logger.newLevelOther); + }, + + 'should create named isLevelEnabled function on logger prototype in camel case': + function(logger) { + assert.isFunction(logger.isNewLevelOtherEnabled); + } + }, + + 'creating log events containing newly created log level': { + topic: function() { + var events = [], + logger = new Logger(); + logger.addListener("log", function (logEvent) { events.push(logEvent); }); + + logger.log(Level.forName("LVL1", 6000), "Event 1"); + logger.log(Level.getLevel("LVL1"), "Event 2"); + logger.log("LVL1", "Event 3"); + logger.lvl1("Event 4"); + + logger.setLevel(Level.forName("LVL2", 7000)); + logger.lvl1("Event 5"); + + return events; + }, + + 'should show log events with new log level': function(events) { + assert.equal(events[0].level.toString(), "LVL1"); + assert.equal(events[0].data[0], "Event 1"); + + assert.equal(events[1].level.toString(), "LVL1"); + assert.equal(events[1].data[0], "Event 2"); + + assert.equal(events[2].level.toString(), "LVL1"); + assert.equal(events[2].data[0], "Event 3"); + + assert.equal(events[3].level.toString(), "LVL1"); + assert.equal(events[3].data[0], "Event 4"); + }, + + 'should not be present if min log level is greater than newly created level': + function(events) { + assert.equal(events.length, 4); + } + }, + + 'creating a new log level with incorrect parameters': { + topic: function() { + log4js.levels.forName(9000, "FAIL_LEVEL_1"); + log4js.levels.forName("FAIL_LEVEL_2"); + return new Logger(); + }, + + 'should fail to create the level': function(logger) { + assert.isUndefined(Level.FAIL_LEVEL_1); + assert.isUndefined(Level.FAIL_LEVEL_2); + } + }, + + 'calling log with an undefined log level': { + topic: function() { + var events = [], + logger = new Logger(); + logger.addListener("log", function (logEvent) { events.push(logEvent); }); + + logger.log("LEVEL_DOES_NEXT_EXIST", "Event 1"); + logger.log(Level.forName("LEVEL_DOES_NEXT_EXIST"), "Event 2"); + + return events; + }, + + 'should fallback to the default log level (INFO)': function(events) { + assert.equal(events[0].level.toString(), "INFO"); + assert.equal(events[1].level.toString(), "INFO"); + } + }, + + 'creating a new level with an existing level name': { + topic: function() { + var events = [], + logger = new Logger(); + logger.addListener("log", function (logEvent) { events.push(logEvent); }); + + logger.log(log4js.levels.forName("MY_LEVEL", 9000), "Event 1"); + logger.log(log4js.levels.forName("MY_LEVEL", 8000), "Event 1"); + + return events; + }, + + 'should override the existing log level': function(events) { + assert.equal(events[0].level.level, 9000); + assert.equal(events[1].level.level, 8000); + } + } +}).exportTo(module); \ No newline at end of file