Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaa77b0454 | ||
|
|
78c604b90d | ||
|
|
4648e7a5e6 | ||
|
|
8f3e040786 | ||
|
|
60d2e093ae | ||
|
|
a06478632e | ||
|
|
a4d55b3339 | ||
|
|
914ed5356b | ||
|
|
52b4aa1874 | ||
|
|
2b0a58c2f2 | ||
|
|
fcafed9a7e | ||
|
|
7ff053f104 | ||
|
|
0f51ab1bb3 | ||
|
|
5b2d840472 | ||
|
|
ca635fc4b9 | ||
|
|
f44af56f9e | ||
|
|
a703f2dc12 | ||
|
|
b2edbb1146 | ||
|
|
99e7c0981d | ||
|
|
06bab894af | ||
|
|
101739ebef | ||
|
|
f8ffccffd5 | ||
|
|
7d50b4aeff | ||
|
|
b12200fabc | ||
|
|
f8b6cc7c39 | ||
|
|
6314e4a344 | ||
|
|
d18fb466fb | ||
|
|
e638ff7271 | ||
|
|
2daf29b400 | ||
|
|
8cf03507dd | ||
|
|
ca5272aacc | ||
|
|
614127bb10 | ||
|
|
a549df44b4 | ||
|
|
5e0982f0b1 | ||
|
|
f5a76d9073 | ||
|
|
29d941f0a6 | ||
|
|
c569919160 | ||
|
|
28f7c87a0e | ||
|
|
6ae01b2b84 | ||
|
|
e7c0b0da52 | ||
|
|
25fa48ee8d | ||
|
|
ae1a55fed9 | ||
|
|
7fcdb2e651 | ||
|
|
60a84f16cf | ||
|
|
723dbec964 |
@@ -134,6 +134,8 @@ Documentation for most of the core appenders can be found on the [wiki](https://
|
||||
## Documentation
|
||||
See the [wiki](https://github.com/nomiddlename/log4js-node/wiki). Improve the [wiki](https://github.com/nomiddlename/log4js-node/wiki), please.
|
||||
|
||||
There's also [an example application](https://github.com/nomiddlename/log4js-example).
|
||||
|
||||
## Contributing
|
||||
Contributions welcome, but take a look at the [rules](https://github.com/nomiddlename/log4js-node/wiki/Contributing) first.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -85,6 +85,8 @@ function shutdown(cb) {
|
||||
file.once('drain', function() {
|
||||
file.end(done);
|
||||
});
|
||||
} else {
|
||||
file.end(done);
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
|
||||
187
lib/appenders/fileSync.js
Executable file
187
lib/appenders/fileSync.js
Executable file
@@ -0,0 +1,187 @@
|
||||
"use strict";
|
||||
var debug = require('../debug')('fileSync')
|
||||
, layouts = require('../layouts')
|
||||
, path = require('path')
|
||||
, fs = require('fs')
|
||||
, streams = require('../streams')
|
||||
, os = require('os')
|
||||
, eol = os.EOL || '\n'
|
||||
;
|
||||
|
||||
function RollingFileSync (filename, size, backups, options) {
|
||||
debug("In RollingFileStream");
|
||||
|
||||
function throwErrorIfArgumentsAreNotValid() {
|
||||
if (!filename || !size || size <= 0) {
|
||||
throw new Error("You must specify a filename and file size");
|
||||
}
|
||||
}
|
||||
|
||||
throwErrorIfArgumentsAreNotValid();
|
||||
|
||||
this.filename = filename;
|
||||
this.size = size;
|
||||
this.backups = backups || 1;
|
||||
this.options = options || { encoding: 'utf8', mode: parseInt('0644', 8), flags: 'a' };
|
||||
this.currentSize = 0;
|
||||
|
||||
function currentFileSize(file) {
|
||||
var fileSize = 0;
|
||||
try {
|
||||
fileSize = fs.statSync(file).size;
|
||||
} catch (e) {
|
||||
// file does not exist
|
||||
fs.appendFileSync(filename, '');
|
||||
}
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
this.currentSize = currentFileSize(this.filename);
|
||||
}
|
||||
|
||||
RollingFileSync.prototype.shouldRoll = function() {
|
||||
debug("should roll with current size %d, and max size %d", this.currentSize, this.size);
|
||||
return this.currentSize >= this.size;
|
||||
};
|
||||
|
||||
RollingFileSync.prototype.roll = function(filename) {
|
||||
var that = this,
|
||||
nameMatcher = new RegExp('^' + path.basename(filename));
|
||||
|
||||
function justTheseFiles (item) {
|
||||
return nameMatcher.test(item);
|
||||
}
|
||||
|
||||
function index(filename_) {
|
||||
return parseInt(filename_.substring((path.basename(filename) + '.').length), 10) || 0;
|
||||
}
|
||||
|
||||
function byIndex(a, b) {
|
||||
if (index(a) > index(b)) {
|
||||
return 1;
|
||||
} else if (index(a) < index(b) ) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function increaseFileIndex (fileToRename) {
|
||||
var idx = index(fileToRename);
|
||||
debug('Index of ' + fileToRename + ' is ' + idx);
|
||||
if (idx < that.backups) {
|
||||
//on windows, you can get a EEXIST error if you rename a file to an existing file
|
||||
//so, we'll try to delete the file we're renaming to first
|
||||
try {
|
||||
fs.unlinkSync(filename + '.' + (idx+1));
|
||||
} catch(e) {
|
||||
//ignore err: if we could not delete, it's most likely that it doesn't exist
|
||||
}
|
||||
|
||||
debug('Renaming ' + fileToRename + ' -> ' + filename + '.' + (idx+1));
|
||||
fs.renameSync(path.join(path.dirname(filename), fileToRename), filename + '.' + (idx + 1));
|
||||
}
|
||||
}
|
||||
|
||||
function renameTheFiles() {
|
||||
//roll the backups (rename file.n to file.n+1, where n <= numBackups)
|
||||
debug("Renaming the old files");
|
||||
|
||||
var files = fs.readdirSync(path.dirname(filename));
|
||||
files.filter(justTheseFiles).sort(byIndex).reverse().forEach(increaseFileIndex);
|
||||
}
|
||||
|
||||
debug("Rolling, rolling, rolling");
|
||||
renameTheFiles();
|
||||
};
|
||||
|
||||
RollingFileSync.prototype.write = function(chunk, encoding) {
|
||||
var that = this;
|
||||
|
||||
|
||||
function writeTheChunk() {
|
||||
debug("writing the chunk to the file");
|
||||
that.currentSize += chunk.length;
|
||||
fs.appendFileSync(that.filename, chunk);
|
||||
}
|
||||
|
||||
debug("in write");
|
||||
|
||||
|
||||
if (this.shouldRoll()) {
|
||||
this.currentSize = 0;
|
||||
this.roll(this.filename);
|
||||
}
|
||||
|
||||
writeTheChunk();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* File Appender writing the logs to a text file. Supports rolling of logs by size.
|
||||
*
|
||||
* @param file file log messages will be written to
|
||||
* @param layout a function that takes a logevent and returns a string
|
||||
* (defaults to basicLayout).
|
||||
* @param logSize - the maximum size (in bytes) for a log file,
|
||||
* if not provided then logs won't be rotated.
|
||||
* @param numBackups - the number of log files to keep after logSize
|
||||
* has been reached (default 5)
|
||||
*/
|
||||
function fileAppender (file, layout, logSize, numBackups) {
|
||||
debug("fileSync appender created");
|
||||
var bytesWritten = 0;
|
||||
file = path.normalize(file);
|
||||
layout = layout || layouts.basicLayout;
|
||||
numBackups = numBackups === undefined ? 5 : numBackups;
|
||||
//there has to be at least one backup if logSize has been specified
|
||||
numBackups = numBackups === 0 ? 1 : numBackups;
|
||||
|
||||
function openTheStream(file, fileSize, numFiles) {
|
||||
var stream;
|
||||
|
||||
if (fileSize) {
|
||||
stream = new RollingFileSync(
|
||||
file,
|
||||
fileSize,
|
||||
numFiles
|
||||
);
|
||||
} else {
|
||||
stream = (function(f) {
|
||||
// create file if it doesn't exist
|
||||
if (!fs.existsSync(f))
|
||||
fs.appendFileSync(f, '');
|
||||
|
||||
return {
|
||||
write: function(data) {
|
||||
fs.appendFileSync(f, data);
|
||||
}
|
||||
};
|
||||
})(file);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
var logFile = openTheStream(file, logSize, numBackups);
|
||||
|
||||
return function(loggingEvent) {
|
||||
logFile.write(layout(loggingEvent) + eol);
|
||||
};
|
||||
}
|
||||
|
||||
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 fileAppender(config.filename, layout, config.maxLogSize, config.backups);
|
||||
}
|
||||
|
||||
exports.appender = fileAppender;
|
||||
exports.configure = configure;
|
||||
@@ -48,11 +48,14 @@ function gelfAppender (layout, host, port, hostname, facility) {
|
||||
host = host || 'localhost';
|
||||
port = port || 12201;
|
||||
hostname = hostname || require('os').hostname();
|
||||
facility = facility || 'nodejs-server';
|
||||
layout = layout || layouts.messagePassThroughLayout;
|
||||
|
||||
var defaultCustomFields = customFields || {};
|
||||
|
||||
|
||||
if(facility) {
|
||||
defaultCustomFields['_facility'] = facility;
|
||||
}
|
||||
|
||||
var client = dgram.createSocket("udp4");
|
||||
|
||||
process.on('exit', function() {
|
||||
@@ -96,14 +99,12 @@ function gelfAppender (layout, host, port, hostname, facility) {
|
||||
function preparePacket(loggingEvent) {
|
||||
var msg = {};
|
||||
addCustomFields(loggingEvent, msg);
|
||||
msg.full_message = layout(loggingEvent);
|
||||
msg.short_message = msg.full_message;
|
||||
msg.short_message = layout(loggingEvent);
|
||||
|
||||
msg.version="1.0";
|
||||
msg.version="1.1";
|
||||
msg.timestamp = msg.timestamp || new Date().getTime() / 1000; // log should use millisecond
|
||||
msg.host = hostname;
|
||||
msg.level = levelMapping[loggingEvent.level || levels.DEBUG];
|
||||
msg.facility = facility;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -174,6 +174,9 @@ function configureLevels(levels) {
|
||||
if (levels) {
|
||||
for (var category in levels) {
|
||||
if (levels.hasOwnProperty(category)) {
|
||||
if(category === ALL_CATEGORIES) {
|
||||
setGlobalLogLevel(levels[category]);
|
||||
}
|
||||
getLogger(category).setLevel(levels[category]);
|
||||
}
|
||||
}
|
||||
@@ -298,13 +301,42 @@ 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);
|
||||
|
||||
@@ -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.13",
|
||||
"version": "0.6.16",
|
||||
"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';
|
||||
|
||||
181
test/fileSyncAppender-test.js
Executable file
181
test/fileSyncAppender-test.js
Executable file
@@ -0,0 +1,181 @@
|
||||
"use strict";
|
||||
var vows = require('vows')
|
||||
, fs = require('fs')
|
||||
, path = require('path')
|
||||
, sandbox = require('sandboxed-module')
|
||||
, log4js = require('../lib/log4js')
|
||||
, assert = require('assert');
|
||||
|
||||
log4js.clearAppenders();
|
||||
|
||||
function remove(filename) {
|
||||
try {
|
||||
fs.unlinkSync(filename);
|
||||
} catch (e) {
|
||||
//doesn't really matter if it failed
|
||||
}
|
||||
}
|
||||
|
||||
vows.describe('log4js fileSyncAppender').addBatch({
|
||||
'with default fileSyncAppender settings': {
|
||||
topic: function() {
|
||||
var that = this
|
||||
, testFile = path.join(__dirname, '/fa-default-sync-test.log')
|
||||
, logger = log4js.getLogger('default-settings');
|
||||
remove(testFile);
|
||||
|
||||
log4js.clearAppenders();
|
||||
log4js.addAppender(require('../lib/appenders/fileSync').appender(testFile), 'default-settings');
|
||||
|
||||
logger.info("This should be in the file.");
|
||||
|
||||
fs.readFile(testFile, "utf8", that.callback);
|
||||
},
|
||||
'should write log messages to the file': function(err, fileContents) {
|
||||
assert.include(fileContents, "This should be in the file.\n");
|
||||
},
|
||||
'log messages should be in the basic layout format': function(err, fileContents) {
|
||||
assert.match(
|
||||
fileContents,
|
||||
/\[\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3}\] \[INFO\] default-settings - /
|
||||
);
|
||||
}
|
||||
},
|
||||
'with a max file size and no backups': {
|
||||
topic: function() {
|
||||
var testFile = path.join(__dirname, '/fa-maxFileSize-sync-test.log')
|
||||
, logger = log4js.getLogger('max-file-size')
|
||||
, that = this;
|
||||
remove(testFile);
|
||||
remove(testFile + '.1');
|
||||
//log file of 100 bytes maximum, no backups
|
||||
log4js.clearAppenders();
|
||||
log4js.addAppender(
|
||||
require('../lib/appenders/fileSync').appender(testFile, log4js.layouts.basicLayout, 100, 0),
|
||||
'max-file-size'
|
||||
);
|
||||
logger.info("This is the first log message.");
|
||||
logger.info("This is an intermediate log message.");
|
||||
logger.info("This is the second log message.");
|
||||
|
||||
fs.readFile(testFile, "utf8", that.callback);
|
||||
},
|
||||
'log file should only contain the second message': function(err, fileContents) {
|
||||
assert.include(fileContents, "This is the second log message.\n");
|
||||
assert.equal(fileContents.indexOf("This is the first log message."), -1);
|
||||
},
|
||||
'the number of files': {
|
||||
topic: function() {
|
||||
fs.readdir(__dirname, this.callback);
|
||||
},
|
||||
'starting with the test file name should be two': function(err, files) {
|
||||
//there will always be one backup if you've specified a max log size
|
||||
var logFiles = files.filter(
|
||||
function(file) { return file.indexOf('fa-maxFileSize-sync-test.log') > -1; }
|
||||
);
|
||||
assert.equal(logFiles.length, 2);
|
||||
}
|
||||
}
|
||||
},
|
||||
'with a max file size and 2 backups': {
|
||||
topic: function() {
|
||||
var testFile = path.join(__dirname, '/fa-maxFileSize-with-backups-sync-test.log')
|
||||
, logger = log4js.getLogger('max-file-size-backups');
|
||||
remove(testFile);
|
||||
remove(testFile+'.1');
|
||||
remove(testFile+'.2');
|
||||
|
||||
//log file of 50 bytes maximum, 2 backups
|
||||
log4js.clearAppenders();
|
||||
log4js.addAppender(
|
||||
require('../lib/appenders/fileSync').appender(testFile, log4js.layouts.basicLayout, 50, 2),
|
||||
'max-file-size-backups'
|
||||
);
|
||||
logger.info("This is the first log message.");
|
||||
logger.info("This is the second log message.");
|
||||
logger.info("This is the third log message.");
|
||||
logger.info("This is the fourth log message.");
|
||||
var that = this;
|
||||
|
||||
fs.readdir(__dirname, function(err, files) {
|
||||
if (files) {
|
||||
that.callback(null, files.sort());
|
||||
} else {
|
||||
that.callback(err, files);
|
||||
}
|
||||
});
|
||||
},
|
||||
'the log files': {
|
||||
topic: function(files) {
|
||||
var logFiles = files.filter(
|
||||
function(file) { return file.indexOf('fa-maxFileSize-with-backups-sync-test.log') > -1; }
|
||||
);
|
||||
return logFiles;
|
||||
},
|
||||
'should be 3': function (files) {
|
||||
assert.equal(files.length, 3);
|
||||
},
|
||||
'should be named in sequence': function (files) {
|
||||
assert.deepEqual(files, [
|
||||
'fa-maxFileSize-with-backups-sync-test.log',
|
||||
'fa-maxFileSize-with-backups-sync-test.log.1',
|
||||
'fa-maxFileSize-with-backups-sync-test.log.2'
|
||||
]);
|
||||
},
|
||||
'and the contents of the first file': {
|
||||
topic: function(logFiles) {
|
||||
fs.readFile(path.join(__dirname, logFiles[0]), "utf8", this.callback);
|
||||
},
|
||||
'should be the last log message': function(contents) {
|
||||
assert.include(contents, 'This is the fourth log message.');
|
||||
}
|
||||
},
|
||||
'and the contents of the second file': {
|
||||
topic: function(logFiles) {
|
||||
fs.readFile(path.join(__dirname, logFiles[1]), "utf8", this.callback);
|
||||
},
|
||||
'should be the third log message': function(contents) {
|
||||
assert.include(contents, 'This is the third log message.');
|
||||
}
|
||||
},
|
||||
'and the contents of the third file': {
|
||||
topic: function(logFiles) {
|
||||
fs.readFile(path.join(__dirname, logFiles[2]), "utf8", this.callback);
|
||||
},
|
||||
'should be the second log message': function(contents) {
|
||||
assert.include(contents, 'This is the second log message.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'configure' : {
|
||||
'with fileSyncAppender': {
|
||||
topic: function() {
|
||||
var log4js = require('../lib/log4js')
|
||||
, logger;
|
||||
//this config defines one file appender (to ./tmp-sync-tests.log)
|
||||
//and sets the log level for "tests" to WARN
|
||||
log4js.configure({
|
||||
appenders: [{
|
||||
category: "tests",
|
||||
type: "file",
|
||||
filename: "tmp-sync-tests.log",
|
||||
layout: { type: "messagePassThrough" }
|
||||
}],
|
||||
|
||||
levels: { tests: "WARN" }
|
||||
});
|
||||
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('tmp-sync-tests.log', 'utf8', this.callback);
|
||||
},
|
||||
'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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
@@ -73,7 +73,7 @@ var vows = require('vows')
|
||||
console: fakeConsole
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
log4js.clearAppenders();
|
||||
log4js.addAppender(appender.configure(options || {}), category || "gelf-test");
|
||||
return {
|
||||
@@ -87,7 +87,7 @@ var vows = require('vows')
|
||||
};
|
||||
|
||||
vows.describe('log4js gelfAppender').addBatch({
|
||||
|
||||
|
||||
'with default gelfAppender settings': {
|
||||
topic: function() {
|
||||
var setup = setupLogging();
|
||||
@@ -115,12 +115,10 @@ vows.describe('log4js gelfAppender').addBatch({
|
||||
return message;
|
||||
},
|
||||
'should be in the gelf format': function(message) {
|
||||
assert.equal(message.version, '1.0');
|
||||
assert.equal(message.version, '1.1');
|
||||
assert.equal(message.host, require('os').hostname());
|
||||
assert.equal(message.level, 6); //INFO
|
||||
assert.equal(message.facility, 'nodejs-server');
|
||||
assert.equal(message.full_message, message.short_message);
|
||||
assert.equal(message.full_message, 'This is a test');
|
||||
assert.equal(message.short_message, 'This is a test');
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -166,7 +164,7 @@ vows.describe('log4js gelfAppender').addBatch({
|
||||
},
|
||||
'should pick up the options': function(message) {
|
||||
assert.equal(message.host, 'cheese');
|
||||
assert.equal(message.facility, 'nonsense');
|
||||
assert.equal(message._facility, 'nonsense');
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -246,12 +244,11 @@ vows.describe('log4js gelfAppender').addBatch({
|
||||
},
|
||||
'should pick up the options': function(message) {
|
||||
assert.equal(message.host, 'cheese');
|
||||
assert.equal(message.facility, 'nonsense');
|
||||
assert.equal(message._facility, 'nonsense');
|
||||
assert.equal(message._every1, 'Hello every one'); // the default value
|
||||
assert.equal(message._every2, 'Overwritten!'); // the overwritten value
|
||||
assert.equal(message._myField, 'This is my field!'); // the value for this message only
|
||||
assert.equal(message.short_message, 'Just testing.'); // skip the field object
|
||||
assert.equal(message.full_message, 'Just testing.'); // should be as same as short_message
|
||||
assert.equal(message.short_message, 'Just testing.'); // skip the field object
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ vows.describe('log4js global loglevel').addBatch({
|
||||
var log4js = require('../lib/log4js');
|
||||
return log4js;
|
||||
},
|
||||
|
||||
|
||||
'set global loglevel on creation': function(log4js) {
|
||||
var log1 = log4js.getLogger('log1');
|
||||
var level = 'OFF';
|
||||
@@ -16,14 +16,14 @@ vows.describe('log4js global loglevel').addBatch({
|
||||
level = 'TRACE';
|
||||
}
|
||||
assert.notEqual(log1.level.toString(), level);
|
||||
|
||||
|
||||
log4js.setGlobalLogLevel(level);
|
||||
assert.equal(log1.level.toString(), level);
|
||||
|
||||
var log2 = log4js.getLogger('log2');
|
||||
assert.equal(log2.level.toString(), level);
|
||||
},
|
||||
|
||||
|
||||
'global change loglevel': function(log4js) {
|
||||
var log1 = log4js.getLogger('log1');
|
||||
var log2 = log4js.getLogger('log2');
|
||||
@@ -32,7 +32,7 @@ vows.describe('log4js global loglevel').addBatch({
|
||||
level = 'TRACE';
|
||||
}
|
||||
assert.notEqual(log1.level.toString(), level);
|
||||
|
||||
|
||||
log4js.setGlobalLogLevel(level);
|
||||
assert.equal(log1.level.toString(), level);
|
||||
assert.equal(log2.level.toString(), level);
|
||||
@@ -46,20 +46,20 @@ vows.describe('log4js global loglevel').addBatch({
|
||||
level = 'TRACE';
|
||||
}
|
||||
assert.notEqual(log1.level.toString(), level);
|
||||
|
||||
|
||||
var oldLevel = log1.level.toString();
|
||||
assert.equal(log2.level.toString(), oldLevel);
|
||||
|
||||
|
||||
log2.setLevel(level);
|
||||
assert.equal(log1.level.toString(), oldLevel);
|
||||
assert.equal(log2.level.toString(), level);
|
||||
assert.notEqual(oldLevel, level);
|
||||
|
||||
|
||||
log2.removeLevel();
|
||||
assert.equal(log1.level.toString(), oldLevel);
|
||||
assert.equal(log2.level.toString(), oldLevel);
|
||||
},
|
||||
|
||||
|
||||
'preload loglevel': function(log4js) {
|
||||
var log1 = log4js.getLogger('log1');
|
||||
var level = 'OFF';
|
||||
@@ -67,20 +67,55 @@ vows.describe('log4js global loglevel').addBatch({
|
||||
level = 'TRACE';
|
||||
}
|
||||
assert.notEqual(log1.level.toString(), level);
|
||||
|
||||
|
||||
var oldLevel = log1.level.toString();
|
||||
log4js.getLogger('log2').setLevel(level);
|
||||
|
||||
|
||||
assert.equal(log1.level.toString(), oldLevel);
|
||||
|
||||
|
||||
// get again same logger but as different variable
|
||||
var log2 = log4js.getLogger('log2');
|
||||
assert.equal(log2.level.toString(), level);
|
||||
assert.notEqual(oldLevel, level);
|
||||
|
||||
|
||||
log2.removeLevel();
|
||||
assert.equal(log1.level.toString(), oldLevel);
|
||||
assert.equal(log2.level.toString(), oldLevel);
|
||||
},
|
||||
|
||||
'set level on all categories': function(log4js) {
|
||||
// Get 2 loggers
|
||||
var log1 = log4js.getLogger('log1');
|
||||
var log2 = log4js.getLogger('log2');
|
||||
|
||||
// First a test with 2 categories with different levels
|
||||
var config = {
|
||||
'levels': {
|
||||
'log1': 'ERROR',
|
||||
'log2': 'WARN'
|
||||
}
|
||||
};
|
||||
log4js.configure(config);
|
||||
|
||||
// Check if the levels are set correctly
|
||||
assert.equal('ERROR', log1.level.toString());
|
||||
assert.equal('WARN', log2.level.toString());
|
||||
|
||||
log1.removeLevel();
|
||||
log2.removeLevel();
|
||||
|
||||
// Almost identical test, but now we set
|
||||
// level on all categories
|
||||
var config2 = {
|
||||
'levels': {
|
||||
'[all]': 'DEBUG'
|
||||
}
|
||||
};
|
||||
log4js.configure(config2);
|
||||
|
||||
// Check if the loggers got the DEBUG level
|
||||
assert.equal('DEBUG', log1.level.toString());
|
||||
assert.equal('DEBUG', log2.level.toString());
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
|
||||
Reference in New Issue
Block a user