mirror of
https://github.com/log4js-node/log4js-node.git
synced 2025-12-08 19:26:01 +00:00
338 lines
9.1 KiB
JavaScript
338 lines
9.1 KiB
JavaScript
const { test } = require('tap');
|
|
const net = require('net');
|
|
const flatted = require('flatted');
|
|
const sandbox = require('@log4js-node/sandboxed-module');
|
|
const log4js = require('../../lib/log4js');
|
|
const LoggingEvent = require('../../lib/LoggingEvent');
|
|
|
|
let messages = [];
|
|
let server = null;
|
|
|
|
function makeServer(config) {
|
|
server = net.createServer((socket) => {
|
|
socket.setEncoding('utf8');
|
|
|
|
socket.on('data', (data) => {
|
|
data
|
|
.split(config.endMsg)
|
|
.filter((s) => s.length)
|
|
.forEach((s) => {
|
|
messages.push(config.deserialise(s));
|
|
});
|
|
});
|
|
});
|
|
|
|
server.unref();
|
|
|
|
return server;
|
|
}
|
|
|
|
function makeFakeNet() {
|
|
return {
|
|
data: [],
|
|
cbs: {},
|
|
createConnectionCalled: 0,
|
|
createConnection(port, host) {
|
|
const fakeNet = this;
|
|
this.port = port;
|
|
this.host = host;
|
|
this.createConnectionCalled += 1;
|
|
return {
|
|
on(evt, cb) {
|
|
fakeNet.cbs[evt] = cb;
|
|
},
|
|
write(data, encoding) {
|
|
fakeNet.data.push(data);
|
|
fakeNet.encoding = encoding;
|
|
return false;
|
|
},
|
|
end() {
|
|
fakeNet.closeCalled = true;
|
|
},
|
|
};
|
|
},
|
|
createServer(cb) {
|
|
const fakeNet = this;
|
|
cb({
|
|
remoteAddress: '1.2.3.4',
|
|
remotePort: '1234',
|
|
setEncoding(encoding) {
|
|
fakeNet.encoding = encoding;
|
|
},
|
|
on(event, cb2) {
|
|
fakeNet.cbs[event] = cb2;
|
|
},
|
|
});
|
|
|
|
return {
|
|
listen(port, host) {
|
|
fakeNet.port = port;
|
|
fakeNet.host = host;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
test('TCP Appender', (batch) => {
|
|
batch.test('Default Configuration', (t) => {
|
|
messages = [];
|
|
|
|
const serverConfig = {
|
|
endMsg: '__LOG4JS__',
|
|
deserialise: (log) => LoggingEvent.deserialise(log),
|
|
};
|
|
server = makeServer(serverConfig);
|
|
|
|
server.listen(() => {
|
|
const { port } = server.address();
|
|
log4js.configure({
|
|
appenders: {
|
|
default: { type: 'tcp', port },
|
|
},
|
|
categories: {
|
|
default: { appenders: ['default'], level: 'debug' },
|
|
},
|
|
});
|
|
|
|
const logger = log4js.getLogger();
|
|
logger.info('This should be sent via TCP.');
|
|
logger.info('This should also be sent via TCP and not break things.');
|
|
|
|
log4js.shutdown(() => {
|
|
server.close(() => {
|
|
t.equal(messages.length, 2);
|
|
t.match(messages[0], {
|
|
data: ['This should be sent via TCP.'],
|
|
categoryName: 'default',
|
|
context: {},
|
|
level: { levelStr: 'INFO' },
|
|
});
|
|
t.match(messages[1], {
|
|
data: ['This should also be sent via TCP and not break things.'],
|
|
categoryName: 'default',
|
|
context: {},
|
|
level: { levelStr: 'INFO' },
|
|
});
|
|
t.end();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
batch.test('Custom EndMessage String', (t) => {
|
|
messages = [];
|
|
|
|
const serverConfig = {
|
|
endMsg: '\n',
|
|
deserialise: (log) => LoggingEvent.deserialise(log),
|
|
};
|
|
server = makeServer(serverConfig);
|
|
|
|
server.listen(() => {
|
|
const { port } = server.address();
|
|
log4js.configure({
|
|
appenders: {
|
|
customEndMsg: { type: 'tcp', port, endMsg: '\n' },
|
|
},
|
|
categories: {
|
|
default: { appenders: ['customEndMsg'], level: 'debug' },
|
|
},
|
|
});
|
|
|
|
const logger = log4js.getLogger();
|
|
logger.info('This should be sent via TCP using a custom EndMsg string.');
|
|
logger.info(
|
|
'This should also be sent via TCP using a custom EndMsg string and not break things.'
|
|
);
|
|
|
|
log4js.shutdown(() => {
|
|
server.close(() => {
|
|
t.equal(messages.length, 2);
|
|
t.match(messages[0], {
|
|
data: ['This should be sent via TCP using a custom EndMsg string.'],
|
|
categoryName: 'default',
|
|
context: {},
|
|
level: { levelStr: 'INFO' },
|
|
});
|
|
t.match(messages[1], {
|
|
data: [
|
|
'This should also be sent via TCP using a custom EndMsg string and not break things.',
|
|
],
|
|
categoryName: 'default',
|
|
context: {},
|
|
level: { levelStr: 'INFO' },
|
|
});
|
|
t.end();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
batch.test('Custom Layout', (t) => {
|
|
messages = [];
|
|
|
|
const serverConfig = {
|
|
endMsg: '__LOG4JS__',
|
|
deserialise: (log) => JSON.parse(log),
|
|
};
|
|
server = makeServer(serverConfig);
|
|
|
|
log4js.addLayout(
|
|
'json',
|
|
() =>
|
|
function (logEvent) {
|
|
return JSON.stringify({
|
|
time: logEvent.startTime,
|
|
message: logEvent.data[0],
|
|
level: logEvent.level.toString(),
|
|
});
|
|
}
|
|
);
|
|
|
|
server.listen(() => {
|
|
const { port } = server.address();
|
|
log4js.configure({
|
|
appenders: {
|
|
customLayout: {
|
|
type: 'tcp',
|
|
port,
|
|
layout: { type: 'json' },
|
|
},
|
|
},
|
|
categories: {
|
|
default: { appenders: ['customLayout'], level: 'debug' },
|
|
},
|
|
});
|
|
|
|
const logger = log4js.getLogger();
|
|
logger.info('This should be sent as a customized json.');
|
|
logger.info(
|
|
'This should also be sent via TCP as a customized json and not break things.'
|
|
);
|
|
|
|
log4js.shutdown(() => {
|
|
server.close(() => {
|
|
t.equal(messages.length, 2);
|
|
t.match(messages[0], {
|
|
message: 'This should be sent as a customized json.',
|
|
level: 'INFO',
|
|
});
|
|
t.match(messages[1], {
|
|
message:
|
|
'This should also be sent via TCP as a customized json and not break things.',
|
|
level: 'INFO',
|
|
});
|
|
t.end();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
batch.test('when underlying stream errors', (t) => {
|
|
const fakeNet = makeFakeNet();
|
|
|
|
const sandboxedLog4js = sandbox.require('../../lib/log4js', {
|
|
requires: {
|
|
net: fakeNet,
|
|
},
|
|
});
|
|
sandboxedLog4js.configure({
|
|
appenders: {
|
|
default: { type: 'tcp' },
|
|
},
|
|
categories: {
|
|
default: { appenders: ['default'], level: 'debug' },
|
|
},
|
|
});
|
|
|
|
const logger = sandboxedLog4js.getLogger();
|
|
|
|
logger.info('before connect');
|
|
t.test(
|
|
'should buffer messages written before socket is connected',
|
|
(assert) => {
|
|
assert.equal(fakeNet.data.length, 0);
|
|
assert.equal(fakeNet.createConnectionCalled, 1);
|
|
assert.end();
|
|
}
|
|
);
|
|
|
|
fakeNet.cbs.connect();
|
|
t.test('should flush buffered messages', (assert) => {
|
|
assert.equal(fakeNet.data.length, 1);
|
|
assert.equal(fakeNet.createConnectionCalled, 1);
|
|
assert.match(fakeNet.data[0], 'before connect');
|
|
assert.end();
|
|
});
|
|
|
|
logger.info('after connect');
|
|
t.test(
|
|
'should write log messages to socket as flatted strings with a terminator string',
|
|
(assert) => {
|
|
assert.equal(fakeNet.data.length, 2);
|
|
assert.match(fakeNet.data[0], 'before connect');
|
|
assert.ok(fakeNet.data[0].endsWith('__LOG4JS__'));
|
|
assert.match(fakeNet.data[1], 'after connect');
|
|
assert.ok(fakeNet.data[1].endsWith('__LOG4JS__'));
|
|
assert.equal(fakeNet.encoding, 'utf8');
|
|
assert.end();
|
|
}
|
|
);
|
|
|
|
fakeNet.cbs.error();
|
|
logger.info('after error, before close');
|
|
fakeNet.cbs.close();
|
|
logger.info('after close, before connect');
|
|
fakeNet.cbs.connect();
|
|
logger.info('after error, after connect');
|
|
t.test('should attempt to re-open the socket on error', (assert) => {
|
|
assert.equal(fakeNet.data.length, 5);
|
|
assert.equal(fakeNet.createConnectionCalled, 2);
|
|
assert.match(fakeNet.data[2], 'after error, before close');
|
|
assert.match(fakeNet.data[3], 'after close, before connect');
|
|
assert.match(fakeNet.data[4], 'after error, after connect');
|
|
assert.end();
|
|
});
|
|
|
|
t.test('should buffer messages until drain', (assert) => {
|
|
const previousLength = fakeNet.data.length;
|
|
logger.info('should not be flushed');
|
|
assert.equal(fakeNet.data.length, previousLength);
|
|
assert.notMatch(
|
|
fakeNet.data[fakeNet.data.length - 1],
|
|
'should not be flushed'
|
|
);
|
|
|
|
fakeNet.cbs.drain();
|
|
assert.equal(fakeNet.data.length, previousLength + 1);
|
|
assert.match(
|
|
fakeNet.data[fakeNet.data.length - 1],
|
|
'should not be flushed'
|
|
);
|
|
assert.end();
|
|
});
|
|
|
|
t.test('should serialize an Error correctly', (assert) => {
|
|
const previousLength = fakeNet.data.length;
|
|
logger.error(new Error('Error test'));
|
|
fakeNet.cbs.drain();
|
|
assert.equal(fakeNet.data.length, previousLength + 1);
|
|
const raw = fakeNet.data[fakeNet.data.length - 1];
|
|
const offset = raw.indexOf('__LOG4JS__');
|
|
assert.ok(
|
|
flatted.parse(raw.slice(0, offset !== -1 ? offset : 0)).data[0].stack,
|
|
`Expected:\n\n${fakeNet.data[6]}\n\n to have a 'data[0].stack' property`
|
|
);
|
|
const actual = flatted.parse(raw.slice(0, offset !== -1 ? offset : 0))
|
|
.data[0].stack;
|
|
assert.match(actual, /^Error: Error test/);
|
|
assert.end();
|
|
});
|
|
|
|
t.end();
|
|
});
|
|
|
|
batch.end();
|
|
});
|