From 84ab47d6e5e02ac81958ec0dd5a662cf202ed9e1 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Tue, 18 Jul 2017 22:42:06 +1000 Subject: [PATCH] feat(pm2): got pm2 working, needs tests --- lib/configuration.js | 5 ++++- lib/log4js.js | 41 +++++++++++++++++++++++------------- test/tap/pm2-support-test.js | 10 +++++++++ 3 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 test/tap/pm2-support-test.js diff --git a/lib/configuration.js b/lib/configuration.js index 71cb484..2339117 100644 --- a/lib/configuration.js +++ b/lib/configuration.js @@ -76,7 +76,7 @@ class Configuration { debug(`DEPRECATION: Appender ${config.type} exports a shutdown function.`); } - if (cluster.isMaster) { + if (cluster.isMaster || (this.pm2 && process.env[this.pm2InstanceVar] === '0')) { return appenderModule.configure( config, layouts, @@ -195,6 +195,9 @@ class Configuration { this.throwExceptionIf(not(anObject(candidate.appenders)), 'must have a property "appenders" of type object.'); this.throwExceptionIf(not(anObject(candidate.categories)), 'must have a property "categories" of type object.'); + this.pm2 = this.candidate.pm2; + this.pm2InstanceVar = this.candidate.pm2InstanceVar || 'NODE_APP_INSTANCE'; + this.levels = candidate.levels; this.appenders = candidate.appenders; this.categories = candidate.categories; diff --git a/lib/log4js.js b/lib/log4js.js index 91b147e..2184863 100644 --- a/lib/log4js.js +++ b/lib/log4js.js @@ -139,7 +139,7 @@ function sendLogEventToAppender(logEvent) { function workerDispatch(logEvent) { debug(`sending message to master from worker ${process.pid}`); - process.send({ type: '::log4js-message', event: serialise(logEvent) }); + process.send({ topic: 'log4js:message', data: serialise(logEvent) }); } /** @@ -162,6 +162,21 @@ function loadConfigurationFile(filename) { return filename; } +// in a multi-process node environment, worker loggers will use +// process.send +const receiver = (worker, message) => { + // prior to node v6, the worker parameter was not passed (args were message, handle) + debug('cluster message received from worker ', worker, ': ', message); + if (worker.topic && worker.data) { + message = worker; + worker = undefined; + } + if (message && message.topic && message.topic === 'log4js:message') { + debug('received message: ', message.data); + sendLogEventToAppender(deserialise(message.data)); + } +}; + function configure(configurationFileOrObject) { let configObject = configurationFileOrObject; @@ -175,6 +190,15 @@ function configure(configurationFileOrObject) { Logger = loggerModule.Logger; LoggingEvent = loggerModule.LoggingEvent; module.exports.connectLogger = connectModule(config.levels).connectLogger; + + // PM2 cluster support + // PM2 runs everything as workers - install pm2-intercom for this to work. + // we only want one of the app instances to write logs + if (config.pm2 && process.env[config.pm2InstanceVar] === '0') { + debug('listening for PM2 broadcast messages'); + process.on('message', receiver); + } + enabled = true; } @@ -236,20 +260,7 @@ const log4js = { module.exports = log4js; -// in a multi-process node environment, worker loggers will use -// process.send -cluster.on('message', (worker, message) => { - // prior to node v6, the worker parameter was not passed (args were message, handle) - debug('cluster message received from worker ', worker, ': ', message); - if (worker.type && worker.event) { - message = worker; - worker = undefined; - } - if (message && message.type && message.type === '::log4js-message') { - debug('received message: ', message.event); - sendLogEventToAppender(deserialise(message.event)); - } -}); +cluster.on('message', receiver); // set ourselves up configure(process.env.LOG4JS_CONFIG || defaultConfig); diff --git a/test/tap/pm2-support-test.js b/test/tap/pm2-support-test.js new file mode 100644 index 0000000..863fd74 --- /dev/null +++ b/test/tap/pm2-support-test.js @@ -0,0 +1,10 @@ +'use strict'; + +const test = require('tap').test; + +test('PM2 Cluster support', (batch) => { + batch.test('should listen for messages if pm2 support enabled'); + batch.test('should write messages on NODE_APP_INSTANCE - 0'); + batch.test('should send messages with the correct format'); + batch.end(); +});