You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

145 lines
5.1 KiB

const path = require('path');
const debug = require('debug')('log4js:appenders');
const configuration = require('../configuration');
const clustering = require('../clustering');
const levels = require('../levels');
const layouts = require('../layouts');
const adapters = require('./adapters');
// pre-load the core appenders so that webpack can find them
const coreAppenders = new Map();
coreAppenders.set('console', require('./console'));
coreAppenders.set('stdout', require('./stdout'));
coreAppenders.set('stderr', require('./stderr'));
coreAppenders.set('logLevelFilter', require('./logLevelFilter'));
coreAppenders.set('categoryFilter', require('./categoryFilter'));
coreAppenders.set('noLogFilter', require('./noLogFilter'));
coreAppenders.set('file', require('./file'));
coreAppenders.set('dateFile', require('./dateFile'));
coreAppenders.set('fileSync', require('./fileSync'));
coreAppenders.set('tcp', require('./tcp'));
const appenders = new Map();
const tryLoading = (modulePath, config) => {
debug('Loading module from ', modulePath);
try {
return require(modulePath); // eslint-disable-line
} catch (e) {
// if the module was found, and we still got an error, then raise it
configuration.throwExceptionIf(
config,
e.code !== 'MODULE_NOT_FOUND',
`appender "${modulePath}" could not be loaded (error was: ${e})`
);
return undefined;
}
};
const loadAppenderModule = (type, config) => coreAppenders.get(type)
|| tryLoading(`./${type}`, config)
|| tryLoading(type, config)
|| (require.main && require.main.filename && tryLoading(path.join(path.dirname(require.main.filename), type), config))
|| tryLoading(path.join(process.cwd(), type), config);
const appendersLoading = new Set();
const getAppender = (name, config) => {
if (appenders.has(name)) return appenders.get(name);
if (!config.appenders[name]) return false;
if (appendersLoading.has(name)) throw new Error(`Dependency loop detected for appender ${name}.`);
appendersLoading.add(name);
debug(`Creating appender ${name}`);
// eslint-disable-next-line no-use-before-define
const appender = createAppender(name, config);
appendersLoading.delete(name);
appenders.set(name, appender);
return appender;
};
const createAppender = (name, config) => {
const appenderConfig = config.appenders[name];
const appenderModule = appenderConfig.type.configure
? appenderConfig.type : loadAppenderModule(appenderConfig.type, config);
configuration.throwExceptionIf(
config,
configuration.not(appenderModule),
`appender "${name}" is not valid (type "${appenderConfig.type}" could not be found)`
);
if (appenderModule.appender) {
process.emitWarning(
`Appender ${appenderConfig.type} exports an appender function.`,
"DeprecationWarning", "log4js-node-DEP0001"
);
debug(`DEPRECATION: Appender ${appenderConfig.type} exports an appender function.`);
}
if (appenderModule.shutdown) {
process.emitWarning(
`Appender ${appenderConfig.type} exports a shutdown function.`,
"DeprecationWarning", "log4js-node-DEP0002"
);
debug(`DEPRECATION: Appender ${appenderConfig.type} exports a shutdown function.`);
}
debug(`${name}: clustering.isMaster ? ${clustering.isMaster()}`);
debug(`${name}: appenderModule is ${require('util').inspect(appenderModule)}`); // eslint-disable-line
return clustering.onlyOnMaster(() => {
debug(`calling appenderModule.configure for ${name} / ${appenderConfig.type}`);
return appenderModule.configure(
adapters.modifyConfig(appenderConfig),
layouts,
appender => getAppender(appender, config),
levels
);
}, () => { });
};
const setup = (config) => {
appenders.clear();
appendersLoading.clear();
const usedAppenders = [];
Object.values(config.categories).forEach(category => {
usedAppenders.push(...category.appenders);
});
Object.keys(config.appenders).forEach((name) => {
// dodgy hard-coding of special case for tcp-server and multiprocess which may not have
// any categories associated with it, but needs to be started up anyway
if (usedAppenders.includes(name) || config.appenders[name].type === 'tcp-server'
|| config.appenders[name].type === 'multiprocess') {
getAppender(name, config);
}
});
};
const init = () => {
setup({ appenders: { out: { type: 'stdout' } }, categories: { default: { appenders: ['out'], level: 'trace' } } });
};
init();
configuration.addListener((config) => {
configuration.throwExceptionIf(
config,
configuration.not(configuration.anObject(config.appenders)),
'must have a property "appenders" of type object.'
);
const appenderNames = Object.keys(config.appenders);
configuration.throwExceptionIf(
config,
configuration.not(appenderNames.length),
'must define at least one appender.'
);
appenderNames.forEach((name) => {
configuration.throwExceptionIf(
config,
configuration.not(config.appenders[name].type),
`appender "${name}" is not valid (must be an object with property "type")`
);
});
});
configuration.addListener(setup);
module.exports = appenders;
module.exports.init = init;