2013-06-04 06:17:36 +08:00
|
|
|
"use strict";
|
2010-08-10 19:56:10 +08:00
|
|
|
/*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2011-07-12 11:02:48 +08:00
|
|
|
* @fileoverview log4js is a library to log in JavaScript in similar manner
|
2010-08-10 19:56:10 +08:00
|
|
|
* than in log4j for Java. The API should be nearly the same.
|
2011-07-12 11:02:48 +08:00
|
|
|
*
|
2010-08-10 19:56:10 +08:00
|
|
|
* <h3>Example:</h3>
|
|
|
|
* <pre>
|
2011-07-12 11:02:48 +08:00
|
|
|
* var logging = require('log4js');
|
2010-08-10 19:56:10 +08:00
|
|
|
* //add an appender that logs all messages to stdout.
|
|
|
|
* logging.addAppender(logging.consoleAppender());
|
|
|
|
* //add an appender that logs "some-category" to a file
|
|
|
|
* logging.addAppender(logging.fileAppender("file.log"), "some-category");
|
|
|
|
* //get a logger
|
2011-07-12 11:02:48 +08:00
|
|
|
* var log = logging.getLogger("some-category");
|
2010-08-10 19:56:10 +08:00
|
|
|
* log.setLevel(logging.levels.TRACE); //set the Level
|
2011-07-12 11:02:48 +08:00
|
|
|
*
|
2010-08-10 19:56:10 +08:00
|
|
|
* ...
|
2011-07-12 11:02:48 +08:00
|
|
|
*
|
2010-08-10 19:56:10 +08:00
|
|
|
* //call the log
|
|
|
|
* log.trace("trace me" );
|
|
|
|
* </pre>
|
|
|
|
*
|
2011-07-26 06:52:40 +08:00
|
|
|
* NOTE: the authors below are the original browser-based log4js authors
|
|
|
|
* don't try to contact them about bugs in this version :)
|
2010-08-10 19:56:10 +08:00
|
|
|
* @version 1.0
|
|
|
|
* @author Stephan Strittmatter - http://jroller.com/page/stritti
|
|
|
|
* @author Seth Chisamore - http://www.chisamore.com
|
|
|
|
* @since 2005-05-20
|
|
|
|
* @static
|
|
|
|
* Website: http://log4js.berlios.de
|
|
|
|
*/
|
2011-07-12 11:02:48 +08:00
|
|
|
var events = require('events')
|
2013-08-05 05:21:12 +08:00
|
|
|
, async = require('async')
|
2011-07-12 11:02:48 +08:00
|
|
|
, fs = require('fs')
|
|
|
|
, path = require('path')
|
2011-11-16 05:10:20 +08:00
|
|
|
, util = require('util')
|
2011-07-12 11:02:48 +08:00
|
|
|
, layouts = require('./layouts')
|
|
|
|
, levels = require('./levels')
|
2014-04-08 10:06:29 +08:00
|
|
|
, loggerModule = require('./logger')
|
|
|
|
, LoggingEvent = loggerModule.LoggingEvent
|
|
|
|
, Logger = loggerModule.Logger
|
2011-07-12 11:02:48 +08:00
|
|
|
, ALL_CATEGORIES = '[all]'
|
|
|
|
, appenders = {}
|
|
|
|
, loggers = {}
|
2012-05-29 13:50:35 +08:00
|
|
|
, appenderMakers = {}
|
2014-04-06 06:12:45 +08:00
|
|
|
, appenderShutdowns = {}
|
2012-05-29 13:50:35 +08:00
|
|
|
, defaultConfig = {
|
2013-06-04 06:17:36 +08:00
|
|
|
appenders: [
|
|
|
|
{ type: "console" }
|
|
|
|
],
|
|
|
|
replaceConsole: false
|
2012-05-29 13:50:35 +08:00
|
|
|
};
|
2010-08-10 19:56:10 +08:00
|
|
|
|
2014-03-04 23:45:56 +08:00
|
|
|
function hasLogger(logger) {
|
|
|
|
return loggers.hasOwnProperty(logger);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-16 10:05:13 +08:00
|
|
|
/**
|
|
|
|
* Get a logger instance. Instance is cached on categoryName level.
|
|
|
|
* @param {String} categoryName name of category to log to.
|
|
|
|
* @return {Logger} instance of logger for the category
|
|
|
|
* @static
|
|
|
|
*/
|
|
|
|
function getLogger (categoryName) {
|
2011-07-12 11:02:48 +08:00
|
|
|
|
2013-06-04 06:17:36 +08:00
|
|
|
// Use default logger if categoryName is not specified or invalid
|
|
|
|
if (typeof categoryName !== "string") {
|
|
|
|
categoryName = Logger.DEFAULT_CATEGORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
var appenderList;
|
2014-03-04 23:45:56 +08:00
|
|
|
if (!hasLogger(categoryName)) {
|
2013-06-04 06:17:36 +08:00
|
|
|
// Create the logger for this name if it doesn't already exist
|
|
|
|
loggers[categoryName] = new Logger(categoryName);
|
|
|
|
if (appenders[categoryName]) {
|
|
|
|
appenderList = appenders[categoryName];
|
|
|
|
appenderList.forEach(function(appender) {
|
|
|
|
loggers[categoryName].addListener("log", appender);
|
|
|
|
});
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
if (appenders[ALL_CATEGORIES]) {
|
|
|
|
appenderList = appenders[ALL_CATEGORIES];
|
|
|
|
appenderList.forEach(function(appender) {
|
|
|
|
loggers[categoryName].addListener("log", appender);
|
|
|
|
});
|
2010-08-10 19:56:10 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return loggers[categoryName];
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
2010-08-10 19:56:10 +08:00
|
|
|
|
2011-01-16 10:05:13 +08:00
|
|
|
/**
|
|
|
|
* args are appender, then zero or more categories
|
|
|
|
*/
|
|
|
|
function addAppender () {
|
2013-06-04 06:17:36 +08:00
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
var appender = args.shift();
|
|
|
|
if (args.length === 0 || args[0] === undefined) {
|
|
|
|
args = [ ALL_CATEGORIES ];
|
|
|
|
}
|
|
|
|
//argument may already be an array
|
|
|
|
if (Array.isArray(args[0])) {
|
|
|
|
args = args[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
args.forEach(function(category) {
|
2013-06-04 06:37:36 +08:00
|
|
|
addAppenderToCategory(appender, category);
|
2013-06-04 06:17:36 +08:00
|
|
|
|
|
|
|
if (category === ALL_CATEGORIES) {
|
2013-06-04 06:37:36 +08:00
|
|
|
addAppenderToAllLoggers(appender);
|
2014-03-04 23:45:56 +08:00
|
|
|
} else if (hasLogger(category)) {
|
2013-06-04 06:17:36 +08:00
|
|
|
loggers[category].addListener("log", appender);
|
|
|
|
}
|
|
|
|
});
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
2013-06-04 06:37:36 +08:00
|
|
|
function addAppenderToAllLoggers(appender) {
|
|
|
|
for (var logger in loggers) {
|
2014-03-04 23:45:56 +08:00
|
|
|
if (hasLogger(logger)) {
|
2013-06-04 06:37:36 +08:00
|
|
|
loggers[logger].addListener("log", appender);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function addAppenderToCategory(appender, category) {
|
|
|
|
if (!appenders[category]) {
|
|
|
|
appenders[category] = [];
|
|
|
|
}
|
|
|
|
appenders[category].push(appender);
|
|
|
|
}
|
|
|
|
|
2011-01-16 10:05:13 +08:00
|
|
|
function clearAppenders () {
|
2013-06-04 06:17:36 +08:00
|
|
|
appenders = {};
|
|
|
|
for (var logger in loggers) {
|
2014-03-04 23:45:56 +08:00
|
|
|
if (hasLogger(logger)) {
|
2013-06-04 06:17:36 +08:00
|
|
|
loggers[logger].removeAllListeners("log");
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
2012-05-31 05:50:01 +08:00
|
|
|
function configureAppenders(appenderList, options) {
|
2013-06-04 06:17:36 +08:00
|
|
|
clearAppenders();
|
|
|
|
if (appenderList) {
|
|
|
|
appenderList.forEach(function(appenderConfig) {
|
|
|
|
loadAppender(appenderConfig.type);
|
|
|
|
var appender;
|
|
|
|
appenderConfig.makers = appenderMakers;
|
2013-06-17 14:01:03 +08:00
|
|
|
try {
|
|
|
|
appender = appenderMakers[appenderConfig.type](appenderConfig, options);
|
2013-06-04 06:17:36 +08:00
|
|
|
addAppender(appender, appenderConfig.category);
|
2013-06-17 14:01:03 +08:00
|
|
|
} catch(e) {
|
|
|
|
throw new Error("log4js configuration problem for " + util.inspect(appenderConfig), e);
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
2010-08-10 19:56:10 +08:00
|
|
|
|
2011-01-16 10:05:13 +08:00
|
|
|
function configureLevels(levels) {
|
2013-06-04 06:17:36 +08:00
|
|
|
if (levels) {
|
|
|
|
for (var category in levels) {
|
|
|
|
if (levels.hasOwnProperty(category)) {
|
|
|
|
getLogger(category).setLevel(levels[category]);
|
|
|
|
}
|
2010-12-04 17:49:39 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
2011-05-30 19:26:30 +08:00
|
|
|
function setGlobalLogLevel(level) {
|
2013-06-04 06:17:36 +08:00
|
|
|
Logger.prototype.level = levels.toLevel(level, levels.TRACE);
|
2011-05-30 19:26:30 +08:00
|
|
|
}
|
|
|
|
|
2011-01-16 10:05:13 +08:00
|
|
|
/**
|
|
|
|
* Get the default logger instance.
|
|
|
|
* @return {Logger} instance of default logger
|
|
|
|
* @static
|
|
|
|
*/
|
|
|
|
function getDefaultLogger () {
|
2013-06-04 06:17:36 +08:00
|
|
|
return getLogger(Logger.DEFAULT_CATEGORY);
|
2011-01-16 10:05:13 +08:00
|
|
|
}
|
|
|
|
|
2011-10-05 09:22:31 +08:00
|
|
|
var configState = {};
|
|
|
|
|
2011-07-22 12:43:33 +08:00
|
|
|
function loadConfigurationFile(filename) {
|
2013-07-09 07:24:11 +08:00
|
|
|
if (filename) {
|
2013-06-04 06:17:36 +08:00
|
|
|
return JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
|
|
}
|
|
|
|
return undefined;
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
|
|
|
|
2012-05-31 05:50:01 +08:00
|
|
|
function configureOnceOff(config, options) {
|
2013-06-04 06:17:36 +08:00
|
|
|
if (config) {
|
|
|
|
try {
|
|
|
|
configureAppenders(config.appenders, options);
|
|
|
|
configureLevels(config.levels);
|
|
|
|
|
|
|
|
if (config.replaceConsole) {
|
|
|
|
replaceConsole();
|
|
|
|
} else {
|
|
|
|
restoreConsole();
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
throw new Error(
|
|
|
|
"Problem reading log4js config " + util.inspect(config) +
|
|
|
|
". Error was \"" + e.message + "\" (" + e.stack + ")"
|
|
|
|
);
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function reloadConfiguration() {
|
2013-07-09 07:24:11 +08:00
|
|
|
var mtime = getMTime(configState.filename);
|
|
|
|
if (!mtime) return;
|
|
|
|
|
|
|
|
if (configState.lastMTime && (mtime.getTime() > configState.lastMTime.getTime())) {
|
|
|
|
configureOnceOff(loadConfigurationFile(configState.filename));
|
|
|
|
}
|
|
|
|
configState.lastMTime = mtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMTime(filename) {
|
|
|
|
var mtime;
|
2013-06-04 06:17:36 +08:00
|
|
|
try {
|
2013-07-09 07:24:11 +08:00
|
|
|
mtime = fs.statSync(configState.filename).mtime;
|
2013-06-04 06:17:36 +08:00
|
|
|
} catch (e) {
|
|
|
|
getLogger('log4js').warn('Failed to load configuration file ' + filename);
|
|
|
|
}
|
2013-07-09 07:24:11 +08:00
|
|
|
return mtime;
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function initReloadConfiguration(filename, options) {
|
2013-06-04 06:17:36 +08:00
|
|
|
if (configState.timerId) {
|
|
|
|
clearInterval(configState.timerId);
|
|
|
|
delete configState.timerId;
|
|
|
|
}
|
|
|
|
configState.filename = filename;
|
2013-07-09 07:24:11 +08:00
|
|
|
configState.lastMTime = getMTime(filename);
|
2013-06-04 06:17:36 +08:00
|
|
|
configState.timerId = setInterval(reloadConfiguration, options.reloadSecs*1000);
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
|
|
|
|
2012-05-29 13:50:35 +08:00
|
|
|
function configure(configurationFileOrObject, options) {
|
2013-06-04 06:17:36 +08:00
|
|
|
var config = configurationFileOrObject;
|
|
|
|
config = config || process.env.LOG4JS_CONFIG;
|
|
|
|
options = options || {};
|
2012-10-16 05:36:26 +08:00
|
|
|
|
2013-06-04 06:17:36 +08:00
|
|
|
if (config === undefined || config === null || typeof(config) === 'string') {
|
|
|
|
if (options.reloadSecs) {
|
|
|
|
initReloadConfiguration(config, options);
|
|
|
|
}
|
|
|
|
config = loadConfigurationFile(config) || defaultConfig;
|
|
|
|
} else {
|
|
|
|
if (options.reloadSecs) {
|
|
|
|
getLogger('log4js').warn(
|
|
|
|
'Ignoring configuration reload parameter for "object" configuration.'
|
|
|
|
);
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
}
|
|
|
|
configureOnceOff(config, options);
|
2011-07-22 12:43:33 +08:00
|
|
|
}
|
|
|
|
|
2012-02-22 05:53:28 +08:00
|
|
|
var originalConsoleFunctions = {
|
2013-06-04 06:17:36 +08:00
|
|
|
log: console.log,
|
|
|
|
debug: console.debug,
|
|
|
|
info: console.info,
|
|
|
|
warn: console.warn,
|
|
|
|
error: console.error
|
2012-02-22 05:53:28 +08:00
|
|
|
};
|
|
|
|
|
2011-07-12 11:02:48 +08:00
|
|
|
function replaceConsole(logger) {
|
2013-06-04 06:17:36 +08:00
|
|
|
function replaceWith(fn) {
|
|
|
|
return function() {
|
|
|
|
fn.apply(logger, arguments);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
logger = logger || getLogger("console");
|
|
|
|
['log','debug','info','warn','error'].forEach(function (item) {
|
|
|
|
console[item] = replaceWith(item === 'log' ? logger.info : logger[item]);
|
|
|
|
});
|
2011-11-18 05:44:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function restoreConsole() {
|
2013-06-04 06:17:36 +08:00
|
|
|
['log', 'debug', 'info', 'warn', 'error'].forEach(function (item) {
|
|
|
|
console[item] = originalConsoleFunctions[item];
|
|
|
|
});
|
2011-07-12 11:02:48 +08:00
|
|
|
}
|
2010-12-08 05:53:59 +08:00
|
|
|
|
2011-10-27 13:25:38 +08:00
|
|
|
function loadAppender(appender) {
|
2013-06-04 06:17:36 +08:00
|
|
|
var appenderModule;
|
|
|
|
try {
|
|
|
|
appenderModule = require('./appenders/' + appender);
|
|
|
|
} catch (e) {
|
|
|
|
appenderModule = require(appender);
|
|
|
|
}
|
|
|
|
module.exports.appenders[appender] = appenderModule.appender.bind(appenderModule);
|
2014-04-06 06:12:45 +08:00
|
|
|
if (appenderModule.shutdown) {
|
|
|
|
appenderShutdowns[appender] = appenderModule.shutdown.bind(appenderModule);
|
|
|
|
}
|
2013-06-04 06:17:36 +08:00
|
|
|
appenderMakers[appender] = appenderModule.configure.bind(appenderModule);
|
2011-07-24 19:58:02 +08:00
|
|
|
}
|
2010-12-08 05:53:59 +08:00
|
|
|
|
2014-04-08 10:06:29 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2013-08-05 05:21:12 +08:00
|
|
|
function shutdown(cb) {
|
2014-04-08 10:06:29 +08:00
|
|
|
// First, disable all writing to appenders. This prevents appenders from
|
|
|
|
// not being able to be drained because of run-away log writes.
|
|
|
|
loggerModule.disableAllLogWrites();
|
|
|
|
|
|
|
|
// Next, get all the shutdown functions for appenders as an array.
|
2014-04-06 06:12:45 +08:00
|
|
|
var shutdownFunctions = Object.keys(appenderShutdowns).reduce(
|
2013-08-05 05:21:12 +08:00
|
|
|
function(accum, category) {
|
2014-04-06 06:12:45 +08:00
|
|
|
return accum.concat(appenderShutdowns[category]);
|
2013-08-05 05:21:12 +08:00
|
|
|
}, []);
|
2014-04-08 10:06:29 +08:00
|
|
|
|
|
|
|
// Call each of the shutdown functions.
|
2013-08-05 05:21:12 +08:00
|
|
|
async.forEach(
|
2014-04-06 06:12:45 +08:00
|
|
|
shutdownFunctions,
|
|
|
|
function(shutdownFn, done) {
|
|
|
|
shutdownFn(done);
|
2013-08-05 05:21:12 +08:00
|
|
|
},
|
2014-04-06 06:12:45 +08:00
|
|
|
cb
|
2013-08-05 05:21:12 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2011-07-12 11:02:48 +08:00
|
|
|
module.exports = {
|
2013-06-04 06:17:36 +08:00
|
|
|
getLogger: getLogger,
|
|
|
|
getDefaultLogger: getDefaultLogger,
|
2014-03-04 23:45:56 +08:00
|
|
|
hasLogger: hasLogger,
|
2013-06-04 06:17:36 +08:00
|
|
|
|
|
|
|
addAppender: addAppender,
|
|
|
|
loadAppender: loadAppender,
|
|
|
|
clearAppenders: clearAppenders,
|
|
|
|
configure: configure,
|
2013-08-05 05:21:12 +08:00
|
|
|
shutdown: shutdown,
|
2013-06-04 06:17:36 +08:00
|
|
|
|
|
|
|
replaceConsole: replaceConsole,
|
|
|
|
restoreConsole: restoreConsole,
|
|
|
|
|
|
|
|
levels: levels,
|
|
|
|
setGlobalLogLevel: setGlobalLogLevel,
|
|
|
|
|
|
|
|
layouts: layouts,
|
|
|
|
appenders: {},
|
|
|
|
appenderMakers: appenderMakers,
|
|
|
|
connectLogger: require('./connect-logger').connectLogger
|
2010-08-10 19:56:10 +08:00
|
|
|
};
|
|
|
|
|
2012-05-29 13:50:35 +08:00
|
|
|
//set ourselves up
|
|
|
|
configure();
|
2011-07-24 19:58:02 +08:00
|
|
|
|