Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a703f2dc12 | ||
|
|
b2edbb1146 | ||
|
|
99e7c0981d | ||
|
|
06bab894af | ||
|
|
101739ebef | ||
|
|
f8ffccffd5 | ||
|
|
7d50b4aeff | ||
|
|
b12200fabc | ||
|
|
f8b6cc7c39 | ||
|
|
6314e4a344 | ||
|
|
d18fb466fb | ||
|
|
e638ff7271 | ||
|
|
2daf29b400 | ||
|
|
ca5272aacc | ||
|
|
614127bb10 | ||
|
|
a549df44b4 | ||
|
|
5e0982f0b1 | ||
|
|
f5a76d9073 | ||
|
|
29d941f0a6 | ||
|
|
0c2baa9690 | ||
|
|
9b538ee8ed | ||
|
|
e4d5228f2b | ||
|
|
6aacb0da0b | ||
|
|
6e3da6f44b | ||
|
|
3b5eb28115 | ||
|
|
633ed3cddb | ||
|
|
8ca092cdb9 | ||
|
|
3ec9811b5e | ||
|
|
c852fceaf4 | ||
|
|
c569919160 | ||
|
|
28f7c87a0e | ||
|
|
492919b940 | ||
|
|
470baa6c09 | ||
|
|
cd2ee14bde | ||
|
|
c09c11b147 | ||
|
|
b74a514369 | ||
|
|
fd05d90c2f | ||
|
|
73344ba79f | ||
|
|
22c156582f | ||
|
|
ae1a55fed9 | ||
|
|
2a38f460dc | ||
|
|
9f77734f74 | ||
|
|
ce8b6b06b9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ build
|
||||
node_modules
|
||||
.bob/
|
||||
test/streams/test-rolling-file-stream*
|
||||
test/streams/test-rolling-stream-with-existing-files*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# log4js-node [](http://travis-ci.org/nomiddlename/log4js-node)
|
||||
|
||||
|
||||
This is a conversion of the [log4js](http://log4js.berlios.de/index.html)
|
||||
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.
|
||||
|
||||
Out of the box it supports the following features:
|
||||
|
||||
27
examples/flush-on-exit.js
Normal file
27
examples/flush-on-exit.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* run this, then "ab -c 10 -n 100 localhost:4444/" to test (in
|
||||
* another shell)
|
||||
*/
|
||||
var log4js = require('../lib/log4js');
|
||||
log4js.configure({
|
||||
appenders: [
|
||||
{ type: 'file', filename: 'cheese.log', category: 'cheese' },
|
||||
{ type: 'console'}
|
||||
]
|
||||
});
|
||||
|
||||
var logger = log4js.getLogger('cheese');
|
||||
logger.setLevel('INFO');
|
||||
|
||||
var http=require('http');
|
||||
|
||||
var server = http.createServer(function(request, response){
|
||||
response.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
var rd = Math.random() * 50;
|
||||
logger.info("hello " + rd);
|
||||
response.write('hello ');
|
||||
if (Math.floor(rd) == 30){
|
||||
log4js.shutdown(function() { process.exit(1); });
|
||||
}
|
||||
response.end();
|
||||
}).listen(4444);
|
||||
@@ -71,7 +71,10 @@ function createAppender(config) {
|
||||
if (config.actualAppenders) {
|
||||
var size = config.actualAppenders.length;
|
||||
for(var i = 0; i < size; i++) {
|
||||
config.actualAppenders[i](loggingEvent);
|
||||
if (!config.appenders[i].category || config.appenders[i].category === loggingEvent.categoryName) {
|
||||
// Relying on the index is not a good practice but otherwise the change would have been bigger.
|
||||
config.actualAppenders[i](loggingEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
var streams = require('../streams')
|
||||
, layouts = require('../layouts')
|
||||
, async = require('async')
|
||||
, path = require('path')
|
||||
, os = require('os')
|
||||
, eol = os.EOL || '\n'
|
||||
@@ -24,12 +25,12 @@ function appender(filename, pattern, alwaysIncludePattern, layout) {
|
||||
layout = layout || layouts.basicLayout;
|
||||
|
||||
var logFile = new streams.DateRollingFileStream(
|
||||
filename,
|
||||
pattern,
|
||||
filename,
|
||||
pattern,
|
||||
{ alwaysIncludePattern: alwaysIncludePattern }
|
||||
);
|
||||
openFiles.push(logFile);
|
||||
|
||||
|
||||
return function(logEvent) {
|
||||
logFile.write(layout(logEvent) + eol, "utf8");
|
||||
};
|
||||
@@ -38,15 +39,15 @@ function appender(filename, pattern, alwaysIncludePattern, layout) {
|
||||
|
||||
function configure(config, options) {
|
||||
var layout;
|
||||
|
||||
|
||||
if (config.layout) {
|
||||
layout = layouts.layout(config.layout.type, config.layout);
|
||||
}
|
||||
|
||||
|
||||
if (!config.alwaysIncludePattern) {
|
||||
config.alwaysIncludePattern = false;
|
||||
}
|
||||
|
||||
|
||||
if (options && options.cwd && !config.absolute) {
|
||||
config.filename = path.join(options.cwd, config.filename);
|
||||
}
|
||||
@@ -54,5 +55,18 @@ function configure(config, options) {
|
||||
return appender(config.filename, config.pattern, config.alwaysIncludePattern, layout);
|
||||
}
|
||||
|
||||
function shutdown(cb) {
|
||||
async.forEach(openFiles, function(file, done) {
|
||||
if (!file.write(eol, "utf-8")) {
|
||||
file.once('drain', function() {
|
||||
file.end(done);
|
||||
});
|
||||
} else {
|
||||
file.end(done);
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
|
||||
exports.appender = appender;
|
||||
exports.configure = configure;
|
||||
exports.shutdown = shutdown;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use strict";
|
||||
var layouts = require('../layouts')
|
||||
, async = require('async')
|
||||
, path = require('path')
|
||||
, fs = require('fs')
|
||||
, streams = require('../streams')
|
||||
@@ -78,5 +79,18 @@ function configure(config, options) {
|
||||
return fileAppender(config.filename, layout, config.maxLogSize, config.backups);
|
||||
}
|
||||
|
||||
function shutdown(cb) {
|
||||
async.forEach(openFiles, function(file, done) {
|
||||
if (!file.write(eol, "utf-8")) {
|
||||
file.once('drain', function() {
|
||||
file.end(done);
|
||||
});
|
||||
} else {
|
||||
file.end(done);
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
|
||||
exports.appender = fileAppender;
|
||||
exports.configure = configure;
|
||||
exports.shutdown = shutdown;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
var layouts = require("../layouts")
|
||||
, loggly = require("loggly")
|
||||
'use strict';
|
||||
var layouts = require('../layouts')
|
||||
, loggly = require('loggly')
|
||||
, os = require('os');
|
||||
|
||||
/**
|
||||
@@ -12,15 +12,62 @@ var layouts = require("../layouts")
|
||||
* subdomain: 'your-subdomain',
|
||||
* tags: ['loggly-tag1', 'loggly-tag2', .., 'loggly-tagn']
|
||||
* }
|
||||
* @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 objectLayout).
|
||||
*/
|
||||
function logglyAppender(config, layout) {
|
||||
layout = layout || layouts.basicLayout;
|
||||
|
||||
var client = loggly.createClient(config);
|
||||
|
||||
var packageMessage = function (loggingEvent) {
|
||||
var BaseItem = function(level, msg) {
|
||||
this.level = level || loggingEvent.level.toString();
|
||||
this.category = loggingEvent.categoryName;
|
||||
this.hostname = os.hostname().toString();
|
||||
if (typeof msg !== 'undefined')
|
||||
this.msg = msg;
|
||||
};
|
||||
|
||||
var packageItem = function (item) {
|
||||
if (item instanceof Error)
|
||||
return new BaseItem('ERROR', item.message);
|
||||
|
||||
if (['string', 'number', 'boolean'].indexOf(typeof item) > -1 )
|
||||
return new BaseItem(undefined, item);
|
||||
|
||||
var obj = new BaseItem();
|
||||
if (Array.isArray(item))
|
||||
return item.unshift(obj); //add base object as first item
|
||||
|
||||
if (item && Object.prototype.toString.call(item) === '[object Object]') {
|
||||
for (var key in item) {
|
||||
if (item.hasOwnProperty(key)) {
|
||||
obj[key] = item[key]; //don't do packageItem on nested items, because level, category and hostname are needed on top level items only.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
if (loggingEvent.data.length === 1) {
|
||||
return packageItem(loggingEvent.data[0]);
|
||||
}
|
||||
//length >1
|
||||
var msg = loggingEvent.data;
|
||||
for (var i = 0, l = msg.length; i < l; i++) {
|
||||
msg[i] = packageItem(msg[i]);
|
||||
}
|
||||
|
||||
return msg;
|
||||
};
|
||||
|
||||
return function(loggingEvent) {
|
||||
client.log(layout(loggingEvent), config.tags);
|
||||
var a = layout ? layout(loggingEvent) : packageMessage(loggingEvent);
|
||||
//console.log('log now', a);
|
||||
client.log(a, config.tags, function(err, result) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,6 +79,6 @@ function configure(config) {
|
||||
return logglyAppender(config, layout);
|
||||
}
|
||||
|
||||
exports.name = "loggly";
|
||||
exports.name = 'loggly';
|
||||
exports.appender = logglyAppender;
|
||||
exports.configure = configure;
|
||||
@@ -44,17 +44,20 @@
|
||||
* Website: http://log4js.berlios.de
|
||||
*/
|
||||
var events = require('events')
|
||||
, async = require('async')
|
||||
, fs = require('fs')
|
||||
, path = require('path')
|
||||
, util = require('util')
|
||||
, layouts = require('./layouts')
|
||||
, levels = require('./levels')
|
||||
, LoggingEvent = require('./logger').LoggingEvent
|
||||
, Logger = require('./logger').Logger
|
||||
, loggerModule = require('./logger')
|
||||
, LoggingEvent = loggerModule.LoggingEvent
|
||||
, Logger = loggerModule.Logger
|
||||
, ALL_CATEGORIES = '[all]'
|
||||
, appenders = {}
|
||||
, loggers = {}
|
||||
, appenderMakers = {}
|
||||
, appenderShutdowns = {}
|
||||
, defaultConfig = {
|
||||
appenders: [
|
||||
{ type: "console" }
|
||||
@@ -62,6 +65,11 @@ var events = require('events')
|
||||
replaceConsole: false
|
||||
};
|
||||
|
||||
function hasLogger(logger) {
|
||||
return loggers.hasOwnProperty(logger);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a logger instance. Instance is cached on categoryName level.
|
||||
* @param {String} categoryName name of category to log to.
|
||||
@@ -76,7 +84,7 @@ function getLogger (categoryName) {
|
||||
}
|
||||
|
||||
var appenderList;
|
||||
if (!loggers[categoryName]) {
|
||||
if (!hasLogger(categoryName)) {
|
||||
// Create the logger for this name if it doesn't already exist
|
||||
loggers[categoryName] = new Logger(categoryName);
|
||||
if (appenders[categoryName]) {
|
||||
@@ -115,7 +123,7 @@ function addAppender () {
|
||||
|
||||
if (category === ALL_CATEGORIES) {
|
||||
addAppenderToAllLoggers(appender);
|
||||
} else if (loggers[category]) {
|
||||
} else if (hasLogger(category)) {
|
||||
loggers[category].addListener("log", appender);
|
||||
}
|
||||
});
|
||||
@@ -123,7 +131,7 @@ function addAppender () {
|
||||
|
||||
function addAppenderToAllLoggers(appender) {
|
||||
for (var logger in loggers) {
|
||||
if (loggers.hasOwnProperty(logger)) {
|
||||
if (hasLogger(logger)) {
|
||||
loggers[logger].addListener("log", appender);
|
||||
}
|
||||
}
|
||||
@@ -139,7 +147,7 @@ function addAppenderToCategory(appender, category) {
|
||||
function clearAppenders () {
|
||||
appenders = {};
|
||||
for (var logger in loggers) {
|
||||
if (loggers.hasOwnProperty(logger)) {
|
||||
if (hasLogger(logger)) {
|
||||
loggers[logger].removeAllListeners("log");
|
||||
}
|
||||
}
|
||||
@@ -290,25 +298,89 @@ function restoreConsole() {
|
||||
});
|
||||
}
|
||||
|
||||
function loadAppender(appender) {
|
||||
/**
|
||||
* Load an appenderModule based on the provided appender filepath. Will first
|
||||
* check if the appender path is a subpath of the log4js "lib/appenders" directory.
|
||||
* If not, it will attempt to load the the appender as complete path.
|
||||
*
|
||||
* @param {string} appender The filepath for the appender.
|
||||
* @returns {Object|null} The required appender or null if appender could not be loaded.
|
||||
* @private
|
||||
*/
|
||||
function requireAppender(appender) {
|
||||
var appenderModule;
|
||||
try {
|
||||
appenderModule = require('./appenders/' + appender);
|
||||
} catch (e) {
|
||||
appenderModule = require(appender);
|
||||
}
|
||||
return appenderModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an appender. Provided the appender path to be loaded. If appenderModule is defined,
|
||||
* it will be used in place of requiring the appender module.
|
||||
*
|
||||
* @param {string} appender The path to the appender module.
|
||||
* @param {Object|void} [appenderModule] The pre-required appender module. When provided,
|
||||
* instead of requiring the appender by its path, this object will be used.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function loadAppender(appender, appenderModule) {
|
||||
appenderModule = appenderModule || requireAppender(appender);
|
||||
|
||||
if (!appenderModule) {
|
||||
throw new Error("Invalid log4js appender: " + util.inspect(appender));
|
||||
}
|
||||
|
||||
module.exports.appenders[appender] = appenderModule.appender.bind(appenderModule);
|
||||
if (appenderModule.shutdown) {
|
||||
appenderShutdowns[appender] = appenderModule.shutdown.bind(appenderModule);
|
||||
}
|
||||
appenderMakers[appender] = appenderModule.configure.bind(appenderModule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown all log appenders. This will first disable all writing to appenders
|
||||
* and then call the shutdown function each appender.
|
||||
*
|
||||
* @params {Function} cb - The callback to be invoked once all appenders have
|
||||
* shutdown. If an error occurs, the callback will be given the error object
|
||||
* as the first argument.
|
||||
* @returns {void}
|
||||
*/
|
||||
function shutdown(cb) {
|
||||
// First, disable all writing to appenders. This prevents appenders from
|
||||
// not being able to be drained because of run-away log writes.
|
||||
loggerModule.disableAllLogWrites();
|
||||
|
||||
// Next, get all the shutdown functions for appenders as an array.
|
||||
var shutdownFunctions = Object.keys(appenderShutdowns).reduce(
|
||||
function(accum, category) {
|
||||
return accum.concat(appenderShutdowns[category]);
|
||||
}, []);
|
||||
|
||||
// Call each of the shutdown functions.
|
||||
async.forEach(
|
||||
shutdownFunctions,
|
||||
function(shutdownFn, done) {
|
||||
shutdownFn(done);
|
||||
},
|
||||
cb
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getLogger: getLogger,
|
||||
getDefaultLogger: getDefaultLogger,
|
||||
hasLogger: hasLogger,
|
||||
|
||||
addAppender: addAppender,
|
||||
loadAppender: loadAppender,
|
||||
clearAppenders: clearAppenders,
|
||||
configure: configure,
|
||||
shutdown: shutdown,
|
||||
|
||||
replaceConsole: replaceConsole,
|
||||
restoreConsole: restoreConsole,
|
||||
|
||||
@@ -4,6 +4,8 @@ var levels = require('./levels')
|
||||
, events = require('events')
|
||||
, DEFAULT_CATEGORY = '[default]';
|
||||
|
||||
var logWritesEnabled = true;
|
||||
|
||||
/**
|
||||
* Models a logging event.
|
||||
* @constructor
|
||||
@@ -49,9 +51,12 @@ Logger.prototype.removeLevel = function() {
|
||||
|
||||
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);
|
||||
, logLevel = levels.toLevel(args.shift())
|
||||
, loggingEvent;
|
||||
if (this.isLevelEnabled(logLevel)) {
|
||||
loggingEvent = new LoggingEvent(this.category, logLevel, args, this);
|
||||
this.emit("log", loggingEvent);
|
||||
}
|
||||
};
|
||||
|
||||
Logger.prototype.isLevelEnabled = function(otherLevel) {
|
||||
@@ -66,7 +71,7 @@ Logger.prototype.isLevelEnabled = function(otherLevel) {
|
||||
};
|
||||
|
||||
Logger.prototype[levelString.toLowerCase()] = function () {
|
||||
if (this.isLevelEnabled(level)) {
|
||||
if (logWritesEnabled && this.isLevelEnabled(level)) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
args.unshift(level);
|
||||
Logger.prototype.log.apply(this, args);
|
||||
@@ -75,6 +80,23 @@ Logger.prototype.isLevelEnabled = function(otherLevel) {
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Disable all log writes.
|
||||
* @returns {void}
|
||||
*/
|
||||
function disableAllLogWrites() {
|
||||
logWritesEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable log writes.
|
||||
* @returns {void}
|
||||
*/
|
||||
function enableAllLogWrites() {
|
||||
logWritesEnabled = true;
|
||||
}
|
||||
|
||||
exports.LoggingEvent = LoggingEvent;
|
||||
exports.Logger = Logger;
|
||||
exports.disableAllLogWrites = disableAllLogWrites;
|
||||
exports.enableAllLogWrites = enableAllLogWrites;
|
||||
|
||||
@@ -48,7 +48,13 @@ BaseRollingFileStream.prototype._write = function(chunk, encoding, callback) {
|
||||
function writeTheChunk() {
|
||||
debug("writing the chunk to the underlying stream");
|
||||
that.currentSize += chunk.length;
|
||||
that.theStream.write(chunk, encoding, callback);
|
||||
try {
|
||||
that.theStream.write(chunk, encoding, callback);
|
||||
}
|
||||
catch (err){
|
||||
debug(err);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
debug("in _write");
|
||||
|
||||
@@ -17,7 +17,14 @@ function DateRollingFileStream(filename, pattern, options, now) {
|
||||
}
|
||||
this.pattern = pattern || '.yyyy-MM-dd';
|
||||
this.now = now || Date.now;
|
||||
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
|
||||
|
||||
if (fs.existsSync(filename)) {
|
||||
var stat = fs.statSync(filename);
|
||||
this.lastTimeWeWroteSomething = format.asString(this.pattern, stat.mtime);
|
||||
} else {
|
||||
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
|
||||
}
|
||||
|
||||
this.baseFilename = filename;
|
||||
this.alwaysIncludePattern = false;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "log4js",
|
||||
"version": "0.6.10",
|
||||
"version": "0.6.15",
|
||||
"description": "Port of Log4js to work with node.",
|
||||
"keywords": [
|
||||
"logging",
|
||||
|
||||
@@ -37,7 +37,8 @@ vows.describe('log4js cluster appender').addBatch({
|
||||
});
|
||||
|
||||
var masterAppender = appenderModule.appender({
|
||||
actualAppenders: [ fakeActualAppender ]
|
||||
actualAppenders: [fakeActualAppender, fakeActualAppender, fakeActualAppender],
|
||||
appenders: [{}, {category: "test"}, {category: "wovs"}]
|
||||
});
|
||||
|
||||
// Actual test - log message using masterAppender
|
||||
@@ -56,7 +57,9 @@ vows.describe('log4js cluster appender').addBatch({
|
||||
},
|
||||
|
||||
"should log using actual appender": function(topic) {
|
||||
assert.equal(topic.loggingEvents.length, 2)
|
||||
assert.equal(topic.loggingEvents[0].data[0], 'masterAppender test');
|
||||
assert.equal(topic.loggingEvents[1].data[0], 'masterAppender test');
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
@@ -86,6 +86,21 @@ vows.describe('log4js configure').addBatch({
|
||||
assert.isFunction(log4js.appenderMakers['some/other/external']);
|
||||
}
|
||||
},
|
||||
'when appender object loaded via loadAppender': {
|
||||
topic: function() {
|
||||
var testAppender = makeTestAppender(),
|
||||
log4js = sandbox.require('../lib/log4js');
|
||||
|
||||
log4js.loadAppender('some/other/external', testAppender);
|
||||
return log4js;
|
||||
},
|
||||
'should load appender with provided object': 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']);
|
||||
}
|
||||
},
|
||||
'when configuration file loaded via LOG4JS_CONFIG environment variable': {
|
||||
topic: function() {
|
||||
process.env.LOG4JS_CONFIG = 'some/path/to/mylog4js.json';
|
||||
|
||||
@@ -4,7 +4,8 @@ var vows = require('vows')
|
||||
, path = require('path')
|
||||
, fs = require('fs')
|
||||
, sandbox = require('sandboxed-module')
|
||||
, log4js = require('../lib/log4js');
|
||||
, log4js = require('../lib/log4js')
|
||||
, EOL = require('os').EOL || '\n';
|
||||
|
||||
function removeFile(filename) {
|
||||
return function() {
|
||||
@@ -134,7 +135,10 @@ vows.describe('../lib/appenders/dateFile').addBatch({
|
||||
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' + require('os').EOL);
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
assert.include(contents, 'this should be written to the file' + EOL);
|
||||
assert.equal(contents.indexOf('this should not be written to the file'), -1);
|
||||
}
|
||||
},
|
||||
@@ -161,7 +165,7 @@ vows.describe('../lib/appenders/dateFile').addBatch({
|
||||
, thisTime = format.asString(options.appenders[0].pattern, new Date());
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, 'date-file-test' + thisTime),
|
||||
"this is existing data" + require('os').EOL,
|
||||
"this is existing data" + EOL,
|
||||
'utf8'
|
||||
);
|
||||
log4js.clearAppenders();
|
||||
|
||||
@@ -7,7 +7,7 @@ function test(args, pattern, value) {
|
||||
var layout = args[0]
|
||||
, event = args[1]
|
||||
, tokens = args[2];
|
||||
|
||||
|
||||
assert.equal(layout(pattern, tokens)(event), value);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ vows.describe('log4js layouts').addBatch({
|
||||
topic: function() {
|
||||
return require('../lib/layouts').colouredLayout;
|
||||
},
|
||||
|
||||
|
||||
'should apply level colour codes to output': function(layout) {
|
||||
var output = layout({
|
||||
data: ["nonsense"],
|
||||
@@ -40,7 +40,7 @@ vows.describe('log4js layouts').addBatch({
|
||||
assert.equal(output, '\x1B[31m[2010-12-05 14:18:30.045] [ERROR] cheese - \x1B[39mthing 2');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
'messagePassThroughLayout': {
|
||||
topic: function() {
|
||||
return require('../lib/layouts').messagePassThroughLayout;
|
||||
@@ -58,49 +58,49 @@ vows.describe('log4js layouts').addBatch({
|
||||
},
|
||||
'should support the console.log format for the message' : function(layout) {
|
||||
assert.equal(layout({
|
||||
data: ["thing %d", 1, "cheese"],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
data: ["thing %d", 1, "cheese"],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
level : {
|
||||
colour: "green",
|
||||
colour: "green",
|
||||
toString: function() { return "ERROR"; }
|
||||
}
|
||||
}), "thing 1 cheese");
|
||||
},
|
||||
'should output the first item even if it is not a string': function(layout) {
|
||||
assert.equal(layout({
|
||||
data: [ { thing: 1} ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
data: [ { thing: 1} ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
level: {
|
||||
colour: "green",
|
||||
colour: "green",
|
||||
toString: function() { return "ERROR"; }
|
||||
}
|
||||
}), "{ thing: 1 }");
|
||||
},
|
||||
'should print the stacks of a passed error objects': function(layout) {
|
||||
assert.isArray(layout({
|
||||
data: [ new Error() ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
data: [ new Error() ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
level: {
|
||||
colour: "green",
|
||||
colour: "green",
|
||||
toString: function() { return "ERROR"; }
|
||||
}
|
||||
}).match(/Error\s+at Object\..*\s+\((.*)test[\\\/]layouts-test\.js\:\d+\:\d+\)\s+at runTest/)
|
||||
, 'regexp did not return a match');
|
||||
},
|
||||
'with passed augmented errors': {
|
||||
'with passed augmented errors': {
|
||||
topic: function(layout){
|
||||
var e = new Error("My Unique Error Message");
|
||||
e.augmented = "My Unique attribute value";
|
||||
e.augObj = { at1: "at2" };
|
||||
return layout({
|
||||
data: [ e ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
data: [ e ],
|
||||
startTime: new Date(2010, 11, 5, 14, 18, 30, 45),
|
||||
categoryName: "cheese",
|
||||
level: {
|
||||
colour: "green",
|
||||
colour: "green",
|
||||
toString: function() { return "ERROR"; }
|
||||
}
|
||||
});
|
||||
@@ -118,10 +118,10 @@ vows.describe('log4js layouts').addBatch({
|
||||
assert.isArray(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
'basicLayout': {
|
||||
topic: function() {
|
||||
var layout = require('../lib/layouts').basicLayout,
|
||||
@@ -143,17 +143,17 @@ vows.describe('log4js layouts').addBatch({
|
||||
var layout = args[0], event = args[1], output, lines,
|
||||
error = new Error("Some made-up error"),
|
||||
stack = error.stack.split(/\n/);
|
||||
|
||||
|
||||
event.data = ['this is a test', error];
|
||||
output = layout(event);
|
||||
lines = output.split(/\n/);
|
||||
|
||||
|
||||
assert.equal(lines.length - 1, stack.length);
|
||||
assert.equal(
|
||||
lines[0],
|
||||
lines[0],
|
||||
"[2010-12-05 14:18:30.045] [DEBUG] tests - this is a test [Error: Some made-up error]"
|
||||
);
|
||||
|
||||
|
||||
for (var i = 1; i < stack.length; i++) {
|
||||
assert.equal(lines[i+2], stack[i+1]);
|
||||
}
|
||||
@@ -166,13 +166,13 @@ vows.describe('log4js layouts').addBatch({
|
||||
}];
|
||||
output = layout(event);
|
||||
assert.equal(
|
||||
output,
|
||||
"[2010-12-05 14:18:30.045] [DEBUG] tests - this is a test " +
|
||||
output,
|
||||
"[2010-12-05 14:18:30.045] [DEBUG] tests - this is a test " +
|
||||
"{ name: 'Cheese', message: 'Gorgonzola smells.' }"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
'patternLayout': {
|
||||
topic: function() {
|
||||
var event = {
|
||||
@@ -188,9 +188,12 @@ vows.describe('log4js layouts').addBatch({
|
||||
testFunction: function() { return 'testFunctionToken'; },
|
||||
fnThatUsesLogEvent: function(logEvent) { return logEvent.level.toString(); }
|
||||
};
|
||||
|
||||
//override getTimezoneOffset
|
||||
event.startTime.getTimezoneOffset = function() { return 0; };
|
||||
return [layout, event, tokens];
|
||||
},
|
||||
|
||||
|
||||
'should default to "time logLevel loggerName - message"': function(args) {
|
||||
test(args, null, "14:18:30 DEBUG multiple.levels.of.tests - this is a test\n");
|
||||
},
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
var vows = require('vows')
|
||||
, assert = require('assert')
|
||||
, levels = require('../lib/levels')
|
||||
, Logger = require('../lib/logger').Logger;
|
||||
, loggerModule = require('../lib/logger')
|
||||
, Logger = loggerModule.Logger;
|
||||
|
||||
vows.describe('../lib/logger').addBatch({
|
||||
'constructor with no parameters': {
|
||||
@@ -53,5 +54,28 @@ vows.describe('../lib/logger').addBatch({
|
||||
assert.isTrue(logger.isErrorEnabled());
|
||||
assert.isTrue(logger.isFatalEnabled());
|
||||
}
|
||||
},
|
||||
|
||||
'should emit log events': {
|
||||
topic: function() {
|
||||
var events = [],
|
||||
logger = new Logger();
|
||||
logger.addListener('log', function (logEvent) { events.push(logEvent); });
|
||||
logger.debug('Event 1');
|
||||
loggerModule.disableAllLogWrites();
|
||||
logger.debug('Event 2');
|
||||
loggerModule.enableAllLogWrites();
|
||||
logger.debug('Event 3');
|
||||
return events;
|
||||
},
|
||||
|
||||
'when log writes are enabled': function(events) {
|
||||
assert.equal(events[0].data[0], 'Event 1');
|
||||
},
|
||||
|
||||
'but not when log writes are disabled': function(events) {
|
||||
assert.equal(events.length, 2);
|
||||
assert.equal(events[1].data[0], 'Event 3');
|
||||
}
|
||||
}
|
||||
}).exportTo(module);
|
||||
|
||||
@@ -75,13 +75,65 @@ vows.describe('log4js').addBatch({
|
||||
assert.equal(events[1].level.toString(), 'WARN');
|
||||
},
|
||||
|
||||
'should include the error if passed in': function (events) {
|
||||
'should include the error if passed in': function(events) {
|
||||
assert.instanceOf(events[2].data[1], Error);
|
||||
assert.equal(events[2].data[1].message, 'Pants are on fire!');
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
'when shutdown is called': {
|
||||
topic: function() {
|
||||
var events = {
|
||||
appenderShutdownCalled: false,
|
||||
shutdownCallbackCalled: false
|
||||
},
|
||||
log4js = sandbox.require(
|
||||
'../lib/log4js',
|
||||
{
|
||||
requires: {
|
||||
'./appenders/file':
|
||||
{
|
||||
name: "file",
|
||||
appender: function() {},
|
||||
configure: function(configuration) {
|
||||
return function() {};
|
||||
},
|
||||
shutdown: function(cb) {
|
||||
events.appenderShutdownCalled = true;
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
shutdownCallback = function() {
|
||||
events.shutdownCallbackCalled = true;
|
||||
},
|
||||
config = { appenders:
|
||||
[ { "type" : "file",
|
||||
"filename" : "cheesy-wotsits.log",
|
||||
"maxLogSize" : 1024,
|
||||
"backups" : 3
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
log4js.configure(config);
|
||||
log4js.shutdown(shutdownCallback);
|
||||
// Re-enable log writing so other tests that use logger are not
|
||||
// affected.
|
||||
require('../lib/logger').enableAllLogWrites();
|
||||
return events;
|
||||
},
|
||||
|
||||
|
||||
'should invoke appender shutdowns': function(events) {
|
||||
assert.ok(events.appenderShutdownCalled);
|
||||
},
|
||||
|
||||
'should call callback': function(events) {
|
||||
assert.ok(events.shutdownCallbackCalled);
|
||||
}
|
||||
},
|
||||
|
||||
'invalid configuration': {
|
||||
|
||||
@@ -70,7 +70,7 @@ vows.describe('log4js logglyAppender').addBatch({
|
||||
tags: ['loggly-tag1', 'loggly-tag2', 'loggly-tagn']
|
||||
});
|
||||
|
||||
setup.logger.log('Log event #1');
|
||||
setup.logger.log('trace', 'Log event #1');
|
||||
return setup;
|
||||
},
|
||||
'there should be one message only': function (topic) {
|
||||
|
||||
Reference in New Issue
Block a user