fix(#713): handle unexpected hangups in multiprocess appender

Handle the `'error'` event on client sockets of worker logger.
This commit is contained in:
Nico Jansen 2018-05-15 13:43:08 +02:00
parent 26d18314c1
commit 5024badbe7
4 changed files with 78 additions and 0 deletions

View File

@ -64,8 +64,21 @@ function logServer(config, actualAppender, levels) {
}
}
function handleError(error) {
const loggingEvent = {
startTime: new Date(),
categoryName: 'log4js',
level: levels.ERROR,
data: ['A worker log process hung up unexpectedly', error],
remoteAddress: clientSocket.remoteAddress,
remotePort: clientSocket.remotePort
};
actualAppender(loggingEvent);
}
clientSocket.on('data', chunkReceived);
clientSocket.on('end', chunkReceived);
clientSocket.on('error', handleError);
});
server.listen(config.loggerPort || 5000, config.loggerHost || 'localhost', function () {

View File

@ -3,6 +3,7 @@
const test = require('tap').test;
const log4js = require('../../lib/log4js');
const net = require('net');
const childProcess = require('child_process');
const sandbox = require('sandboxed-module');
test('multiprocess appender shutdown (master)', { timeout: 2000 }, (t) => {
@ -88,3 +89,48 @@ test('multiprocess appender shutdown (worker)', (t) => {
t.end();
}, 500);
});
test('multiprocess appender crash (worker)', (t) => {
const loggerPort = 12346;
const messages = [];
const fakeConsole = {
log: function (msg) {
messages.push(msg);
}
};
const log4jsWithFakeConsole = sandbox.require(
'../../lib/log4js',
{
globals: {
console: fakeConsole
}
}
);
log4jsWithFakeConsole.configure({
appenders: {
console: { type: 'console', layout: { type: 'messagePassThrough' } },
multi: {
type: 'multiprocess',
mode: 'master',
loggerPort: loggerPort,
appender: 'console'
}
},
categories: { default: { appenders: ['multi'], level: 'debug' } }
});
setTimeout(() => {
const worker = childProcess.fork(
require.resolve('./multiprocess-worker'),
['start-multiprocess-worker', loggerPort]
);
setTimeout(() => {
worker.kill();
setTimeout(() => {
t.equal(messages[0], 'Logging from worker');
log4jsWithFakeConsole.shutdown(() => t.end());
}, 250);
}, 250);
}, 250);
});

View File

@ -236,6 +236,14 @@ test('Multiprocess Appender', (batch) => {
assert.end();
});
t.test('should log the error on "error" event', (assert) => {
net.cbs.error(new Error('Expected error'));
const logEvents = recording.replay();
assert.plan(2);
assert.equal(logEvents.length, 1);
assert.equal('A worker log process hung up unexpectedly', logEvents[0].data[0]);
});
t.test('when a client connects', (assert) => {
const logString = `${JSON.stringify({
level: { level: 10000, levelStr: 'DEBUG' },

View File

@ -0,0 +1,11 @@
if (process.argv.indexOf('start-multiprocess-worker') >= 0) {
const log4js = require('../../lib/log4js');
const port = parseInt(process.argv[process.argv.length - 1], 10);
log4js.configure({
appenders: {
multi: { type: 'multiprocess', mode: 'worker', loggerPort: port }
},
categories: { default: { appenders: ['multi'], level: 'debug' } }
});
log4js.getLogger('worker').info('Logging from worker');
}