From 459d519058f1afdf4f6c949af2ac50ea7877e45b Mon Sep 17 00:00:00 2001 From: Kanstantsin Kamkou Date: Sat, 18 Jan 2025 13:07:09 +0100 Subject: [PATCH 1/2] Fixed manual aliasing, closes #52 --- README.md | 15 ++++++++++++--- lib/gelf-pro.js | 51 ++++++++++++++++++++++++++++++++----------------- package.json | 2 +- test/tests.js | 26 ++++++++++++++++++++++--- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 47debcb..e6381dd 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,9 @@ Sends logs to Graylog2 server in GELF (Graylog Extended Log Format) format. ## Installation ``` -"dependencies": { - "gelf-pro": "~1.4" // see the "releases" section +"dependencies": { // see the "releases" section + "gelf-pro": "~1.4" // proven by years of stable operation + "gelf-pro": "~2.0" // future-oriented and volatile } ``` @@ -160,7 +161,15 @@ log.setConfig({ Default: `{emergency: 0, alert: 1, critical: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7}` Example: `log.emergency(...)`, `log.critical(...)`, etc. -Custom example: `{alert: 0, notice: 1, ...}` +Custom example (it is **NOT POSSIBLE** to redefine a name [used by the library](lib/gelf-pro.js#L202)): +```javascript +// via config +log.setConfig({aliases: {waaagh: 'emergency', oopsie: 'alert'}}); // (!) overwrite existing +log.waaagh('Da ooman base iz got walls an'); + +// via api +log.bindAliases({waaagh: 'emergency', oopsie: 'alert'}, /*optional*/ aliasesToRemove); +``` ### Third party adapters You can force using custom adapter by setting the `adapter` right after initialisation. The [signature](lib/adapter/abstract.js) might be found here. diff --git a/lib/gelf-pro.js b/lib/gelf-pro.js index 62acf52..b8fbe7d 100644 --- a/lib/gelf-pro.js +++ b/lib/gelf-pro.js @@ -27,22 +27,24 @@ var gelf = Object.create(null, { host: '127.0.0.1', port: 12201 }, - levels: { - emergency: 0, - alert: 1, - critical: 2, - error: 3, - warning: 4, - notice: 5, - info: 6, - debug: 7 - }, aliases: { log: 'debug', warn: 'warning' } } }, + levels: { + value: { + emergency: 0, + alert: 1, + critical: 2, + error: 3, + warning: 4, + notice: 5, + info: 6, + debug: 7 + } + }, adapter: { writable: true // the adapter holder (opened on test purpose) } @@ -54,6 +56,9 @@ var gelf = Object.create(null, { * @returns {gelf} */ gelf.setConfig = function (conf) { + if (conf.aliases) { + this.bindAliases(conf.aliases, this.config.aliases); + } this.config = _.merge({}, this.config, conf); return this; }; @@ -190,16 +195,28 @@ gelf.message = function (message, lvl, extra, cb) { }); }; +// aliases to be console alike +gelf.bindAliases = function (entriesToAdd, entriesToRemove) { + var self = this; + var blacklist = _(self.levels).keys().concat([ + 'config', 'levels', 'adapter', 'getadapter', 'getstringfromobject', 'send', + 'setconfig', 'message', 'bindaliases' + ]).value(); + + _(entriesToRemove).omit(blacklist).toPairs().forEach(function (e) { + self[e[0]] && delete self[e[0]]; + }); + _(entriesToAdd).omit(blacklist).toPairs().forEach(function (e) { + Object.defineProperty(self, e[0], {enumerable: true, value: self[e[1]]}); + }); + return this; +} + // defining default functions like info(), error(), etc. -_.forEach(gelf.config.levels, function (idx, lvl) { +_.forEach(gelf.levels, function (idx, lvl) { this[lvl] = function (message, extra, cb) { this.message(message, idx, extra, cb); }; }.bind(gelf)); -// aliases to be console alike -_.forEach(gelf.config.aliases, function (from, to) { - this[to] = this[from]; -}.bind(gelf)); - -module.exports = gelf; +module.exports = gelf.bindAliases(gelf.config.aliases); diff --git a/package.json b/package.json index b6d7c6f..fe34383 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gelf-pro", - "version": "1.4.0", + "version": "2.0.0", "main": "./lib/gelf-pro.js", "typings": "./typings/index.d.ts", "author": "Kanstantsin Kamkou ", diff --git a/test/tests.js b/test/tests.js index 65994b3..3a61f62 100644 --- a/test/tests.js +++ b/test/tests.js @@ -39,12 +39,12 @@ module.exports = { }, 'Expose pre-defined levels': function () { + var gelf = _.cloneDeep(gelfOriginal); var levels = { - emergency: 0, alert: 1, critical: 2, error: 3, warning: 4, warn: 4, notice: 5, info: 6, - debug: 7, log: 7 + emergency: 0, alert: 1, critical: 2, error: 3, + warning: 4, notice: 5, info: 6, debug: 7 }; - var gelf = _.cloneDeep(gelfOriginal); sinon.spy(gelf, 'getStringFromObject'); _.forEach(levels, function (lvl, fnc) { @@ -53,6 +53,26 @@ module.exports = { }); }, + 'Modify aliases': function () { + var gelf = _.cloneDeep(gelfOriginal); + var verifyAliasExists = function (obj) { + _.forEach(obj, function (lvl, fnc) { + gelf[fnc]('test'); + JSON.parse(gelf.getStringFromObject.lastCall.returnValue).level.should.equal(lvl); + }); + } + + sinon.spy(gelf, 'getStringFromObject'); + + verifyAliasExists({log: 7, warn: 4}); + + gelf.setConfig({aliases: {waaagh: 'emergency', oopsie: 'alert'}}); + should.not.exist(gelf.log); + should.not.exist(gelf.warn); + + verifyAliasExists({waaagh: 0, oopsie: 1}); + }, + 'Manually set level': function () { var gelf = _.cloneDeep(gelfOriginal), mock = sinon.mock(gelf); From c67d4459711a1e7773ef5a1418550f7fe77643b8 Mon Sep 17 00:00:00 2001 From: Kanstantsin Kamkou Date: Sat, 18 Jan 2025 13:48:28 +0100 Subject: [PATCH 2/2] flow and test corrections --- README.md | 44 ++++++++++++++++++++++++++++---------------- lib/gelf-pro.js | 14 ++++++++------ test/tests.js | 4 ++-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e6381dd..5c589f3 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ gelf pro Sends logs to Graylog2 server in GELF (Graylog Extended Log Format) format. **Features:** -- JS object marshalling -- UDP/TCP/TLS support +- JS object marshalling. +- UDP/TCP/TLS support. - Filtering, Transforming, Broadcasting. +- Custom aliases. ![Build Status](https://github.com/kkamkou/node-gelf-pro/actions/workflows/node.js.yml/badge.svg?branch=master) ![Coverage Status](https://coveralls.io/repos/github/kkamkou/node-gelf-pro/badge.svg?branch=master) @@ -116,7 +117,7 @@ log.info( ``` ##### Filtering -Sometimes we have to discard a message which is not suitable for the current environment. It is `NOT` possible to modify the data. +Sometimes we have to discard a message which is not suitable for the current environment. It is `NOT ALLOWED` to modify the data. ```javascript log.setConfig({ filter: [ @@ -144,7 +145,7 @@ log.setConfig({ ``` ##### Broadcasting -`broadcasting` happens after `transforming`. It is `NOT` possible to modify the data. +`broadcasting` happens after `transforming`. It is `NOT ALLOWED` to modify the data. ```javascript log.setConfig({ @@ -157,18 +158,35 @@ log.setConfig({ ``` ### Levels ([1](https://httpd.apache.org/docs/current/mod/core.html#loglevel), [2](https://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/Level.html), [3](http://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels)) +> [!WARNING] +> It is `NOT ALLOWED` to modify the levels. If you need it, consider <2.0 version. + +| Level | Severity | +|-----------|-----------| +| emergency | 0 | +| alert | 1 | +| critical | 2 | +| error | 3 | +| warning | 4 | +| notice | 5 | +| info | 6 | +| debug | 7 | + +### Aliases +**Default:** `log -> debug`, `warn -> warning` + +Custom example: + +> [!WARNING] +> It is `NOT ALLOWED` to redefine a name [used by the library](lib/gelf-pro.js#L202). -Default: -`{emergency: 0, alert: 1, critical: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7}` -Example: `log.emergency(...)`, `log.critical(...)`, etc. -Custom example (it is **NOT POSSIBLE** to redefine a name [used by the library](lib/gelf-pro.js#L202)): ```javascript // via config log.setConfig({aliases: {waaagh: 'emergency', oopsie: 'alert'}}); // (!) overwrite existing log.waaagh('Da ooman base iz got walls an'); -// via api -log.bindAliases({waaagh: 'emergency', oopsie: 'alert'}, /*optional*/ aliasesToRemove); +// via api (aliasMapping: HashMap, aliasesToRemove: Set) +log.bindAliases({waaagh: 'emergency', oopsie: 'alert'}, /*optional*/ ['warn', 'log']); ``` ### Third party adapters @@ -180,12 +198,6 @@ You can force using custom adapter by setting the `adapter` right after initiali // (!) adapterName and adapterOptions will be ignored ``` -### Aliases - -Default: `{log: 'debug', warn: 'warning'}` -Example: `log.log(...) -> log.debug(...)`, `log.warn(...) -> log.warning(...)`, etc. -Custom example: `{red: 'alert', yellow: 'notice', ...}` - ### Tests #### Cli ```bash diff --git a/lib/gelf-pro.js b/lib/gelf-pro.js index b8fbe7d..651ac24 100644 --- a/lib/gelf-pro.js +++ b/lib/gelf-pro.js @@ -57,7 +57,7 @@ var gelf = Object.create(null, { */ gelf.setConfig = function (conf) { if (conf.aliases) { - this.bindAliases(conf.aliases, this.config.aliases); + this.bindAliases(conf.aliases, _.keys(this.config.aliases)); } this.config = _.merge({}, this.config, conf); return this; @@ -196,18 +196,20 @@ gelf.message = function (message, lvl, extra, cb) { }; // aliases to be console alike -gelf.bindAliases = function (entriesToAdd, entriesToRemove) { +gelf.bindAliases = function (aliasMapping, aliasesToRemove) { var self = this; var blacklist = _(self.levels).keys().concat([ 'config', 'levels', 'adapter', 'getadapter', 'getstringfromobject', 'send', 'setconfig', 'message', 'bindaliases' ]).value(); - _(entriesToRemove).omit(blacklist).toPairs().forEach(function (e) { - self[e[0]] && delete self[e[0]]; + _(aliasesToRemove).omit(blacklist).forEach(function (alias) { + self[alias] && delete self[alias]; }); - _(entriesToAdd).omit(blacklist).toPairs().forEach(function (e) { - Object.defineProperty(self, e[0], {enumerable: true, value: self[e[1]]}); + _(aliasMapping).toPairs().filter(function (p) { + return !_.includes(blacklist, p[0]); + }).forEach(function (p) { + Object.defineProperty(self, p[0], {enumerable: true, value: self[p[1]]}); }); return this; } diff --git a/test/tests.js b/test/tests.js index 3a61f62..4b27b65 100644 --- a/test/tests.js +++ b/test/tests.js @@ -66,7 +66,7 @@ module.exports = { verifyAliasExists({log: 7, warn: 4}); - gelf.setConfig({aliases: {waaagh: 'emergency', oopsie: 'alert'}}); + gelf.setConfig({aliases: {waaagh: 'emergency', oopsie: 'alert', send: 'dEBug', message: 'warning'}}); should.not.exist(gelf.log); should.not.exist(gelf.warn); @@ -125,7 +125,7 @@ module.exports = { sinon.spy(gelf, 'getStringFromObject'); gelf.info('Test message'); ("" + JSON.parse(gelf.getStringFromObject.lastCall.returnValue).timestamp) - .should.match(/^\d{10}\.\d{2,3}$/); + .should.match(/^\d{10}\.\d{1,3}$/); }, 'Normalize extra fields': function () {