From eb21e102080691d4143055096db64a8f11083b7c Mon Sep 17 00:00:00 2001 From: Nick Howes Date: Tue, 26 Feb 2013 13:24:02 +0000 Subject: [PATCH 01/19] Category excluding filter. This filtering appender allows you to choose some category names that won't be logged to the delegated appender. This is useful if you have e.g. a category that you use to log web requests to one file, but want to keep those entries out of the main log file without having to explicitly list all the other categories that you _do_ want to include. Has one option, "exclude", which is a category name or array of category names. The child appender is set in "appender", modelled on the logLevelFilter. --- lib/appenders/categoryFilter.js | 24 ++++++++++ test/categoryFilter-test.js | 79 +++++++++++++++++++++++++++++++++ test/with-categoryFilter.json | 23 ++++++++++ 3 files changed, 126 insertions(+) create mode 100644 lib/appenders/categoryFilter.js create mode 100644 test/categoryFilter-test.js create mode 100644 test/with-categoryFilter.json diff --git a/lib/appenders/categoryFilter.js b/lib/appenders/categoryFilter.js new file mode 100644 index 0000000..7a35624 --- /dev/null +++ b/lib/appenders/categoryFilter.js @@ -0,0 +1,24 @@ +var levels = require('../levels'); +var log4js = require('../log4js'); + +function contains(list, value) { + return list.indexOf(value) !== -1; +} + +function categoryFilter (excludes, appender) { + if (typeof(excludes) === 'string') excludes = [excludes]; + return function(logEvent) { + if (excludes.indexOf(logEvent.categoryName) === -1) { + appender(logEvent); + } + } +} + +function configure(config) { + log4js.loadAppender(config.appender.type); + var appender = log4js.appenderMakers[config.appender.type](config.appender); + return categoryFilter(config.exclude, appender); +} + +exports.appender = categoryFilter; +exports.configure = configure; diff --git a/test/categoryFilter-test.js b/test/categoryFilter-test.js new file mode 100644 index 0000000..30dd42d --- /dev/null +++ b/test/categoryFilter-test.js @@ -0,0 +1,79 @@ +'use strict'; + +var vows = require('vows') +, fs = require('fs') +, assert = require('assert'); + +function remove(filename) { + try { + fs.unlinkSync(filename); + } catch (e) { + //doesn't really matter if it failed + } +} + +vows.describe('log4js categoryFilter').addBatch({ + 'appender': { + topic: function() { + + var log4js = require('../lib/log4js'), logEvents = [], webLogger, appLogger; + log4js.clearAppenders(); + var appender = require('../lib/appenders/categoryFilter').appender(['app'], function(evt) { logEvents.push(evt); }); + log4js.addAppender(appender, ["app","web"]); + + webLogger = log4js.getLogger("web"); + appLogger = log4js.getLogger("app"); + + webLogger.debug('This should get logged'); + appLogger.debug('This should not'); + webLogger.debug('Hello again'); + log4js.getLogger('db').debug('This shouldn\'t be included by the appender anyway'); + + return logEvents; + }, + 'should only pass matching category' : function(logEvents) { + assert.equal(logEvents.length, 2); + assert.equal(logEvents[0].data[0], 'This should get logged'); + assert.equal(logEvents[1].data[0], 'Hello again'); + } + }, + + 'configure': { + topic: function() { + var log4js = require('../lib/log4js') + , logger, weblogger; + + remove(__dirname + '/categoryFilter-web.log'); + remove(__dirname + '/categoryFilter-noweb.log'); + + log4js.configure('test/with-categoryFilter.json'); + logger = log4js.getLogger("app"); + weblogger = log4js.getLogger("web"); + + logger.info('Loading app'); + logger.debug('Initialising indexes'); + weblogger.info('00:00:00 GET / 200'); + weblogger.warn('00:00:00 GET / 500'); + //wait for the file system to catch up + setTimeout(this.callback, 100); + }, + 'tmp-tests.log': { + topic: function() { + fs.readFile(__dirname + '/categoryFilter-noweb.log', 'utf8', this.callback); + }, + 'should contain all log messages': function(contents) { + var messages = contents.trim().split('\n'); + assert.deepEqual(messages, ['Loading app','Initialising indexes']); + } + }, + 'tmp-tests-web.log': { + topic: function() { + fs.readFile(__dirname + '/categoryFilter-web.log','utf8',this.callback); + }, + 'should contain only error and warning log messages': function(contents) { + var messages = contents.trim().split('\n'); + assert.deepEqual(messages, ['00:00:00 GET / 200','00:00:00 GET / 500']); + } + } + } +}).export(module); diff --git a/test/with-categoryFilter.json b/test/with-categoryFilter.json new file mode 100644 index 0000000..7998cc8 --- /dev/null +++ b/test/with-categoryFilter.json @@ -0,0 +1,23 @@ +{ + "appenders": [ + { + "type": "categoryFilter", + "exclude": "web", + "appender": { + "type": "file", + "filename": "test/categoryFilter-noweb.log", + "layout": { + "type": "messagePassThrough" + } + } + }, + { + "category": "web", + "type": "file", + "filename": "test/categoryFilter-web.log", + "layout": { + "type": "messagePassThrough" + } + } + ] +} From 1e17f88ded8b72edeea008dd0566fccfb6456377 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 2 Aug 2013 11:38:34 +1000 Subject: [PATCH 02/19] 0.6.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0056ad..00bd6bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "log4js", - "version": "0.6.6", + "version": "0.6.7", "description": "Port of Log4js to work with node.", "keywords": [ "logging", From 8ad1cd67e2ae69a43e16fec75d49fc0268d8a4d5 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 5 Aug 2013 11:40:59 +1000 Subject: [PATCH 03/19] formatting fixes, unnecessary code removed --- lib/appenders/categoryFilter.js | 22 +++--- test/categoryFilter-test.js | 136 ++++++++++++++++---------------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/lib/appenders/categoryFilter.js b/lib/appenders/categoryFilter.js index 7a35624..f854f65 100644 --- a/lib/appenders/categoryFilter.js +++ b/lib/appenders/categoryFilter.js @@ -1,23 +1,19 @@ -var levels = require('../levels'); +"use strict"; var log4js = require('../log4js'); -function contains(list, value) { - return list.indexOf(value) !== -1; -} - function categoryFilter (excludes, appender) { - if (typeof(excludes) === 'string') excludes = [excludes]; - return function(logEvent) { - if (excludes.indexOf(logEvent.categoryName) === -1) { - appender(logEvent); - } + if (typeof(excludes) === 'string') excludes = [excludes]; + return function(logEvent) { + if (excludes.indexOf(logEvent.categoryName) === -1) { + appender(logEvent); } + }; } function configure(config) { - log4js.loadAppender(config.appender.type); - var appender = log4js.appenderMakers[config.appender.type](config.appender); - return categoryFilter(config.exclude, appender); + log4js.loadAppender(config.appender.type); + var appender = log4js.appenderMakers[config.appender.type](config.appender); + return categoryFilter(config.exclude, appender); } exports.appender = categoryFilter; diff --git a/test/categoryFilter-test.js b/test/categoryFilter-test.js index 30dd42d..1ad10a0 100644 --- a/test/categoryFilter-test.js +++ b/test/categoryFilter-test.js @@ -5,75 +5,79 @@ var vows = require('vows') , assert = require('assert'); function remove(filename) { - try { - fs.unlinkSync(filename); - } catch (e) { - //doesn't really matter if it failed - } + try { + fs.unlinkSync(filename); + } catch (e) { + //doesn't really matter if it failed + } } vows.describe('log4js categoryFilter').addBatch({ - 'appender': { - topic: function() { - - var log4js = require('../lib/log4js'), logEvents = [], webLogger, appLogger; - log4js.clearAppenders(); - var appender = require('../lib/appenders/categoryFilter').appender(['app'], function(evt) { logEvents.push(evt); }); - log4js.addAppender(appender, ["app","web"]); - - webLogger = log4js.getLogger("web"); - appLogger = log4js.getLogger("app"); - - webLogger.debug('This should get logged'); - appLogger.debug('This should not'); - webLogger.debug('Hello again'); - log4js.getLogger('db').debug('This shouldn\'t be included by the appender anyway'); - - return logEvents; - }, - 'should only pass matching category' : function(logEvents) { - assert.equal(logEvents.length, 2); - assert.equal(logEvents[0].data[0], 'This should get logged'); - assert.equal(logEvents[1].data[0], 'Hello again'); - } + 'appender': { + topic: function() { + + var log4js = require('../lib/log4js'), logEvents = [], webLogger, appLogger; + log4js.clearAppenders(); + var appender = require('../lib/appenders/categoryFilter') + .appender( + ['app'], + function(evt) { logEvents.push(evt); } + ); + log4js.addAppender(appender, ["app","web"]); + + webLogger = log4js.getLogger("web"); + appLogger = log4js.getLogger("app"); + + webLogger.debug('This should get logged'); + appLogger.debug('This should not'); + webLogger.debug('Hello again'); + log4js.getLogger('db').debug('This shouldn\'t be included by the appender anyway'); + + return logEvents; }, - - 'configure': { - topic: function() { - var log4js = require('../lib/log4js') - , logger, weblogger; - - remove(__dirname + '/categoryFilter-web.log'); - remove(__dirname + '/categoryFilter-noweb.log'); - - log4js.configure('test/with-categoryFilter.json'); - logger = log4js.getLogger("app"); - weblogger = log4js.getLogger("web"); - - logger.info('Loading app'); - logger.debug('Initialising indexes'); - weblogger.info('00:00:00 GET / 200'); - weblogger.warn('00:00:00 GET / 500'); - //wait for the file system to catch up - setTimeout(this.callback, 100); - }, - 'tmp-tests.log': { - topic: function() { - fs.readFile(__dirname + '/categoryFilter-noweb.log', 'utf8', this.callback); - }, - 'should contain all log messages': function(contents) { - var messages = contents.trim().split('\n'); - assert.deepEqual(messages, ['Loading app','Initialising indexes']); - } - }, - 'tmp-tests-web.log': { - topic: function() { - fs.readFile(__dirname + '/categoryFilter-web.log','utf8',this.callback); - }, - 'should contain only error and warning log messages': function(contents) { - var messages = contents.trim().split('\n'); - assert.deepEqual(messages, ['00:00:00 GET / 200','00:00:00 GET / 500']); - } - } + 'should only pass matching category' : function(logEvents) { + assert.equal(logEvents.length, 2); + assert.equal(logEvents[0].data[0], 'This should get logged'); + assert.equal(logEvents[1].data[0], 'Hello again'); } + }, + + 'configure': { + topic: function() { + var log4js = require('../lib/log4js') + , logger, weblogger; + + remove(__dirname + '/categoryFilter-web.log'); + remove(__dirname + '/categoryFilter-noweb.log'); + + log4js.configure('test/with-categoryFilter.json'); + logger = log4js.getLogger("app"); + weblogger = log4js.getLogger("web"); + + logger.info('Loading app'); + logger.debug('Initialising indexes'); + weblogger.info('00:00:00 GET / 200'); + weblogger.warn('00:00:00 GET / 500'); + //wait for the file system to catch up + setTimeout(this.callback, 100); + }, + 'tmp-tests.log': { + topic: function() { + fs.readFile(__dirname + '/categoryFilter-noweb.log', 'utf8', this.callback); + }, + 'should contain all log messages': function(contents) { + var messages = contents.trim().split('\n'); + assert.deepEqual(messages, ['Loading app','Initialising indexes']); + } + }, + 'tmp-tests-web.log': { + topic: function() { + fs.readFile(__dirname + '/categoryFilter-web.log','utf8',this.callback); + }, + 'should contain only error and warning log messages': function(contents) { + var messages = contents.trim().split('\n'); + assert.deepEqual(messages, ['00:00:00 GET / 200','00:00:00 GET / 500']); + } + } + } }).export(module); From 61beac28d39ee59ddf27286368a131f5ccdeb28f Mon Sep 17 00:00:00 2001 From: Marcin Kielar Date: Fri, 9 Aug 2013 00:04:25 +0200 Subject: [PATCH 04/19] Clustered appender for log4js. + lib/appenders/clustered.js + test/clusteredAppender-test.js Instead os using sockets (like multiprocess) or dead and unmaintained hook.io, Clustered appender uses process.send(message) / worker.on('message', callback) mechanisms for transporting data between worker processes and master logger. Master logger takes an "appenders" array of actual appenders that are triggered when worker appenders send some data. This guarantees sequential writes to appenders, so the log messages are not mixed in single lines of log. --- lib/appenders/clustered.js | 118 +++++++++++++++++++++++++++++++++ test/clusteredAppender-test.js | 116 ++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100755 lib/appenders/clustered.js create mode 100755 test/clusteredAppender-test.js diff --git a/lib/appenders/clustered.js b/lib/appenders/clustered.js new file mode 100755 index 0000000..f56e89a --- /dev/null +++ b/lib/appenders/clustered.js @@ -0,0 +1,118 @@ +"use strict"; + +var cluster = require('cluster'); +var log4js = require('../log4js'); + +/** + * Takes a loggingEvent object, returns string representation of it. + */ +function serializeLoggingEvent(loggingEvent) { + return JSON.stringify(loggingEvent); +} + +/** + * Takes a string, returns an object with + * the correct log properties. + * + * This method has been "borrowed" from the `multiprocess` appender + * by `nomiddlename` (https://github.com/nomiddlename/log4js-node/blob/master/lib/appenders/multiprocess.js) + * + * Apparently, node.js serializes everything to strings when using `process.send()`, + * so we need smart deserialization that will recreate log date and level for further processing by log4js internals. + */ +function deserializeLoggingEvent(loggingEventString) { + + var loggingEvent; + + try { + + loggingEvent = JSON.parse(loggingEventString); + 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:', loggingEventString ] + }; + } + return loggingEvent; +} + +/** + * Creates an appender. + * + * If the current process is a master (`cluster.isMaster`), then this will be a "master appender". + * Otherwise this will be a worker appender, that just sends loggingEvents to the master process. + * + * If you are using this method directly, make sure to provide it with `config.actualAppenders` array + * of actual appender instances. + * + * Or better use `configure(config, options)` + */ +function createAppender(config) { + + if (cluster.isMaster) { + + var masterAppender = function(loggingEvent) { + + if (config.actualAppenders) { + var size = config.actualAppenders.length; + for(var i = 0; i < size; i++) { + config.actualAppenders[i](loggingEvent); + } + } + } + + // Listen on new workers + cluster.on('fork', function(worker) { + + worker.on('message', function(message) { + if (message.type && message.type === '::log-message') { + // console.log("master : " + cluster.isMaster + " received message: " + JSON.stringify(message.event)); + + var loggingEvent = deserializeLoggingEvent(message.event); + masterAppender(loggingEvent); + } + }); + + }); + + return masterAppender; + + } else { + + return function(loggingEvent) { + // If inside the worker process, then send the logger event to master. + if (cluster.isWorker) { + // console.log("worker " + cluster.worker.id + " is sending message"); + process.send({ type: '::log-message', event: serializeLoggingEvent(loggingEvent)}); + } + } + } +} + +function configure(config, options) { + + if (config.appenders && cluster.isMaster) { + + var size = config.appenders.length; + config.actualAppenders = new Array(size); + + for(var i = 0; i < size; i++) { + + log4js.loadAppender(config.appenders[i].type); + config.actualAppenders[i] = log4js.appenderMakers[config.appenders[i].type](config.appenders[i], options); + + } + } + + return createAppender(config); +} + +exports.appender = createAppender; +exports.configure = configure; \ No newline at end of file diff --git a/test/clusteredAppender-test.js b/test/clusteredAppender-test.js new file mode 100755 index 0000000..a0dd5fb --- /dev/null +++ b/test/clusteredAppender-test.js @@ -0,0 +1,116 @@ +"use strict"; +var assert = require('assert'); +var vows = require('vows'); +var layouts = require('../lib/layouts'); +var sandbox = require('sandboxed-module'); +var LoggingEvent = require('../lib/logger').LoggingEvent; +var cluster = require('cluster'); + +vows.describe('log4js cluster appender').addBatch({ + 'when in master mode': { + topic: function() { + + var registeredClusterEvents = []; + var loggingEvents = []; + + // Fake cluster module, so no cluster listeners be really added + var fakeCluster = { + + on: function(event, callback) { + registeredClusterEvents.push(event); + }, + + isMaster: true, + isWorker: false, + + }; + + var fakeActualAppender = function(loggingEvent) { + loggingEvents.push(loggingEvent); + } + + // Load appender and fake modules in it + var appenderModule = sandbox.require('../lib/appenders/clustered', { + requires: { + 'cluster': fakeCluster, + } + }); + + var masterAppender = appenderModule.appender({ + actualAppenders: [ fakeActualAppender ] + }); + + // Actual test - log message using masterAppender + masterAppender(new LoggingEvent('wovs', 'Info', ['masterAppender test'])); + + var returnValue = { + registeredClusterEvents: registeredClusterEvents, + loggingEvents: loggingEvents, + }; + + return returnValue; + }, + + "should register 'fork' event listener on 'cluster'": function(topic) { + assert.equal(topic.registeredClusterEvents[0], 'fork'); + }, + + "should log using actual appender": function(topic) { + assert.equal(topic.loggingEvents[0].data[0], 'masterAppender test'); + }, + + }, + + 'when in worker mode': { + + topic: function() { + + var registeredProcessEvents = []; + + // Fake cluster module, to fake we're inside a worker process + var fakeCluster = { + + isMaster: false, + isWorker: true, + + }; + + var fakeProcess = { + + send: function(data) { + registeredProcessEvents.push(data); + }, + + }; + + // Load appender and fake modules in it + var appenderModule = sandbox.require('../lib/appenders/clustered', { + requires: { + 'cluster': fakeCluster, + }, + globals: { + 'process': fakeProcess, + } + }); + + var workerAppender = appenderModule.appender(); + + // Actual test - log message using masterAppender + workerAppender(new LoggingEvent('wovs', 'Info', ['workerAppender test'])); + + var returnValue = { + registeredProcessEvents: registeredProcessEvents, + }; + + return returnValue; + + }, + + "worker appender should call process.send" : function(topic) { + assert.equal(topic.registeredProcessEvents[0].type, '::log-message'); + assert.equal(JSON.parse(topic.registeredProcessEvents[0].event).data[0], "workerAppender test"); + } + + } + +}).exportTo(module); From 21aebbde33be0d533d22d6fa2ce9a3dfbbd4a57f Mon Sep 17 00:00:00 2001 From: wood1986 Date: Tue, 13 Aug 2013 23:04:11 +0800 Subject: [PATCH 05/19] Update layouts.js --- lib/layouts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/layouts.js b/lib/layouts.js index b171cee..35b2aee 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -166,6 +166,8 @@ function patternLayout (pattern, tokens) { // Pick up special cases if (format == "ISO8601") { format = dateFormat.ISO8601_FORMAT; + } else if (format == "ISO8601_WITH_TZ_OFFSET") { + format = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT; } else if (format == "ABSOLUTE") { format = dateFormat.ABSOLUTETIME_FORMAT; } else if (format == "DATE") { From 2d177d517b77f87cedd165bdeb14500a26338152 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Tue, 13 Aug 2013 23:04:52 +0800 Subject: [PATCH 06/19] Update date_format.js --- lib/date_format.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/date_format.js b/lib/date_format.js index bf36318..d75ce20 100644 --- a/lib/date_format.js +++ b/lib/date_format.js @@ -45,7 +45,7 @@ exports.asString = function(/*format,*/ date) { var vDay = addZero(date.getDate()); var vMonth = addZero(date.getMonth()+1); var vYearLong = addZero(date.getFullYear()); - var vYearShort = addZero(date.getFullYear().toString().substring(3,4)); + var vYearShort = addZero(date.getFullYear().toString().substring(2,4)); var vYear = (format.indexOf("yyyy") > -1 ? vYearLong : vYearShort); var vHour = addZero(date.getHours()); var vMinute = addZero(date.getMinutes()); From 1ed026a8d9cc901de6a8e3a466ffc44e29b9962d Mon Sep 17 00:00:00 2001 From: wood1986 Date: Wed, 14 Aug 2013 17:35:47 +0800 Subject: [PATCH 07/19] Update fileAppender-test.js --- test/fileAppender-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fileAppender-test.js b/test/fileAppender-test.js index cb4692a..9476ad6 100644 --- a/test/fileAppender-test.js +++ b/test/fileAppender-test.js @@ -222,7 +222,7 @@ vows.describe('log4js fileAppender').addBatch({ , logger; //this config file defines one file appender (to ./tmp-tests.log) //and sets the log level for "tests" to WARN - log4js.configure('test/log4js.json'); + log4js.configure('./test/log4js.json'); logger = log4js.getLogger('tests'); logger.info('this should not be written to the file'); logger.warn('this should be written to the file'); From 5755faa7bbad56fe1e52a81290ca47d886dd651d Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:29:36 +0800 Subject: [PATCH 08/19] Update layouts-test.js --- test/layouts-test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/layouts-test.js b/test/layouts-test.js index 9af1242..dde6c97 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -197,6 +197,12 @@ vows.describe('log4js layouts').addBatch({ '%r should output time only': function(args) { test(args, '%r', '14:18:30'); }, + '%d{ISO8601_WITH_TZ_OFFSET} should output time only': function(args) { + test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-11-05T14:18:30'); + }, + '%d{yy.MM.dd.hh.mm.ss.sss} should output time only': function(args) { + test(args, '%d{yy.MM.dd.hh.mm.ss.sss}', '10.11.05.14.18.30.045'); + }, '%p should output the log level': function(args) { test(args, '%p', 'DEBUG'); }, From 5a167d853afbd9d786dc3d1e7775c212805617c6 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:29:52 +0800 Subject: [PATCH 09/19] Update date_format-test.js --- test/date_format-test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/date_format-test.js b/test/date_format-test.js index d4a5cb5..444446d 100644 --- a/test/date_format-test.js +++ b/test/date_format-test.js @@ -39,6 +39,12 @@ vows.describe('date_format').addBatch({ dateFormat.asString(dateFormat.ABSOLUTETIME_FORMAT, date), '14:31:30.005' ); + }, + 'should provide a custom format': function(date) { + assert.equal( + dateFormat.asString("O.SSS.ss.mm.hh.dd.MM.yy", date), + '+1100.005.30.31.14.11.01.10' + ); } } }).export(module); From 9e7218957427c06e1eeb49e067c34906eb1bed7e Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:30:57 +0800 Subject: [PATCH 10/19] Update date_format-test.js --- test/date_format-test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/date_format-test.js b/test/date_format-test.js index 444446d..6085843 100644 --- a/test/date_format-test.js +++ b/test/date_format-test.js @@ -41,9 +41,10 @@ vows.describe('date_format').addBatch({ ); }, 'should provide a custom format': function(date) { + date.getTimezoneOffset = function() { return 120; }; assert.equal( dateFormat.asString("O.SSS.ss.mm.hh.dd.MM.yy", date), - '+1100.005.30.31.14.11.01.10' + '-0200.005.30.31.14.11.01.10' ); } } From 069ed3175905e0c28c2bbd0d434e869d8286a249 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:37:01 +0800 Subject: [PATCH 11/19] Update layouts-test.js --- test/layouts-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/layouts-test.js b/test/layouts-test.js index dde6c97..db10318 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -198,10 +198,10 @@ vows.describe('log4js layouts').addBatch({ test(args, '%r', '14:18:30'); }, '%d{ISO8601_WITH_TZ_OFFSET} should output time only': function(args) { - test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-11-05T14:18:30'); + test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-12-05T14:18:30'); }, '%d{yy.MM.dd.hh.mm.ss.sss} should output time only': function(args) { - test(args, '%d{yy.MM.dd.hh.mm.ss.sss}', '10.11.05.14.18.30.045'); + test(args, '%d{yy.MM.dd.hh.mm.ss.SSS}', '10.12.05.14.18.30.045'); }, '%p should output the log level': function(args) { test(args, '%p', 'DEBUG'); From 112246dd55de41ce54a56043089e80e45359add8 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:39:59 +0800 Subject: [PATCH 12/19] Update layouts-test.js --- test/layouts-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/layouts-test.js b/test/layouts-test.js index db10318..aee28dc 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -198,7 +198,7 @@ vows.describe('log4js layouts').addBatch({ test(args, '%r', '14:18:30'); }, '%d{ISO8601_WITH_TZ_OFFSET} should output time only': function(args) { - test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-12-05T14:18:30'); + test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-12-05T14:18:30-0000'); }, '%d{yy.MM.dd.hh.mm.ss.sss} should output time only': function(args) { test(args, '%d{yy.MM.dd.hh.mm.ss.SSS}', '10.12.05.14.18.30.045'); From 613474eb441d016bfbfd18247e2f6a35d1977995 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Thu, 15 Aug 2013 22:45:56 +0800 Subject: [PATCH 13/19] Update layouts-test.js --- test/layouts-test.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/layouts-test.js b/test/layouts-test.js index aee28dc..476628f 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -197,12 +197,6 @@ vows.describe('log4js layouts').addBatch({ '%r should output time only': function(args) { test(args, '%r', '14:18:30'); }, - '%d{ISO8601_WITH_TZ_OFFSET} should output time only': function(args) { - test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-12-05T14:18:30-0000'); - }, - '%d{yy.MM.dd.hh.mm.ss.sss} should output time only': function(args) { - test(args, '%d{yy.MM.dd.hh.mm.ss.SSS}', '10.12.05.14.18.30.045'); - }, '%p should output the log level': function(args) { test(args, '%p', 'DEBUG'); }, @@ -227,9 +221,11 @@ vows.describe('log4js layouts').addBatch({ test(args, '%d', '2010-12-05 14:18:30.045'); }, '%d should allow for format specification': function(args) { + test(args, '%d{ISO8601_WITH_TZ_OFFSET}', '2010-12-05T14:18:30-0000'); test(args, '%d{ISO8601}', '2010-12-05 14:18:30.045'); test(args, '%d{ABSOLUTE}', '14:18:30.045'); test(args, '%d{DATE}', '05 12 2010 14:18:30.045'); + test(args, '%d{yy MM dd hh mm ss}', '10 12 05 14 18 30'); test(args, '%d{yyyy MM dd}', '2010 12 05'); test(args, '%d{yyyy MM dd hh mm ss SSS}', '2010 12 05 14 18 30 045'); }, From 6df4753822ab34bf91b26f172f2302942522a252 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Sun, 18 Aug 2013 01:36:07 +0800 Subject: [PATCH 14/19] Update layouts.js --- lib/layouts.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/layouts.js b/lib/layouts.js index 35b2aee..eb07c89 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -120,6 +120,7 @@ function messagePassThroughLayout (loggingEvent) { * - %r time in toLocaleTimeString format * - %p log level * - %c log category + * - %h hostname * - %m log data * - %d date in various formats * - %% % @@ -143,7 +144,7 @@ function messagePassThroughLayout (loggingEvent) { */ function patternLayout (pattern, tokens) { var TTCC_CONVERSION_PATTERN = "%r %p %c - %m%n"; - var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([\[\]cdmnprx%])(\{([^\}]+)\})?|([^%]+)/; + var regex = /%(-?[0-9]+)?(\.?[0-9]+)?([\[\]cdhmnprx%])(\{([^\}]+)\})?|([^%]+)/; pattern = pattern || TTCC_CONVERSION_PATTERN; @@ -166,8 +167,6 @@ function patternLayout (pattern, tokens) { // Pick up special cases if (format == "ISO8601") { format = dateFormat.ISO8601_FORMAT; - } else if (format == "ISO8601_WITH_TZ_OFFSET") { - format = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT; } else if (format == "ABSOLUTE") { format = dateFormat.ABSOLUTETIME_FORMAT; } else if (format == "DATE") { @@ -177,6 +176,10 @@ function patternLayout (pattern, tokens) { // Format the date return dateFormat.asString(format, loggingEvent.startTime); } + + function hostname() { + return os.hostname().toString(); + } function formatMessage(loggingEvent) { return formatLogData(loggingEvent.data); @@ -220,6 +223,7 @@ function patternLayout (pattern, tokens) { var replacers = { 'c': categoryName, 'd': formatAsDate, + 'h': hostname, 'm': formatMessage, 'n': endOfLine, 'p': logLevel, From cd286fa25fdada5e657d03afcfe57a5cc1201813 Mon Sep 17 00:00:00 2001 From: wood1986 Date: Sun, 18 Aug 2013 01:39:37 +0800 Subject: [PATCH 15/19] Update layouts-test.js --- test/layouts-test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/layouts-test.js b/test/layouts-test.js index 476628f..c355bdd 100644 --- a/test/layouts-test.js +++ b/test/layouts-test.js @@ -209,6 +209,9 @@ vows.describe('log4js layouts').addBatch({ '%n should output a new line': function(args) { test(args, '%n', '\n'); }, + '%h should output hostname' : function(args) { + test(args, '%h', require('os').hostname().toString()); + }, '%c should handle category names like java-style package names': function(args) { test(args, '%c{1}', 'tests'); test(args, '%c{2}', 'of.tests'); From 788838199113d99cab42c5044c65287ea7e1429b Mon Sep 17 00:00:00 2001 From: wood1986 Date: Sun, 18 Aug 2013 01:43:48 +0800 Subject: [PATCH 16/19] Update layouts.js --- lib/layouts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/layouts.js b/lib/layouts.js index eb07c89..9cfd035 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -167,6 +167,8 @@ function patternLayout (pattern, tokens) { // Pick up special cases if (format == "ISO8601") { format = dateFormat.ISO8601_FORMAT; + } else if (format == "ISO8601_WITH_TZ_OFFSET") { + format = dateFormat.ISO8601_WITH_TZ_OFFSET_FORMAT; } else if (format == "ABSOLUTE") { format = dateFormat.ABSOLUTETIME_FORMAT; } else if (format == "DATE") { From 7a1a895e46d997f619460dd0fb6e795241e9091a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= Date: Tue, 20 Aug 2013 18:48:27 +0200 Subject: [PATCH 17/19] browserify support --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 00bd6bc..60e5689 100644 --- a/package.json +++ b/package.json @@ -38,5 +38,8 @@ "sandboxed-module": "0.1.3", "hook.io": "0.8.10", "underscore": "1.2.1" + }, + "browser": { + "os": false } } From 3018a49bde08939f71606a254597721cae0ebe5b Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 22 Aug 2013 11:52:25 +1000 Subject: [PATCH 18/19] 0.6.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60e5689..5280c91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "log4js", - "version": "0.6.7", + "version": "0.6.8", "description": "Port of Log4js to work with node.", "keywords": [ "logging", From 731e217505d2f9b2982d2ceca41ba004ade2afae Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 22 Aug 2013 15:46:42 +1000 Subject: [PATCH 19/19] removed dequeue from dependencies --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 5280c91..bb16a08 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ }, "dependencies": { "async": "0.1.15", - "dequeue": "1.0.3", "semver": "~1.1.4", "readable-stream": "~1.0.2" },