Skip to content

Commit 5283782

Browse files
author
Gareth Jones
committed
refactor(all): basic logging to stdout works again
- removed config reloading - removed console replacement - added recording appender - added config validation - changed config format
1 parent db90ea6 commit 5283782

12 files changed

Lines changed: 582 additions & 1420 deletions

lib/appenders/recording.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
let recordedEvents = [];
4+
5+
function configure() {
6+
return function (logEvent) {
7+
recordedEvents.push(logEvent);
8+
};
9+
}
10+
11+
function replay() {
12+
return recordedEvents;
13+
}
14+
15+
function reset() {
16+
recordedEvents = [];
17+
}
18+
19+
module.exports = {
20+
configure: configure,
21+
replay: replay,
22+
reset: reset
23+
};

lib/appenders/stdout.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
'use strict';
22

3-
const layouts = require('../layouts');
4-
53
function stdoutAppender(layout, timezoneOffset) {
6-
layout = layout || layouts.colouredLayout;
74
return function (loggingEvent) {
85
process.stdout.write(`${layout(loggingEvent, timezoneOffset)}\n`);
96
};
107
}
118

12-
function configure(config) {
13-
let layout;
9+
function configure(config, layouts) {
10+
let layout = layouts.colouredLayout;
1411
if (config.layout) {
1512
layout = layouts.layout(config.layout.type, config.layout);
1613
}
1714
return stdoutAppender(layout, config.timezoneOffset);
1815
}
1916

20-
exports.appender = stdoutAppender;
2117
exports.configure = configure;

lib/configuration.js

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
'use strict';
2+
3+
const util = require('util');
4+
const levels = require('./levels');
5+
const layouts = require('./layouts');
6+
7+
function not(thing) {
8+
return !thing;
9+
}
10+
11+
function anObject(thing) {
12+
return thing && typeof thing === 'object' && !Array.isArray(thing);
13+
}
14+
15+
class Configuration {
16+
17+
throwExceptionIf(checks, message) {
18+
const tests = Array.isArray(checks) ? checks : [checks];
19+
tests.forEach((test) => {
20+
if (test) {
21+
throw new Error(
22+
`Problem with log4js configuration: (${util.inspect(this.candidate, { depth: 5 })}) - ${message}`
23+
);
24+
}
25+
});
26+
}
27+
28+
tryLoading(path) {
29+
try {
30+
return require(path); //eslint-disable-line
31+
} catch (e) {
32+
// if the module was found, and we still got an error, then raise it
33+
this.throwExceptionIf(
34+
e.code !== 'MODULE_NOT_FOUND',
35+
`appender "${path}" could not be loaded (error was: ${e})`
36+
);
37+
return undefined;
38+
}
39+
}
40+
41+
loadAppenderModule(type) {
42+
return this.tryLoading(`./appenders/${type}`) || this.tryLoading(type);
43+
}
44+
45+
createAppender(name, config) {
46+
const appenderModule = this.loadAppenderModule(config.type);
47+
this.throwExceptionIf(
48+
not(appenderModule),
49+
`appender "${name}" is not valid (type "${config.type}" could not be found)`
50+
);
51+
return appenderModule.configure(config, layouts, this.configuredAppenders.get.bind(this.configuredAppenders));
52+
}
53+
54+
get appenders() {
55+
return this.configuredAppenders;
56+
}
57+
58+
set appenders(appenderConfig) {
59+
const appenderNames = Object.keys(appenderConfig);
60+
this.throwExceptionIf(not(appenderNames.length), 'must define at least one appender.');
61+
62+
this.configuredAppenders = new Map();
63+
appenderNames.forEach((name) => {
64+
this.throwExceptionIf(
65+
not(appenderConfig[name].type),
66+
`appender "${name}" is not valid (must be an object with property "type")`
67+
);
68+
69+
this.configuredAppenders.set(name, this.createAppender(name, appenderConfig[name]));
70+
});
71+
}
72+
73+
get categories() {
74+
return this.configuredCategories;
75+
}
76+
77+
set categories(categoryConfig) {
78+
const categoryNames = Object.keys(categoryConfig);
79+
this.throwExceptionIf(not(categoryNames.length), 'must define at least one category.');
80+
81+
this.configuredCategories = new Map();
82+
categoryNames.forEach((name) => {
83+
const category = categoryConfig[name];
84+
this.throwExceptionIf(
85+
[
86+
not(category.appenders),
87+
not(category.level)
88+
],
89+
`category "${name}" is not valid (must be an object with properties "appenders" and "level")`
90+
);
91+
92+
this.throwExceptionIf(
93+
not(Array.isArray(category.appenders)),
94+
`category "${name}" is not valid (appenders must be an array of appender names)`
95+
);
96+
97+
this.throwExceptionIf(
98+
not(category.appenders.length),
99+
`category "${name}" is not valid (appenders must contain at least one appender name)`
100+
);
101+
102+
const appenders = [];
103+
category.appenders.forEach((appender) => {
104+
this.throwExceptionIf(
105+
not(this.configuredAppenders.get(appender)),
106+
`category "${name}" is not valid (appender "${appender}" is not defined)`
107+
);
108+
appenders.push(this.appenders.get(appender));
109+
});
110+
111+
this.throwExceptionIf(
112+
not(levels.toLevel(category.level)),
113+
`category "${name}" is not valid (level "${category.level}" not recognised;` +
114+
` valid levels are ${levels.levels.join(', ')})`
115+
);
116+
117+
this.configuredCategories.set(name, { appenders: appenders, level: levels.toLevel(category.level) });
118+
});
119+
120+
this.throwExceptionIf(not(categoryConfig.default), 'must define a "default" category.');
121+
}
122+
123+
constructor(candidate) {
124+
this.candidate = candidate;
125+
126+
this.throwExceptionIf(not(anObject(candidate)), 'must be an object.');
127+
this.throwExceptionIf(not(anObject(candidate.appenders)), 'must have a property "appenders" of type object.');
128+
this.throwExceptionIf(not(anObject(candidate.categories)), 'must have a property "categories" of type object.');
129+
130+
this.appenders = candidate.appenders;
131+
this.categories = candidate.categories;
132+
}
133+
}
134+
135+
module.exports = Configuration;

lib/levels.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,15 @@ module.exports = {
8383
Level: Level,
8484
getLevel: getLevel
8585
};
86+
87+
module.exports.levels = [
88+
module.exports.ALL,
89+
module.exports.TRACE,
90+
module.exports.DEBUG,
91+
module.exports.INFO,
92+
module.exports.WARN,
93+
module.exports.ERROR,
94+
module.exports.FATAL,
95+
module.exports.MARK,
96+
module.exports.OFF
97+
];

0 commit comments

Comments
 (0)