feat: TCP appender - enabling a custom EndMsg token and a custom Layout

This commit is contained in:
rnd-debug 2020-04-12 19:34:06 +02:00
parent 7f540a8bb8
commit ceae893896
3 changed files with 162 additions and 33 deletions

View File

@ -7,6 +7,8 @@ The TCP appender sends log events to a master server over TCP sockets. It can be
* `type` - `tcp`
* `port` - `integer` (optional, defaults to `5000`) - the port to send to
* `host` - `string` (optional, defaults to `localhost`) - the host/IP address to send to
* `endMsg` - `string` (optional, defaults to `__LOG4JS__`) - the delimiter that marks the end of a log message
* `layout` - `object` (optional, defaults to a serialized log event) - see [layouts](layouts.md)
## Example
```javascript

View File

@ -3,15 +3,16 @@
const debug = require('debug')('log4js:tcp');
const net = require('net');
function appender(config) {
function appender(config, layout) {
let canWrite = false;
const buffer = [];
let socket;
let shutdownAttempts = 3;
let endMsg = '__LOG4JS__';
function write(loggingEvent) {
debug('Writing log event to socket');
canWrite = socket.write(`${loggingEvent.serialise()}__LOG4JS__`, 'utf8');
canWrite = socket.write(`${layout(loggingEvent)}${endMsg}`, 'utf8');
}
function emptyBuffer() {
@ -25,6 +26,7 @@ function appender(config) {
function createSocket() {
debug(`appender creating socket to ${config.host || 'localhost'}:${config.port || 5000}`);
endMsg = `${config.endMsg || '__LOG4JS__'}`;
socket = net.createConnection(config.port || 5000, config.host || 'localhost');
socket.on('connect', () => {
debug('socket connected');
@ -68,9 +70,15 @@ function appender(config) {
return log;
}
function configure(config) {
function configure(config, layouts) {
debug(`configure with config = ${config}`);
return appender(config);
let layout = function (loggingEvent) {
return loggingEvent.serialise();
};
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
return appender(config, layout);
}
module.exports.configure = configure;

View File

@ -3,39 +3,57 @@ const net = require("net");
const log4js = require("../../lib/log4js");
const LoggingEvent = require("../../lib/LoggingEvent");
const messages = [];
const server = net.createServer(socket => {
socket.setEncoding("utf8");
socket.on("data", data => {
data
.split("__LOG4JS__")
.filter(s => s.length)
.forEach(s => {
messages.push(LoggingEvent.deserialise(s));
});
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();
server.unref();
server.listen(() => {
const { port } = server.address();
log4js.configure({
appenders: {
tcp: { type: "tcp", port }
},
categories: {
default: { appenders: ["tcp"], level: "debug" }
return server;
}
test("TCP Appender", batch => {
batch.test("Default Configuration", t => {
messages = [];
const serverConfig = {
endMsg: "__LOG4JS__",
deserialise: (log) => { return LoggingEvent.deserialise(log); }
}
});
server = makeServer(serverConfig);
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(() => {
test("TCP Appender", batch => {
batch.test("should send log messages as JSON over TCP", t => {
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."],
@ -51,8 +69,109 @@ server.listen(() => {
});
t.end();
});
batch.end();
});
});
});
batch.test("Custom EndMessage String", t => {
messages = [];
const serverConfig = {
endMsg: "\n",
deserialise: (log) => { return 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) => { return JSON.parse(log); }
}
server = makeServer(serverConfig);
log4js.addLayout('json', function () {
return 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.end();
});