mirror of
https://github.com/log4js-node/log4js-node.git
synced 2025-12-08 19:26:01 +00:00
185 lines
5.5 KiB
JavaScript
185 lines
5.5 KiB
JavaScript
'use strict';
|
|
|
|
const util = require('util');
|
|
const levels = require('./levels');
|
|
const layouts = require('./layouts');
|
|
const debug = require('debug')('log4js:configuration');
|
|
|
|
function not(thing) {
|
|
return !thing;
|
|
}
|
|
|
|
function anObject(thing) {
|
|
return thing && typeof thing === 'object' && !Array.isArray(thing);
|
|
}
|
|
|
|
function validIdentifier(thing) {
|
|
return /^[A-Za-z][A-Za-z0-9_]*$/g.test(thing);
|
|
}
|
|
|
|
function anInteger(thing) {
|
|
return thing && typeof thing === 'number' && Number.isInteger(thing);
|
|
}
|
|
|
|
class Configuration {
|
|
|
|
throwExceptionIf(checks, message) {
|
|
const tests = Array.isArray(checks) ? checks : [checks];
|
|
tests.forEach((test) => {
|
|
if (test) {
|
|
throw new Error(
|
|
`Problem with log4js configuration: (${util.inspect(this.candidate, { depth: 5 })}) - ${message}`
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
tryLoading(path) {
|
|
try {
|
|
return require(path); //eslint-disable-line
|
|
} catch (e) {
|
|
// if the module was found, and we still got an error, then raise it
|
|
this.throwExceptionIf(
|
|
e.code !== 'MODULE_NOT_FOUND',
|
|
`appender "${path}" could not be loaded (error was: ${e})`
|
|
);
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
loadAppenderModule(type) {
|
|
return this.tryLoading(`./appenders/${type}`) || this.tryLoading(type);
|
|
}
|
|
|
|
createAppender(name, config) {
|
|
const appenderModule = this.loadAppenderModule(config.type);
|
|
this.throwExceptionIf(
|
|
not(appenderModule),
|
|
`appender "${name}" is not valid (type "${config.type}" could not be found)`
|
|
);
|
|
if (appenderModule.appender) {
|
|
debug(`DEPRECATION: Appender ${config.type} exports an appender function.`);
|
|
}
|
|
if (appenderModule.shutdown) {
|
|
debug(`DEPRECATION: Appender ${config.type} exports a shutdown function.`);
|
|
}
|
|
return appenderModule.configure(
|
|
config,
|
|
layouts,
|
|
this.configuredAppenders.get.bind(this.configuredAppenders),
|
|
this.configuredLevels
|
|
);
|
|
}
|
|
|
|
get appenders() {
|
|
return this.configuredAppenders;
|
|
}
|
|
|
|
set appenders(appenderConfig) {
|
|
const appenderNames = Object.keys(appenderConfig);
|
|
this.throwExceptionIf(not(appenderNames.length), 'must define at least one appender.');
|
|
|
|
this.configuredAppenders = new Map();
|
|
appenderNames.forEach((name) => {
|
|
this.throwExceptionIf(
|
|
not(appenderConfig[name].type),
|
|
`appender "${name}" is not valid (must be an object with property "type")`
|
|
);
|
|
|
|
debug(`Creating appender ${name}`);
|
|
this.configuredAppenders.set(name, this.createAppender(name, appenderConfig[name]));
|
|
});
|
|
}
|
|
|
|
get categories() {
|
|
return this.configuredCategories;
|
|
}
|
|
|
|
set categories(categoryConfig) {
|
|
const categoryNames = Object.keys(categoryConfig);
|
|
this.throwExceptionIf(not(categoryNames.length), 'must define at least one category.');
|
|
|
|
this.configuredCategories = new Map();
|
|
categoryNames.forEach((name) => {
|
|
const category = categoryConfig[name];
|
|
this.throwExceptionIf(
|
|
[
|
|
not(category.appenders),
|
|
not(category.level)
|
|
],
|
|
`category "${name}" is not valid (must be an object with properties "appenders" and "level")`
|
|
);
|
|
|
|
this.throwExceptionIf(
|
|
not(Array.isArray(category.appenders)),
|
|
`category "${name}" is not valid (appenders must be an array of appender names)`
|
|
);
|
|
|
|
this.throwExceptionIf(
|
|
not(category.appenders.length),
|
|
`category "${name}" is not valid (appenders must contain at least one appender name)`
|
|
);
|
|
|
|
const appenders = [];
|
|
category.appenders.forEach((appender) => {
|
|
this.throwExceptionIf(
|
|
not(this.configuredAppenders.get(appender)),
|
|
`category "${name}" is not valid (appender "${appender}" is not defined)`
|
|
);
|
|
appenders.push(this.appenders.get(appender));
|
|
});
|
|
|
|
this.throwExceptionIf(
|
|
not(this.configuredLevels.getLevel(category.level)),
|
|
`category "${name}" is not valid (level "${category.level}" not recognised;` +
|
|
` valid levels are ${this.configuredLevels.levels.join(', ')})`
|
|
);
|
|
|
|
debug(`Creating category ${name}`);
|
|
this.configuredCategories.set(
|
|
name,
|
|
{ appenders: appenders, level: this.configuredLevels.getLevel(category.level) }
|
|
);
|
|
});
|
|
|
|
this.throwExceptionIf(not(categoryConfig.default), 'must define a "default" category.');
|
|
}
|
|
|
|
get levels() {
|
|
return this.configuredLevels;
|
|
}
|
|
|
|
set levels(levelConfig) {
|
|
// levels are optional
|
|
if (levelConfig) {
|
|
this.throwExceptionIf(not(anObject(levelConfig)), 'levels must be an object');
|
|
const newLevels = Object.keys(levelConfig);
|
|
newLevels.forEach((l) => {
|
|
this.throwExceptionIf(
|
|
not(validIdentifier(l)),
|
|
`level name "${l}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`
|
|
);
|
|
this.throwExceptionIf(
|
|
not(anInteger(levelConfig[l])),
|
|
`level "${l}" must have an integer value`
|
|
);
|
|
});
|
|
}
|
|
this.configuredLevels = levels(levelConfig);
|
|
}
|
|
|
|
constructor(candidate) {
|
|
this.candidate = candidate;
|
|
|
|
this.throwExceptionIf(not(anObject(candidate)), 'must be an object.');
|
|
this.throwExceptionIf(not(anObject(candidate.appenders)), 'must have a property "appenders" of type object.');
|
|
this.throwExceptionIf(not(anObject(candidate.categories)), 'must have a property "categories" of type object.');
|
|
|
|
this.levels = candidate.levels;
|
|
this.appenders = candidate.appenders;
|
|
this.categories = candidate.categories;
|
|
}
|
|
}
|
|
|
|
module.exports = Configuration;
|