Compare commits

...

21 Commits

Author SHA1 Message Date
Gareth Jones
cd2ee14bde 0.6.11 2014-03-05 09:25:03 +11:00
Gareth Jones
c09c11b147 Merge branch 'master' of https://github.com/nomiddlename/log4js-node 2014-03-05 09:24:09 +11:00
Gareth Jones
b74a514369 Merge pull request #186 from jci-fox/issue184_dynamicloglevels
Adding level checks on dynamic logging
2014-03-05 09:17:16 +11:00
jci-fox
73344ba79f fixing unit test
logger.log requires 2 params, and with the 1st being level and filtering the level, the log call must provide a level that will result in log messages
2014-03-04 09:27:04 -06:00
jci-fox
22c156582f Adding level checks on dynamic logging
using levels.toLevel and this.isLevelEnabled prior to emiting the event will prevent the appenders from being notified if the log level provided is below the loggers level.
2014-03-04 09:08:27 -06:00
Gareth Jones
72bfb5d980 0.6.10 2014-02-11 08:51:21 +11:00
Gareth Jones
83ad0babf3 changed my email address 2014-02-11 08:50:36 +11:00
Gareth Jones
94034e1226 Merge pull request #172 from devotis/master
Fork with Loggly appender here
2014-01-16 14:00:16 -08:00
Christiaan Westerbeek
9b4c7d1574 Fixes the error with test/logglyAppender-test
Refs #172

I will add more relevant tests later
2014-01-16 16:39:45 +01:00
Christiaan Westerbeek
770f2da627 Cleanup 2014-01-10 21:59:39 +01:00
Christiaan Westerbeek
eb51aa99be First working version
tried examples/loggly-appender.js [OK]
2014-01-10 21:51:08 +01:00
Christiaan Westerbeek
5286c50375 Added the basic files for Loggly appender
appender, example, test
not tested yet!
2014-01-10 21:18:16 +01:00
Christiaan Westerbeek
bb644a1632 Update README.md
Will try to add a appender for Loggly in this Fork. I will keep it in to this feature alone as outlined in the rules
2014-01-10 20:47:48 +01:00
Gareth Jones
a6efbf6273 Merge pull request #168 from macedigital/connectlogger-ip-fix
fix 'remote-addr' property in connect-logger
2013-12-30 12:40:40 -08:00
Matthias Adler
2118d8f7b3 fix 'remote-addr' property in connect-logger 2013-12-21 19:42:44 +01:00
Gareth Jones
d2f044a451 0.6.9 2013-09-30 08:48:15 +10:00
Gareth Jones
d0661322aa Merge pull request #158 from emilecantin/master
Added logic to serialize Error objects correctly
2013-09-29 15:36:40 -07:00
Emile Cantin
8b8844694f Fixed unit tests, now with regexes. 2013-09-27 09:45:10 -04:00
Emile Cantin
abdba8e56f Added logic to serialize Error objects correctly
This should fix #97.
2013-09-26 14:55:20 -04:00
Gareth Jones
093f693232 Merge pull request #157 from karlvlam/gelf-timefix
GELF time precision should be millisecond level
2013-09-17 14:04:49 -07:00
Karl Lam
b9bba00d8c GELF time precision should be millisecond level 2013-09-16 18:31:23 +08:00
12 changed files with 186 additions and 9 deletions

View File

@@ -12,6 +12,7 @@ Out of the box it supports the following features:
* SMTP appender
* GELF appender
* hook.io appender
* Loggly appender
* multiprocess appender (useful when you've got worker processes)
* a logger for connect/express servers
* configurable log message layout/patterns

View File

@@ -0,0 +1,24 @@
//Note that loggly appender needs node-loggly to work.
//If you haven't got node-loggly installed, you'll get cryptic
//"cannot find module" errors when using the loggly appender
var log4js = require('../lib/log4js');
log4js.configure({
"appenders": [
{
type: "console",
category: "test"
},
{
"type" : "loggly",
"token" : "12345678901234567890",
"subdomain": "your-subdomain",
"tags" : ["test"],
"category" : "loggly"
}
]
});
var logger = log4js.getLogger("loggly");
logger.info("Test log message");
//logger.debug("Test log message");

View File

@@ -7,6 +7,14 @@ var log4js = require('../log4js');
* Takes a loggingEvent object, returns string representation of it.
*/
function serializeLoggingEvent(loggingEvent) {
// JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
// The following allows us to serialize errors correctly.
for (var i = 0; i < loggingEvent.data.length; i++) {
var item = loggingEvent.data[i];
if (item && item.stack && JSON.stringify(item) === '{}') { // Validate that we really are in this case
loggingEvent.data[i] = {stack : item.stack};
}
}
return JSON.stringify(loggingEvent);
}
@@ -115,4 +123,4 @@ function configure(config, options) {
}
exports.appender = createAppender;
exports.configure = configure;
exports.configure = configure;

View File

@@ -100,7 +100,7 @@ function gelfAppender (layout, host, port, hostname, facility) {
msg.short_message = msg.full_message;
msg.version="1.0";
msg.timestamp = msg.timestamp || new Date().getTime() / 1000 >> 0;
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;

37
lib/appenders/loggly.js Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
var layouts = require("../layouts")
, loggly = require("loggly")
, os = require('os');
/**
* Loggly Appender. Sends logging events to Loggly using node-loggly
*
* @param config object with loggly configuration data
* {
* token: 'your-really-long-input-token',
* 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).
*/
function logglyAppender(config, layout) {
layout = layout || layouts.basicLayout;
var client = loggly.createClient(config);
return function(loggingEvent) {
client.log(layout(loggingEvent), config.tags);
};
}
function configure(config) {
var layout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return logglyAppender(config, layout);
}
exports.name = "loggly";
exports.appender = logglyAppender;
exports.configure = configure;

View File

@@ -94,6 +94,11 @@ function workerAppender(config) {
}
function write(loggingEvent) {
// JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
// The following allows us to serialize errors correctly.
if (loggingEvent && loggingEvent.stack && JSON.stringify(loggingEvent) === '{}') { // Validate that we really are in this case
loggingEvent = {stack : loggingEvent.stack};
}
socket.write(JSON.stringify(loggingEvent), 'utf8');
socket.write(END_MSG, 'utf8');
}

View File

@@ -120,10 +120,10 @@ function format(str, req, res) {
.replace(':referrer', req.headers.referer || req.headers.referrer || '')
.replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor)
.replace(
':remote-addr',
':remote-addr', req.ip || req._remoteAddress || (
req.socket &&
(req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress))
)
))
.replace(':user-agent', req.headers['user-agent'] || '')
.replace(
':content-length',

View File

@@ -49,9 +49,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) {

View File

@@ -1,6 +1,6 @@
{
"name": "log4js",
"version": "0.6.8",
"version": "0.6.11",
"description": "Port of Log4js to work with node.",
"keywords": [
"logging",
@@ -9,7 +9,7 @@
"node"
],
"main": "./lib/log4js",
"author": "Gareth Jones <gareth.jones@sensis.com.au>",
"author": "Gareth Jones <gareth.nomiddlename@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/nomiddlename/log4js-node.git"

View File

@@ -97,6 +97,7 @@ vows.describe('log4js cluster appender').addBatch({
// Actual test - log message using masterAppender
workerAppender(new LoggingEvent('wovs', 'Info', ['workerAppender test']));
workerAppender(new LoggingEvent('wovs', 'Info', [new Error('Error test')]));
var returnValue = {
registeredProcessEvents: registeredProcessEvents,
@@ -109,6 +110,14 @@ vows.describe('log4js cluster appender').addBatch({
"worker appender should call process.send" : function(topic) {
assert.equal(topic.registeredProcessEvents[0].type, '::log-message');
assert.equal(JSON.parse(topic.registeredProcessEvents[0].event).data[0], "workerAppender test");
},
"worker should serialize an Error correctly" : function(topic) {
assert.equal(topic.registeredProcessEvents[1].type, '::log-message');
assert(JSON.parse(topic.registeredProcessEvents[1].event).data[0].stack);
var actual = JSON.parse(topic.registeredProcessEvents[1].event).data[0].stack;
var expectedRegex = /^Error: Error test/;
assert(actual.match(expectedRegex), "Expected: \n\n " + actual + "\n\n to match " + expectedRegex);
}
}

View File

@@ -0,0 +1,82 @@
"use strict";
var vows = require('vows')
, assert = require('assert')
, log4js = require('../lib/log4js')
, sandbox = require('sandboxed-module')
;
function setupLogging(category, options) {
var msgs = [];
var fakeLoggly = {
createClient: function (options) {
return {
config: options,
log: function (msg, tags) {
msgs.push({
msg: msg,
tags: tags
});
}
};
}
};
var fakeLayouts = {
layout: function(type, config) {
this.type = type;
this.config = config;
return log4js.layouts.messagePassThroughLayout;
},
basicLayout: log4js.layouts.basicLayout,
messagePassThroughLayout: log4js.layouts.messagePassThroughLayout
};
var fakeConsole = {
errors: [],
error: function(msg, value) {
this.errors.push({ msg: msg, value: value });
}
};
var logglyModule = sandbox.require('../lib/appenders/loggly', {
requires: {
'loggly': fakeLoggly,
'../layouts': fakeLayouts
},
globals: {
console: fakeConsole
}
});
log4js.addAppender(logglyModule.configure(options), category);
return {
logger: log4js.getLogger(category),
loggly: fakeLoggly,
layouts: fakeLayouts,
console: fakeConsole,
results: msgs
};
}
log4js.clearAppenders();
vows.describe('log4js logglyAppender').addBatch({
'minimal config': {
topic: function() {
var setup = setupLogging('loggly', {
token: 'your-really-long-input-token',
subdomain: 'your-subdomain',
tags: ['loggly-tag1', 'loggly-tag2', 'loggly-tagn']
});
setup.logger.log('trace', 'Log event #1');
return setup;
},
'there should be one message only': function (topic) {
//console.log('topic', topic);
assert.equal(topic.results.length, 1);
}
}
}).export(module);

View File

@@ -75,6 +75,7 @@ vows.describe('Multiprocess Appender').addBatch({
appender('after error, before connect');
fakeNet.cbs.connect();
appender('after error, after connect');
appender(new Error('Error test'));
return fakeNet;
},
@@ -98,6 +99,13 @@ vows.describe('Multiprocess Appender').addBatch({
assert.equal(net.data[6], JSON.stringify('after error, after connect'));
assert.equal(net.data[7], '__LOG4JS__');
assert.equal(net.createConnectionCalled, 2);
},
'should serialize an Error correctly': function(net) {
assert(JSON.parse(net.data[8]).stack, "Expected:\n\n" + net.data[8] + "\n\n to have a 'stack' property");
var actual = JSON.parse(net.data[8]).stack;
var expectedRegex = /^Error: Error test/;
assert(actual.match(expectedRegex), "Expected: \n\n " + actual + "\n\n to match " + expectedRegex);
}
},
'worker with timeout': {