8000 fix(logFaces): split logfaces into UDP+HTTP, added context to loggers · LikeABossProgrammer/log4js-node@dd20852 · GitHub
[go: up one dir, main page]

Skip to content

Commit dd20852

Browse files
author
Gareth Jones
committed
fix(logFaces): split logfaces into UDP+HTTP, added context to loggers
1 parent 2de20d5 commit dd20852

File tree

6 files changed

+291
-79
lines changed

6 files changed

+291
-79
lines changed

lib/appenders/logFacesAppender.js renamed to lib/appenders/logFaces-HTTP.js

Lines changed: 24 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,68 +14,24 @@
1414
'use strict';
1515

1616
const util = require('util');
17-
18-
const context = {};
19-
20-
function datagram(config) {
21-
const sock = require('dgram').createSocket('udp4');
22-
const host = config.remoteHost || '127.0.0.1';
23-
const port = config.port || 55201;
24-
25-
return function (event) {
26-
const buff = new Buffer(JSON.stringify(event));
27-
sock.send(buff, 0, buff.length, port, host, (err) => {
28-
if (err) {
29-
console.error('log4js.logFacesAppender failed to %s:%d, error: %s',
30-
host, port, err);
31-
}
32-
});
33-
};
34-
}
35-
36-
function servlet(config) {
37-
const axios = require('axios').create();
38-
axios.defaults.baseURL = config.url;
39-
axios.defaults.timeout = config.timeout || 5000;
40-
axios.defaults.headers = { 'Content-Type': 'application/json' };
41-
axios.defaults.withCredentials = true;
42-
43-
return function (lfsEvent) {
44-
axios.post('', lfsEvent)
45-
.then((response) => {
46-
if (response.status !== 200) {
47-
console.error('log4js.logFacesAppender post to %s failed: %d',
48-
config.url, response.status);
49-
}
50-
})
51-
.catch((response) => {
52-
console.error('log4js.logFacesAppender post to %s excepted: %s',
53-
config.url, response.status);
54-
});
55-
};
56-
}
17+
const axios = require('axios');
5718

5819
/**
59-
* For UDP (node.js) use the following configuration params:
60-
* {
61-
* "type": "logFacesAppender", // must be present for instantiation
62-
* "application": "LFS-TEST", // name of the application (domain)
63-
* "remoteHost": "127.0.0.1", // logFaces server address (hostname)
64-
* "port": 55201 // UDP receiver listening port
65-
* }
6620
*
6721
* For HTTP (browsers or node.js) use the following configuration params:
6822
* {
69-
* "type": "logFacesAppender", // must be present for instantiation
70-
* "application": "LFS-TEST", // name of the application (domain)
71-
* "url": "http://lfs-server/logs", // logFaces receiver servlet URL
72-
* }
23+
* "type": "logFaces-HTTP", // must be present for instantiation
24+
* "application": "LFS-TEST", // name of the application (domain)
25+
* "url": "http://lfs-server/logs", // logFaces receiver servlet URL
26+
* }
7327
*/
7428
function logFacesAppender(config) {
75-
let send = config.send;
76-
if (send === undefined) {
77-
send = (config.url === undefined) ? datagram(config) : servlet(config);
78-
}
29+
const sender = axios.create({
30+
baseURL: config.url,
31+
timeout: config.timeout || 5000,
32+
headers: { 'Content-Type': 'application/json' },
33+
withCredentials: true
34+
});
7935

8036
return function log(event) {
8137
// convert to logFaces compact json format
@@ -88,23 +44,29 @@ function logFacesAppender(config) {
8844
};
8945

9046
// add context variables if exist
91-
Object.keys(context).forEach((key) => {
92-
lfsEvent[`p_${key}`] = context[key];
47+
Object.keys(event.context).forEach((key) => {
48+
lfsEvent[`p_${key}`] = event.context[key];
9349
});
9450

9551
// send to server
96-
send(lfsEvent);
52+
sender.post('', lfsEvent)
53+
.then((response) => {
54+
if (response.status !== 200) {
55+
console.error('log4js.logFacesAppender post to %s failed: %d',
56+
config.url, response.status);
57+
}
58+
})
59+
.catch((response) => {
60+
console.error('log4js.logFacesAppender post to %s excepted: %s',
61+
config.url, response.status);
62+
});
9763
};
9864
}
9965

10066
function configure(config) {
10167
return logFacesAppender(config);
10268
}
10369

104-
function setContext(key, value) {
105-
context[key] = value;
106-
}
107-
10870
function format(logData) {
10971
const data = Array.isArray(logData) ?
11072
logData : Array.prototype.slice.call(arguments);
@@ -126,4 +88,3 @@ function wrapErrorsWithInspect(items) {
12688
}
12789

12890
module.exports.configure = configure;
129-
module.exports.setContext = setContext;

lib/appenders/logFaces-UDP.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* logFaces appender sends JSON formatted log events to logFaces receivers.
3+
* There are two types of receivers supported - raw UDP sockets (for server side apps),
4+
* and HTTP (for client side apps). Depending on the usage, this appender
5+
* requires either of the two:
6+
*
7+
* For UDP require 'dgram', see 'https://nodejs.org/api/dgram.html'
8+
* For HTTP require 'axios', see 'https://www.npmjs.com/package/axios'
9+
*
10+
* Make sure your project have relevant dependancy installed before using this appender.
11+
*/
12+
13+
'use strict';
14+
15+
const util = require('util');
16+
const dgram = require('dgram');
17+
18+
function datagram(config) {
19+
const sock = dgram.createSocket('udp4');
20+
const host = config.remoteHost || '127.0.0.1';
21+
const port = config.port || 55201;
22+
23+
return function (event) {
24+
const buff = new Buffer(JSON.stringify(event));
25+
sock.send(buff, 0, buff.length, port, host, (err) => {
26+
if (err) {
27+
console.error(`log4js.logFacesUDPAppender error sending to ${host}:${port}, error: `, err);
28+
}
29+
});
30+
};
31+
}
32+
33+
/**
34+
* For UDP (node.js) use the following configuration params:
35+
* {
36+
* "type": "logFaces-UDP", // must be present for instantiation
37+
* "application": "LFS-TEST", // name of the application (domain)
38+
* "r F987 emoteHost": "127.0.0.1", // logFaces server address (hostname)
39+
* "port": 55201 // UDP receiver listening port
40+
* }
41+
*
42+
*/
43+
function logFacesUDPAppender(config) {
44+
const send = datagram(config);
45+
46+
return function log(event) {
47+
// convert to logFaces compact json format
48+
const lfsEvent = {
49+
a: config.application || '', // application name
50+
t: event.startTime.getTime(), // time stamp
51+
p: event.level.levelStr, // level (priority)
52+
g: event.categoryName, // logger name
53+
m: format(event.data) // message text
54+
};
55+
56+
// add context variables if exist
57+
Object.keys(event.context).forEach((key) => {
58+
lfsEvent[`p_${key}`] = event.context[key];
59+
});
60+
61+
// send to server
62+
send(lfsEvent);
63+
};
64+
}
65+
66+
function configure(config) {
67+
return logFacesUDPAppender(config);
68+
}
69+
70+
function wrapErrorsWithInspect(items) {
71+
return items.map((item) => {
72+
if ((item instanceof Error) && item.stack) {
73+
return {
74+
inspect: function () {
75+
return `${util.format(item)}\n${item.stack}`;
76+
}
77+
};
78+
}
79+
80+
return item;
81+
});
82+
}
83+
84+
function format(logData) {
85+
const data = Array.isArray(logData) ?
86+
logData : Array.prototype.slice.call(arguments);
87+
return util.format.apply(util, wrapErrorsWithInspect(data));
88+
}
89+
90+
module.exports.configure = configure;

lib/logger.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ class LoggingEvent {
1717
* @param {Array} data objects to log
1818
* @author Seth Chisamore
1919
*/
20-
constructor(categoryName, level, data) {
20+
constructor(categoryName, level, data, context) {
2121
this.startTime = new Date();
2222
this.categoryName = categoryName;
2323
this.data = data;
2424
this.level = level;
25+
this.context = Object.assign({}, context);
2526
}
2627
}
2728

@@ -46,6 +47,7 @@ module.exports = function (levels) {
4647
this.category = name;
4748
this.level = levels.getLevel(level, levels.TRACE);
4849
this.dispatch = dispatch;
50+
this.context = {};
4951
debug(`Logger created (${name}, ${level})`);
5052
}
5153

@@ -69,9 +71,21 @@ module.exports = function (levels) {
6971

7072
_log(level, data) {
7173
debug(`sending log data (${level}, ${data}) to appenders`);
72-
const loggingEvent = new LoggingEvent(this.category, level, data);
74+
const loggingEvent = new LoggingEvent(this.category, level, data, this.context);
7375
this.dispatch(loggingEvent);
7476
}
77< 10000 /td>+
78+
addContext(key, value) {
79+
this.context[key] = value;
80+
}
81+
82+
removeContext(key) {
83+
delete this.context[key];
84+
}
85+
86+
clearContext() {
87+
this.context = {};
88+
}
7589
}
7690

7791
function addLevelMethods(target) {

test/tap/logFacesAppender-test.js renamed to test/tap/logFaces-HTTP-test.js

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,51 @@
11
'use strict';
22

33
const test = require('tap').test;
4-
const log4js = require('../../lib/log4js');
4+
const sandbox = require('sandboxed-module');
55

66
function setupLogging(category, options) {
7-
const sent = {};
7+
const fakeAxios = {
8+
args: [],
9+
create: function (config) {
10+
this.config = config;
11+
return {
12+
post: function (emptyString, event) {
13+
fakeAxios.args.push([emptyString, event]);
14+
return {
15+
catch: function (cb) {
16+
fakeAxios.errorCb = cb;
17+
}
18+
};
19+
}
20+
};
21+
}
22+
};
823

9-
function fake(event) {
10-
Object.keys(event).forEach((key) => {
11-
sent[key] = event[key];
12-
});
13-
}
24+
const fakeConsole = {
25+
error: function (msg) {
26+
this.msg = msg;
27+
}
28+
};
1429

15-
const lfsModule = require('../../lib/appenders/logFacesAppender');
16-
options.send = fake;
17-
log4js.clearAppenders();
18-
log4js.addAppender(lfsModule.configure(options), category);
19-
lfsModule.setContext('foo', 'bar');
20-
lfsModule.setContext('bar', 'foo');
30+
const log4js = sandbox.require('../../lib/log4js', {
31+
requires: {
32+
axios: fakeAxios
33+
},
34+
globals: {
35+
console: fakeConsole
36+
}
37+
});
38+
39+
options.type = 'logFaces-HTTP';
40+
log4js.configure({
41+
appenders: { http: options },
42+
categories: { default: { appenders: ['http'], level: 'trace' } }
43+
});
2144

2245
return {
2346
logger: log4js.getLogger(category),
24-
results: sent
47+
fakeAxios: fakeAxios,
48+
fakeConsole: fakeConsole
2549
};
2650
}
2751

0 commit comments

Comments
 (0)
0