From eb21e102080691d4143055096db64a8f11083b7c Mon Sep 17 00:00:00 2001 From: Nick Howes Date: Tue, 26 Feb 2013 13:24:02 +0000 Subject: [PATCH] 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" + } + } + ] +}