From be754f0c0e1ff1c6dc0526d6ba212278dafad0ef Mon Sep 17 00:00:00 2001 From: Karl Lam Date: Fri, 5 Jul 2013 10:54:31 +0800 Subject: [PATCH 1/3] GELF appender can add custom fields --- lib/appenders/gelf.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/appenders/gelf.js b/lib/appenders/gelf.js index 4599856..e3e2f5c 100644 --- a/lib/appenders/gelf.js +++ b/lib/appenders/gelf.js @@ -47,9 +47,33 @@ function gelfAppender (layout, host, port, hostname, facility) { process.on('exit', function() { if (client) client.close(); }); - + + /** + * Add custom fields (start with underscore ) + * - if the first object passed to the logger contains 'GELF' field, add copy the underscore fields to the message + * @param loggingEvent + * @param msg + */ + function addCustomFields(loggingEvent, msg){ + var data = loggingEvent.data; + if (!Array.isArray(data) || data.length === 0) return; + var firstData = data[0]; + if (!firstData['GELF']) return; // identify with GELF field defined + var keys = Object.keys(firstData); + for (var i in keys){ + var key = keys[i]; + // skip _id field for graylog2, skip keys not starts with UNDERSCORE + if (!key.match(/^_/) || key === "_id") continue; + msg[key] = firstData[key]; + } + loggingEvent.data.shift(); // remove the first object + //console.log('=== msg ==='); + //console.log(msg); + } + function preparePacket(loggingEvent) { var msg = {}; + addCustomFields(loggingEvent, msg); msg.full_message = layout(loggingEvent); msg.short_message = msg.full_message; From 837d007de332c90a48e49adc8b19af6eeec4981c Mon Sep 17 00:00:00 2001 From: Karl Lam Date: Fri, 5 Jul 2013 11:23:59 +0800 Subject: [PATCH 2/3] GELF appender can add customFields to config for every message --- lib/appenders/gelf.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/appenders/gelf.js b/lib/appenders/gelf.js index e3e2f5c..d8f264d 100644 --- a/lib/appenders/gelf.js +++ b/lib/appenders/gelf.js @@ -34,13 +34,16 @@ levelMapping[levels.FATAL] = LOG_CRIT; * @param hostname - hostname of the current host (default:os hostname) * @param facility - facility to log to (default:nodejs-server) */ -function gelfAppender (layout, host, port, hostname, facility) { +function gelfAppender (layout, host, port, hostname, facility, customFields) { host = host || 'localhost'; port = port || 12201; hostname = hostname || require('os').hostname(); facility = facility || 'nodejs-server'; layout = layout || layouts.messagePassThroughLayout; + + var defaultCustomFields = customFields || {}; + console.log(defaultCustomFields) var client = dgram.createSocket("udp4"); @@ -55,9 +58,22 @@ function gelfAppender (layout, host, port, hostname, facility) { * @param msg */ function addCustomFields(loggingEvent, msg){ + + /* append defaultCustomFields firsts */ + var keys = Object.keys(defaultCustomFields); + for (var i in keys){ + var key = keys[i]; + // skip _id field for graylog2, skip keys not starts with UNDERSCORE + if (!key.match(/^_/) || key === "_id") continue; + msg[key] = defaultCustomFields[key]; + } + + + /* append custom fields per message */ var data = loggingEvent.data; if (!Array.isArray(data) || data.length === 0) return; var firstData = data[0]; + if (!firstData['GELF']) return; // identify with GELF field defined var keys = Object.keys(firstData); for (var i in keys){ @@ -66,9 +82,9 @@ function gelfAppender (layout, host, port, hostname, facility) { if (!key.match(/^_/) || key === "_id") continue; msg[key] = firstData[key]; } - loggingEvent.data.shift(); // remove the first object - //console.log('=== msg ==='); - //console.log(msg); + + /* the custom field object should be removed, so it will not be looged by the later appenders */ + loggingEvent.data.shift(); } function preparePacket(loggingEvent) { @@ -112,7 +128,7 @@ function configure(config) { if (config.layout) { layout = layouts.layout(config.layout.type, config.layout); } - return gelfAppender(layout, config.host, config.port, config.hostname, config.facility); + return gelfAppender(layout, config.host, config.port, config.hostname, config.facility, config.customFields); } exports.appender = gelfAppender; From baaebef2eda55e8b15525bee24978a12472d413c Mon Sep 17 00:00:00 2001 From: Karl Lam Date: Fri, 5 Jul 2013 15:28:10 +0800 Subject: [PATCH 3/3] GELF appender - test case covers custom fields, remove unused console.log --- lib/appenders/gelf.js | 1 - test/gelfAppender-test.js | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/appenders/gelf.js b/lib/appenders/gelf.js index d8f264d..0a731db 100644 --- a/lib/appenders/gelf.js +++ b/lib/appenders/gelf.js @@ -43,7 +43,6 @@ function gelfAppender (layout, host, port, hostname, facility, customFields) { layout = layout || layouts.messagePassThroughLayout; var defaultCustomFields = customFields || {}; - console.log(defaultCustomFields) var client = dgram.createSocket("udp4"); diff --git a/test/gelfAppender-test.js b/test/gelfAppender-test.js index 1f45f33..7a0541b 100644 --- a/test/gelfAppender-test.js +++ b/test/gelfAppender-test.js @@ -135,5 +135,51 @@ vows.describe('log4js gelfAppender').addBatch({ assert.equal(message.facility, 'nonsense'); } } + }, + 'with custom fields options': { + topic: function() { + var setup = setupLogging({ + host: 'somewhere', + port: 12345, + hostname: 'cheese', + facility: 'nonsense', + customFields: { + _every1: 'Hello every one', + _every2: 'Hello every two' + } + }); + var myFields = { + GELF: true, + _every2: 'Overwritten!', + _myField: 'This is my field!' + }; + setup.logger.debug(myFields, "Just testing."); + return setup; + }, + 'the dgram packet': { + topic: function(setup) { + return setup.dgram; + }, + 'should pick up the options': function(dgram) { + assert.equal(dgram.socket.host, 'somewhere'); + assert.equal(dgram.socket.port, 12345); + } + }, + 'the uncompressed packet': { + topic: function(setup) { + var message = JSON.parse(setup.compress.uncompressed); + return message; + }, + 'should pick up the options': function(message) { + assert.equal(message.host, 'cheese'); + 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 + } + } } + }).export(module);