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.
171 lines
4.5 KiB
171 lines
4.5 KiB
/**
|
|
* @fileoverview log4js is a library to log in JavaScript in similar manner
|
|
* than in log4j for Java (but not really).
|
|
*
|
|
* <h3>Example:</h3>
|
|
* <pre>
|
|
* const logging = require('log4js');
|
|
* const log = logging.getLogger('some-category');
|
|
*
|
|
* //call the log
|
|
* log.trace('trace me' );
|
|
* </pre>
|
|
*
|
|
* NOTE: the authors below are the original browser-based log4js authors
|
|
* don't try to contact them about bugs in this version :)
|
|
* @author Stephan Strittmatter - http://jroller.com/page/stritti
|
|
* @author Seth Chisamore - http://www.chisamore.com
|
|
* @since 2005-05-20
|
|
* Website: http://log4js.berlios.de
|
|
*/
|
|
const debug = require("debug")("log4js:main");
|
|
const fs = require("fs");
|
|
const deepClone = require("rfdc")({ proto: true });
|
|
const configuration = require("./configuration");
|
|
const layouts = require("./layouts");
|
|
const levels = require("./levels");
|
|
const appenders = require("./appenders");
|
|
const categories = require("./categories");
|
|
const Logger = require("./logger");
|
|
const clustering = require("./clustering");
|
|
const connectLogger = require("./connect-logger");
|
|
const recordingModule = require("./appenders/recording");
|
|
|
|
let enabled = false;
|
|
|
|
function sendLogEventToAppender(logEvent) {
|
|
if (!enabled) return;
|
|
debug("Received log event ", logEvent);
|
|
const categoryAppenders = categories.appendersForCategory(
|
|
logEvent.categoryName
|
|
);
|
|
categoryAppenders.forEach(appender => {
|
|
appender(logEvent);
|
|
});
|
|
}
|
|
|
|
function loadConfigurationFile(filename) {
|
|
debug(`Loading configuration from ${filename}`);
|
|
try {
|
|
return JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
} catch (e) {
|
|
throw new Error(
|
|
`Problem reading config from file "${filename}". Error was ${e.message}`,
|
|
e
|
|
);
|
|
}
|
|
}
|
|
|
|
function configure(configurationFileOrObject) {
|
|
if (enabled) {
|
|
// eslint-disable-next-line no-use-before-define
|
|
shutdown();
|
|
}
|
|
|
|
let configObject = configurationFileOrObject;
|
|
|
|
if (typeof configObject === "string") {
|
|
configObject = loadConfigurationFile(configurationFileOrObject);
|
|
}
|
|
debug(`Configuration is ${configObject}`);
|
|
|
|
configuration.configure(deepClone(configObject));
|
|
|
|
clustering.onMessage(sendLogEventToAppender);
|
|
|
|
enabled = true;
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
return log4js;
|
|
}
|
|
|
|
function recording() {
|
|
return recordingModule
|
|
}
|
|
|
|
/**
|
|
* Shutdown all log appenders. This will first disable all writing to appenders
|
|
* and then call the shutdown function each appender.
|
|
*
|
|
* @params {Function} cb - The callback to be invoked once all appenders have
|
|
* shutdown. If an error occurs, the callback will be given the error object
|
|
* as the first argument.
|
|
*/
|
|
function shutdown(cb) {
|
|
debug("Shutdown called. Disabling all log writing.");
|
|
// First, disable all writing to appenders. This prevents appenders from
|
|
// not being able to be drained because of run-away log writes.
|
|
enabled = false;
|
|
|
|
// Clone out to maintain a reference
|
|
const appendersToCheck = Array.from(appenders.values());
|
|
|
|
// Reset immediately to prevent leaks
|
|
appenders.init();
|
|
categories.init();
|
|
|
|
// Call each of the shutdown functions in parallel
|
|
const shutdownFunctions = appendersToCheck.reduceRight(
|
|
(accum, next) => (next.shutdown ? accum + 1 : accum),
|
|
0
|
|
);
|
|
if (shutdownFunctions === 0) {
|
|
debug("No appenders with shutdown functions found.");
|
|
return cb !== undefined && cb();
|
|
}
|
|
|
|
let completed = 0;
|
|
let error;
|
|
debug(`Found ${shutdownFunctions} appenders with shutdown functions.`);
|
|
function complete(err) {
|
|
error = error || err;
|
|
completed += 1;
|
|
debug(`Appender shutdowns complete: ${completed} / ${shutdownFunctions}`);
|
|
if (completed >= shutdownFunctions) {
|
|
debug("All shutdown functions completed.");
|
|
if (cb) {
|
|
cb(error);
|
|
}
|
|
}
|
|
}
|
|
appendersToCheck.filter(a => a.shutdown).forEach(a => a.shutdown(complete));
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a logger instance.
|
|
* @static
|
|
* @param loggerCategoryName
|
|
* @return {Logger} instance of logger for the category
|
|
*/
|
|
function getLogger(category) {
|
|
if (!enabled) {
|
|
configure(
|
|
process.env.LOG4JS_CONFIG || {
|
|
appenders: { out: { type: "stdout" } },
|
|
categories: { default: { appenders: ["out"], level: "OFF" } }
|
|
}
|
|
);
|
|
}
|
|
return new Logger(category || "default");
|
|
}
|
|
|
|
/**
|
|
* @name log4js
|
|
* @namespace Log4js
|
|
* @property getLogger
|
|
* @property configure
|
|
* @property shutdown
|
|
*/
|
|
const log4js = {
|
|
getLogger,
|
|
configure,
|
|
shutdown,
|
|
connectLogger,
|
|
levels,
|
|
addLayout: layouts.addLayout,
|
|
recording,
|
|
};
|
|
|
|
module.exports = log4js;
|