Moved Logger into separate file, added support for loading appenders outside log4js, removed 'name' from appender requirements

This commit is contained in:
Gareth Jones
2012-06-01 11:11:07 +10:00
parent 0ed1a137d6
commit a046523804
14 changed files with 236 additions and 26 deletions
-1
View File
@@ -16,6 +16,5 @@ function configure(config) {
return consoleAppender(layout); return consoleAppender(layout);
} }
exports.name = "console";
exports.appender = consoleAppender; exports.appender = consoleAppender;
exports.configure = configure; exports.configure = configure;
-1
View File
@@ -63,6 +63,5 @@ function configure(config, options) {
return fileAppender(config.filename, layout, config.maxLogSize, config.backups); return fileAppender(config.filename, layout, config.maxLogSize, config.backups);
} }
exports.name = "file";
exports.appender = fileAppender; exports.appender = fileAppender;
exports.configure = configure; exports.configure = configure;
-1
View File
@@ -89,6 +89,5 @@ function configure(config) {
return gelfAppender(layout, config.host, config.port, config.hostname, config.facility); return gelfAppender(layout, config.host, config.port, config.hostname, config.facility);
} }
exports.name = "gelf";
exports.appender = gelfAppender; exports.appender = gelfAppender;
exports.configure = configure; exports.configure = configure;
-1
View File
@@ -71,6 +71,5 @@ function configure(config) {
return createAppender(config); return createAppender(config);
} }
exports.name = 'hookio';
exports.appender = createAppender; exports.appender = createAppender;
exports.configure = configure; exports.configure = configure;
-1
View File
@@ -16,6 +16,5 @@ function configure(config) {
return logLevelFilter(config.level, appender); return logLevelFilter(config.level, appender);
} }
exports.name = "logLevelFilter";
exports.appender = logLevelFilter; exports.appender = logLevelFilter;
exports.configure = configure; exports.configure = configure;
-1
View File
@@ -72,6 +72,5 @@ function configure(config) {
return createAppender(config); return createAppender(config);
} }
exports.name = 'multiprocess';
exports.appender = createAppender; exports.appender = createAppender;
exports.configure = configure; exports.configure = configure;
+10 -11
View File
@@ -2,15 +2,15 @@ var layouts = require("../layouts"),
mailer = require("nodemailer"); mailer = require("nodemailer");
/** /**
* SMTP Appender. Sends logging events using SMTP protocol. * 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 recipients comma separated list of email recipients * @param recipients comma separated list of email recipients
* @param sender sender of all emails (defaults to SMTP user) * @param sender sender of all emails (defaults to SMTP user)
* @param subject subject of all email messages (defaults to first event's message) * @param subject subject of all email messages (defaults to first event's message)
* @param layout a function that takes a logevent and returns a string (defaults to basicLayout). * @param layout a function that takes a logevent and returns a string (defaults to basicLayout).
* @param smtpConfig SMTP configuration for 'nodemailer' * @param smtpConfig SMTP configuration for 'nodemailer'
* @param sendInterval the time in seconds between sending attempts (defaults to 0); * @param sendInterval the time in seconds between sending attempts (defaults to 0);
* all events are buffered and sent in one email during this time; if 0 than every event sends an email * all events are buffered and sent in one email during this time; if 0 than every event sends an email
*/ */
function smtpAppender(recipients, sender, subject, layout, smtpConfig, sendInterval) { function smtpAppender(recipients, sender, subject, layout, smtpConfig, sendInterval) {
@@ -19,20 +19,20 @@ function smtpAppender(recipients, sender, subject, layout, smtpConfig, sendInter
subjectLayout = layouts.messagePassThroughLayout; subjectLayout = layouts.messagePassThroughLayout;
mailer.SMTP = smtpConfig; mailer.SMTP = smtpConfig;
sendInterval = sendInterval*1000 || 0; sendInterval = sendInterval*1000 || 0;
var logEventBuffer = []; var logEventBuffer = [];
var sendTimer; var sendTimer;
function sendBuffer() { function sendBuffer() {
if (logEventBuffer.length == 0) if (logEventBuffer.length == 0)
return; return;
var firstEvent = logEventBuffer[0]; var firstEvent = logEventBuffer[0];
var body = ""; var body = "";
while (logEventBuffer.length > 0) { while (logEventBuffer.length > 0) {
body += layout(logEventBuffer.shift()) + "\n"; body += layout(logEventBuffer.shift()) + "\n";
} }
var msg = { var msg = {
sender: sender, sender: sender,
to: recipients, to: recipients,
@@ -45,15 +45,15 @@ function smtpAppender(recipients, sender, subject, layout, smtpConfig, sendInter
} }
}); });
} }
function scheduleSend() { function scheduleSend() {
if (!sendTimer) if (!sendTimer)
sendTimer = setTimeout(function() { sendTimer = setTimeout(function() {
sendTimer = null; sendTimer = null;
sendBuffer(); sendBuffer();
}, sendInterval); }, sendInterval);
} }
return function(loggingEvent) { return function(loggingEvent) {
logEventBuffer.push(loggingEvent); logEventBuffer.push(loggingEvent);
if (sendInterval > 0) if (sendInterval > 0)
@@ -71,6 +71,5 @@ function configure(config) {
return smtpAppender(config.recipients, config.sender, config.subject, layout, config.smtp, config.sendInterval); return smtpAppender(config.recipients, config.sender, config.subject, layout, config.smtp, config.sendInterval);
} }
exports.name = "smtp";
exports.appender = smtpAppender; exports.appender = smtpAppender;
exports.configure = configure; exports.configure = configure;
+7
View File
@@ -47,6 +47,13 @@ Level.prototype.isGreaterThanOrEqualTo = function(otherLevel) {
return this.level >= otherLevel.level; return this.level >= otherLevel.level;
}; };
Level.prototype.isEqualTo = function(otherLevel) {
if (typeof otherLevel == "string") {
otherLevel = toLevel(otherLevel);
}
return this.level === otherLevel.level;
}
module.exports = { module.exports = {
ALL: new Level(Number.MIN_VALUE, "ALL") ALL: new Level(Number.MIN_VALUE, "ALL")
, TRACE: new Level(5000, "TRACE") , TRACE: new Level(5000, "TRACE")
+8 -3
View File
@@ -282,9 +282,14 @@ function restoreConsole() {
} }
function loadAppender(appender) { function loadAppender(appender) {
var appenderModule = require('./appenders/' + appender); var appenderModule;
module.exports.appenders[appenderModule.name] = appenderModule.appender; try {
appenderMakers[appenderModule.name] = appenderModule.configure; 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 = { module.exports = {
+78
View File
@@ -0,0 +1,78 @@
var levels = require('./levels'),
util = require('util'),
events = require('events'),
DEFAULT_CATEGORY = '[default]';
/**
* Models a logging event.
* @constructor
* @param {String} categoryName name of category
* @param {Log4js.Level} level level of message
* @param {Array} data objects to log
* @param {Log4js.Logger} logger the associated logger
* @author Seth Chisamore
*/
function LoggingEvent (categoryName, level, data, logger) {
this.startTime = new Date();
this.categoryName = categoryName;
this.data = data;
this.level = level;
this.logger = logger;
}
/**
* Logger to log messages.
* use {@see Log4js#getLogger(String)} to get an instance.
* @constructor
* @param name name of category to log to
* @author Stephan Strittmatter
*/
function Logger (name, level) {
this.category = name || DEFAULT_CATEGORY;
if (! this.level) {
this.__proto__.level = levels.TRACE;
}
}
util.inherits(Logger, events.EventEmitter);
Logger.DEFAULT_CATEGORY = DEFAULT_CATEGORY;
Logger.prototype.setLevel = function(level) {
this.level = levels.toLevel(level, this.level || levels.TRACE);
};
Logger.prototype.removeLevel = function() {
delete this.level;
};
Logger.prototype.log = function() {
var args = Array.prototype.slice.call(arguments)
, logLevel = args.shift()
, loggingEvent = new LoggingEvent(this.category, logLevel, args, this);
this.emit("log", loggingEvent);
};
Logger.prototype.isLevelEnabled = function(otherLevel) {
return this.level.isLessThanOrEqualTo(otherLevel);
};
['Trace','Debug','Info','Warn','Error','Fatal'].forEach(
function(levelString) {
var level = levels.toLevel(levelString);
Logger.prototype['is'+levelString+'Enabled'] = function() {
return this.isLevelEnabled(level);
};
Logger.prototype[levelString.toLowerCase()] = function () {
if (this.isLevelEnabled(level)) {
var args = Array.prototype.slice.call(arguments);
args.unshift(level);
Logger.prototype.log.apply(this, args);
}
};
}
);
exports.LoggingEvent = LoggingEvent;
exports.Logger = Logger;
+89
View File
@@ -0,0 +1,89 @@
var assert = require('assert'),
vows = require('vows'),
sandbox = require('sandboxed-module');
function makeTestAppender() {
return {
configure: function(config, options) {
this.configureCalled = true;
this.config = config;
this.options = options;
return this.appender();
},
appender: function() {
var self = this;
return function(logEvt) { self.logEvt = logEvt; }
}
};
}
vows.describe('log4js configure').addBatch({
'appenders': {
'when specified by type': {
topic: function() {
var testAppender = makeTestAppender(),
log4js = sandbox.require(
'../lib/log4js',
{
requires: {
'./appenders/cheese': testAppender
}
}
);
log4js.configure(
{
appenders: [
{ type: "cheese", flavour: "gouda" }
]
},
{ pants: "yes" }
);
return testAppender;
},
'should load appender': function(testAppender) {
assert.ok(testAppender.configureCalled);
},
'should pass config to appender': function(testAppender) {
assert.equal(testAppender.config.flavour, 'gouda');
},
'should pass log4js options to appender': function(testAppender) {
assert.equal(testAppender.options.pants, 'yes');
}
},
'when core appender loaded via loadAppender': {
topic: function() {
var testAppender = makeTestAppender(),
log4js = sandbox.require(
'../lib/log4js',
{ requires: { './appenders/cheese': testAppender } }
);
log4js.loadAppender('cheese');
return log4js;
},
'should load appender from ../lib/appenders': function(log4js) {
assert.ok(log4js.appenders.cheese);
},
'should add appender configure function to appenderMakers' : function(log4js) {
assert.isFunction(log4js.appenderMakers.cheese);
}
},
'when appender in node_modules loaded via loadAppender': {
topic: function() {
var testAppender = makeTestAppender(),
log4js = sandbox.require(
'../lib/log4js',
{ requires: { 'some/other/external': testAppender } }
);
log4js.loadAppender('some/other/external');
return log4js;
},
'should load appender via require': function(log4js) {
assert.ok(log4js.appenders['some/other/external']);
},
'should add appender configure function to appenderMakers': function(log4js) {
assert.isFunction(log4js.appenderMakers['some/other/external']);
}
}
}
}).exportTo(module);
+38
View File
@@ -21,6 +21,12 @@ function assertThat(level) {
}, },
isNotGreaterThanOrEqualTo: function(levels) { isNotGreaterThanOrEqualTo: function(levels) {
assertForEach(assert.isFalse, level.isGreaterThanOrEqualTo, levels); assertForEach(assert.isFalse, level.isGreaterThanOrEqualTo, levels);
},
isEqualTo: function(levels) {
assertForEach(assert.isTrue, level.isEqualTo, levels);
},
isNotEqualTo: function(levels) {
assertForEach(assert.isFalse, level.isEqualTo, levels);
} }
}; };
} }
@@ -45,6 +51,10 @@ vows.describe('levels').addBatch({
}, },
'should be greater than no levels': function(all) { 'should be greater than no levels': function(all) {
assertThat(all).isNotGreaterThanOrEqualTo([levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]); assertThat(all).isNotGreaterThanOrEqualTo([levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
},
'should only be equal to ALL': function(all) {
assertThat(all).isEqualTo([levels.toLevel("ALL")]);
assertThat(all).isNotEqualTo([levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
} }
}, },
'TRACE': { 'TRACE': {
@@ -56,6 +66,10 @@ vows.describe('levels').addBatch({
'should be greater than ALL': function(trace) { 'should be greater than ALL': function(trace) {
assertThat(trace).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE]); assertThat(trace).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE]);
assertThat(trace).isNotGreaterThanOrEqualTo([levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]); assertThat(trace).isNotGreaterThanOrEqualTo([levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
},
'should only be equal to TRACE': function(trace) {
assertThat(trace).isEqualTo([levels.toLevel("TRACE")]);
assertThat(trace).isNotEqualTo([levels.ALL, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
} }
}, },
'DEBUG': { 'DEBUG': {
@@ -67,6 +81,10 @@ vows.describe('levels').addBatch({
'should be greater than TRACE': function(debug) { 'should be greater than TRACE': function(debug) {
assertThat(debug).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE]); assertThat(debug).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE]);
assertThat(debug).isNotGreaterThanOrEqualTo([levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]); assertThat(debug).isNotGreaterThanOrEqualTo([levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
},
'should only be equal to DEBUG': function(trace) {
assertThat(trace).isEqualTo([levels.toLevel("DEBUG")]);
assertThat(trace).isNotEqualTo([levels.ALL, levels.TRACE, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
} }
}, },
'INFO': { 'INFO': {
@@ -78,6 +96,10 @@ vows.describe('levels').addBatch({
'should be greater than DEBUG': function(info) { 'should be greater than DEBUG': function(info) {
assertThat(info).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG]); assertThat(info).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG]);
assertThat(info).isNotGreaterThanOrEqualTo([levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]); assertThat(info).isNotGreaterThanOrEqualTo([levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
},
'should only be equal to INFO': function(trace) {
assertThat(trace).isEqualTo([levels.toLevel("INFO")]);
assertThat(trace).isNotEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.WARN, levels.ERROR, levels.FATAL, levels.OFF]);
} }
}, },
'WARN': { 'WARN': {
@@ -89,6 +111,10 @@ vows.describe('levels').addBatch({
'should be greater than INFO': function(warn) { 'should be greater than INFO': function(warn) {
assertThat(warn).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO]); assertThat(warn).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO]);
assertThat(warn).isNotGreaterThanOrEqualTo([levels.ERROR, levels.FATAL, levels.OFF]); assertThat(warn).isNotGreaterThanOrEqualTo([levels.ERROR, levels.FATAL, levels.OFF]);
},
'should only be equal to WARN': function(trace) {
assertThat(trace).isEqualTo([levels.toLevel("WARN")]);
assertThat(trace).isNotEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.ERROR, levels.FATAL, levels.OFF]);
} }
}, },
'ERROR': { 'ERROR': {
@@ -100,6 +126,10 @@ vows.describe('levels').addBatch({
'should be greater than WARN': function(error) { 'should be greater than WARN': function(error) {
assertThat(error).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN]); assertThat(error).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN]);
assertThat(error).isNotGreaterThanOrEqualTo([levels.FATAL, levels.OFF]); assertThat(error).isNotGreaterThanOrEqualTo([levels.FATAL, levels.OFF]);
},
'should only be equal to ERROR': function(trace) {
assertThat(trace).isEqualTo([levels.toLevel("ERROR")]);
assertThat(trace).isNotEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.FATAL, levels.OFF]);
} }
}, },
'FATAL': { 'FATAL': {
@@ -111,6 +141,10 @@ vows.describe('levels').addBatch({
'should be greater than ERROR': function(fatal) { 'should be greater than ERROR': function(fatal) {
assertThat(fatal).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR]); assertThat(fatal).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR]);
assertThat(fatal).isNotGreaterThanOrEqualTo([levels.OFF]); assertThat(fatal).isNotGreaterThanOrEqualTo([levels.OFF]);
},
'should only be equal to FATAL': function(fatal) {
assertThat(fatal).isEqualTo([levels.toLevel("FATAL")]);
assertThat(fatal).isNotEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.OFF]);
} }
}, },
'OFF': { 'OFF': {
@@ -120,6 +154,10 @@ vows.describe('levels').addBatch({
}, },
'should be greater than everything': function(off) { 'should be greater than everything': function(off) {
assertThat(off).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL]); assertThat(off).isGreaterThanOrEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL]);
},
'should only be equal to OFF': function(off) {
assertThat(off).isEqualTo([levels.toLevel("OFF")]);
assertThat(off).isNotEqualTo([levels.ALL, levels.TRACE, levels.DEBUG, levels.INFO, levels.WARN, levels.ERROR, levels.FATAL]);
} }
} }
}, },
+2 -2
View File
@@ -77,7 +77,7 @@ vows.describe('log4js connect logger').addBatch({
'check message': function(messages) { 'check message': function(messages) {
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.include(messages[0].message, 'GET'); assert.include(messages[0].message, 'GET');
assert.include(messages[0].message, 'http://url'); assert.include(messages[0].message, 'http://url');
assert.include(messages[0].message, 'my.remote.addr'); assert.include(messages[0].message, 'my.remote.addr');
@@ -118,7 +118,7 @@ vows.describe('log4js connect logger').addBatch({
'check message': function(messages) { 'check message': function(messages) {
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.equal(messages[0].message, 'GET http://url'); assert.equal(messages[0].message, 'GET http://url');
} }
} }
+4 -4
View File
@@ -67,7 +67,7 @@ vows.describe('log4js connect logger').addBatch({
, 'check message': function(messages){ , 'check message': function(messages){
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.include(messages[0].message, 'GET'); assert.include(messages[0].message, 'GET');
assert.include(messages[0].message, 'http://url'); assert.include(messages[0].message, 'http://url');
assert.include(messages[0].message, 'my.remote.addr'); assert.include(messages[0].message, 'my.remote.addr');
@@ -109,7 +109,7 @@ vows.describe('log4js connect logger').addBatch({
, 'check message': function(messages){ , 'check message': function(messages){
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.include(messages[0].message, 'GET'); assert.include(messages[0].message, 'GET');
assert.include(messages[0].message, 'http://url'); assert.include(messages[0].message, 'http://url');
assert.include(messages[0].message, 'my.remote.addr'); assert.include(messages[0].message, 'my.remote.addr');
@@ -163,7 +163,7 @@ vows.describe('log4js connect logger').addBatch({
, 'check message': function(messages){ , 'check message': function(messages){
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.include(messages[0].message, 'GET'); assert.include(messages[0].message, 'GET');
assert.include(messages[0].message, 'http://url'); assert.include(messages[0].message, 'http://url');
assert.include(messages[0].message, 'my.remote.addr'); assert.include(messages[0].message, 'my.remote.addr');
@@ -218,7 +218,7 @@ vows.describe('log4js connect logger').addBatch({
, 'check message': function(messages){ , 'check message': function(messages){
assert.isArray(messages); assert.isArray(messages);
assert.equal(messages.length, 1); assert.equal(messages.length, 1);
assert.equal(messages[0].level, levels.INFO); assert.ok(levels.INFO.isEqualTo(messages[0].level));
assert.include(messages[0].message, 'GET'); assert.include(messages[0].message, 'GET');
assert.include(messages[0].message, 'http://url'); assert.include(messages[0].message, 'http://url');
assert.include(messages[0].message, 'my.remote.addr'); assert.include(messages[0].message, 'my.remote.addr');