From 2b889fe7764fb2e10d7bd1f0bfc28c1561e155a4 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Tue, 25 Sep 2012 08:16:59 +1000 Subject: [PATCH] Working date rolling file appender. --- lib/appenders/dateFile.js | 49 ++++++++++++++++++ test/dateFileAppender-test.js | 98 +++++++++++++++++++++++++++++++++++ test/with-dateFile.json | 17 ++++++ 3 files changed, 164 insertions(+) create mode 100644 lib/appenders/dateFile.js create mode 100644 test/dateFileAppender-test.js create mode 100644 test/with-dateFile.json diff --git a/lib/appenders/dateFile.js b/lib/appenders/dateFile.js new file mode 100644 index 0000000..8c19bf1 --- /dev/null +++ b/lib/appenders/dateFile.js @@ -0,0 +1,49 @@ +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(); + }); +}); + +/** + * File appender that rolls files according to a date pattern. + * @filename base filename. + * @pattern the format that will be added to the end of filename when rolling, + * also used to check when to roll files - defaults to '.yyyy-MM-dd' + * @layout layout function for log messages - defaults to basicLayout + */ +function appender(filename, pattern, layout) { + layout = layout || layouts.basicLayout; + + var logFile = new streams.BufferedWriteStream(new streams.DateRollingFileStream(filename, pattern)); + openFiles.push(logFile); + + return function(logEvent) { + logFile.write(layout(logEvent) + eol, "utf8"); + }; + +} + +function configure(config, options) { + var layout; + + if (config.layout) { + layout = layouts.layout(config.layout.type, config.layout); + } + + if (options && options.cwd && !config.absolute) { + config.filename = path.join(options.cwd, config.filename); + } + + return appender(config.filename, config.pattern, layout); +} + +exports.appender = appender; +exports.configure = configure; diff --git a/test/dateFileAppender-test.js b/test/dateFileAppender-test.js new file mode 100644 index 0000000..9560709 --- /dev/null +++ b/test/dateFileAppender-test.js @@ -0,0 +1,98 @@ +var vows = require('vows'), + assert = require('assert'), + path = require('path'), + fs = require('fs'), + log4js = require('../lib/log4js'); + +function removeFile(filename) { + return function() { + fs.unlink(path.join(__dirname, filename), function(err) { + if (err) { + console.log("Could not delete ", filename, err); + } + }); + }; +} + +vows.describe('../lib/appenders/dateFile').addBatch({ + 'appender': { + 'adding multiple dateFileAppenders': { + topic: function () { + var listenersCount = process.listeners('exit').length, + dateFileAppender = require('../lib/appenders/dateFile'), + count = 5, + logfile; + + while (count--) { + logfile = path.join(__dirname, 'datefa-default-test' + count + '.log'); + log4js.addAppender(dateFileAppender.appender(logfile)); + } + + return listenersCount; + }, + teardown: function() { + removeFile('datefa-default-test0.log')(); + removeFile('datefa-default-test1.log')(); + removeFile('datefa-default-test2.log')(); + removeFile('datefa-default-test3.log')(); + removeFile('datefa-default-test4.log')(); + }, + + 'should only add one `exit` listener': function (initialCount) { + assert.equal(process.listeners('exit').length, initialCount + 1); + } + }, + + 'with default settings': { + topic: function() { + var that = this, + testFile = path.join(__dirname, 'date-appender-default.log'), + appender = require('../lib/appenders/dateFile').appender(testFile), + logger = log4js.getLogger('default-settings'); + log4js.clearAppenders(); + log4js.addAppender(appender, 'default-settings'); + + logger.info("This should be in the file."); + + setTimeout(function() { + fs.readFile(testFile, "utf8", that.callback); + }, 100); + + }, + teardown: removeFile('date-appender-default.log'), + + 'should write to the file': function(contents) { + assert.include(contents, 'This should be in the file'); + }, + + 'should use the basic layout': function(contents) { + assert.match(contents, /\[\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3}\] \[INFO\] default-settings - /); + } + } + + } +}).addBatch({ + 'configure': { + 'with dateFileAppender': { + topic: function() { + var log4js = require('../lib/log4js') + , logger; + //this config file defines one file appender (to ./date-file-test.log) + //and sets the log level for "tests" to WARN + log4js.configure('test/with-dateFile.json'); + logger = log4js.getLogger('tests'); + logger.info('this should not be written to the file'); + logger.warn('this should be written to the file'); + + fs.readFile(path.join(__dirname, 'date-file-test.log'), 'utf8', this.callback); + }, + teardown: removeFile('date-file-test.log'), + + 'should load appender configuration from a json file': function(err, contents) { + assert.include(contents, 'this should be written to the file\n'); + assert.equal(contents.indexOf('this should not be written to the file'), -1); + } + } + + } +}).exportTo(module); diff --git a/test/with-dateFile.json b/test/with-dateFile.json new file mode 100644 index 0000000..1872743 --- /dev/null +++ b/test/with-dateFile.json @@ -0,0 +1,17 @@ +{ + "appenders": [ + { + "category": "tests", + "type": "dateFile", + "filename": "test/date-file-test.log", + "pattern": "-from-MM-dd", + "layout": { + "type": "messagePassThrough" + } + } + ], + + "levels": { + "tests": "WARN" + } +}