Compare commits

...

22 Commits

Author SHA1 Message Date
Gareth Jones
a703f2dc12 0.6.15 2014-07-03 08:16:07 +10:00
Gareth Jones
b2edbb1146 Merge pull request #175 from devotis/master
Loggly appender should not make use of any layout
2014-06-28 08:22:20 +10:00
Gareth Jones
99e7c0981d Merge pull request #189 from jengler/add-support-for-prerequired-appender-styles
Add support for prerequired appender styles
2014-06-28 08:20:12 +10:00
Gareth Jones
06bab894af Merge pull request #203 from idalv/master
Clusterred appender should consider the categories.
2014-06-28 08:17:16 +10:00
Gareth Jones
101739ebef Merge pull request #209 from Icehunter/patch-1
Update for "write after end" uncaught error.
2014-06-28 08:02:27 +10:00
Ryan Wilson
f8ffccffd5 epic day with a forgotten console 2014-06-20 13:23:57 -07:00
Ryan Wilson
7d50b4aeff removed check for writeable
caused broken unit tests
2014-06-20 13:23:09 -07:00
Ryan Wilson
b12200fabc Update for "write after end" uncaught error. 2014-06-20 13:16:23 -07:00
Vladimir Mitev
f8b6cc7c39 Revert "Update connect-logger.js to work correctly with express"
This reverts commit d18fb466fb.
2014-05-26 15:56:23 +03:00
idalv
6314e4a344 Merge pull request #1 from idalv/automation
Update connect-logger.js to work correctly with express
2014-05-26 15:46:07 +03:00
mishless
d18fb466fb Update connect-logger.js to work correctly with express
When used with express levels are wrong since send() does not call writeHead, but sets responseCode on response.
2014-05-23 13:58:52 +03:00
Vladimir Mitev
e638ff7271 Unit test.
Fixed the old unit tests.
Added validation for new functionality.

Signed-off-by: Vladimir Mitev <idalv@users.noreply.github.com>
2014-05-20 14:42:29 +03:00
Vladimir Mitev
2daf29b400 Clusterred appender should consider the categories.
It turns out that whenever the clusterred appender is used the log event is passed to all actual appenders.
The actual appender's category is ignored.

Signed-off-by: Vladimir Mitev <idalv@users.noreply.github.com>
2014-05-20 13:45:46 +03:00
Gareth Jones
ca5272aacc 0.6.14 2014-04-22 10:06:04 +10:00
Gareth Jones
614127bb10 added shutdown to datefile 2014-04-22 10:05:37 +10:00
Gareth Jones
a549df44b4 Merge pull request #199 from lulurun/fix_file_appender
fix shutdown method: make sure to callback when write completed immediat...
2014-04-22 09:58:03 +10:00
Gareth Jones
5e0982f0b1 Merge pull request #200 from lulurun/datefile_appender_fix
file won't get rolled if the process restarted daily
2014-04-22 09:29:15 +10:00
Xiaolu Liu
f5a76d9073 file won't get rolled if the process restarted daily 2014-04-24 00:07:11 +09:00
Xiaolu Liu
29d941f0a6 fix shutdown method: make sure to callback when write completed immediately 2014-04-21 16:27:51 +09:00
John Engler
c569919160 Simplied loadAppender logic. 2014-03-11 02:19:00 -07:00
John Engler
28f7c87a0e Allow adding of appenders as objects
Previously, appenders could only be added by specifying the filepath
to the appender. This required the appender's path to be specified
either relative to the log4js installation, relative to a NODE_PATH
token, or absolute. This creates a coupling between the log4js
configurer and the log4js installation location, or a coupling between
the log4js configurer and the global NODE_PATH. This commit removes
the coupling by allowing the loading of appenders to be done relative
to the log4js configurer.
2014-03-11 02:07:58 -07:00
Christiaan Westerbeek
ae1a55fed9 Stop making use of any layout
Stop making use of any layout by default, because they are intended to
format a line for human reading. Loggly indexes the values (of all
properties of objects) and makes them available for querying.
2014-01-21 12:11:32 +01:00
10 changed files with 146 additions and 20 deletions

View File

@@ -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);
}
}
}
}

View File

@@ -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;

View File

@@ -85,6 +85,8 @@ function shutdown(cb) {
file.once('drain', function() {
file.end(done);
});
} else {
file.end(done);
}
}, cb);
}

View File

@@ -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;

View File

@@ -298,13 +298,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);

View File

@@ -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");

View File

@@ -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;

View File

@@ -1,6 +1,6 @@
{
"name": "log4js",
"version": "0.6.13",
"version": "0.6.15",
"description": "Port of Log4js to work with node.",
"keywords": [
"logging",

View File

@@ -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');
},
},

View File

@@ -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';