egg-logger
Version:
171 lines (154 loc) • 3.97 kB
JavaScript
const util = require('util');
const depd = require('depd')('egg-logger');
const utils = require('./utils');
/**
* Base class for all sub Logger class.
* It extends Map, and can contains multi {@link Transport}
*
* @example
* ```js
* const logger = new Logger();
* logger.set('file', new FileTransport({
* file: '/path/to/log',
* level: 'INFO',
* }));
* logger.set('console', new ConsoleTransport({
* level: 'INFO',
* }));
* logger.info('foo');
* ```
*/
class Logger extends Map {
/**
* @param {Object} options - assign with `defaults` propery
*/
constructor(options) {
super();
this.options = utils.assign(this.defaults, options);
this.transports = {};
this.name = this.constructor.name;
this.redirectLoggers = new Map();
this.duplicateLoggers = new Map();
}
/**
* disable a transport
* @param {String} name - transport name
*/
disable(name) {
const transport = this.get(name);
if (transport) transport.disable();
}
/**
* enable a transport
* @param {String} name - transport name
*/
enable(name) {
const transport = this.get(name);
if (transport) transport.enable();
}
/**
* Send log to all transports.
* It's proxy to {@link Transport}'s log method.
* @param {String} level - log level
* @param {Array} args - log arguments
* @param {Object} meta - log meta
*/
log(level, args, meta) {
let excludes;
let { logger, options } = this.duplicateLoggers.get(level) || {};
if (logger) {
excludes = options.excludes;
logger.log(level, args, meta);
} else {
logger = this.redirectLoggers.get(level);
if (logger) {
logger.log(level, args, meta);
return;
}
}
for (const [ key, transport ] of this.entries()) {
if (transport.shouldLog(level) && !(excludes && excludes.includes(key))) {
transport.log(level, args, meta);
}
}
}
/**
* write raw log to all transports
* @param {String} msg - log message
*/
write(msg) {
// support util.format
if (arguments.length > 1) msg = util.format.apply(util, arguments);
// `NONE` is the top level
this.log('NONE', [ msg ], { raw: true });
}
/**
* Redirect specify level log to the other logger
* @param {String} level - log level
* @param {Logger} logger - target logger instance
*/
redirect(level, logger) {
level = level.toUpperCase();
if (!this.redirectLoggers.has(level) && logger instanceof Logger) {
this.redirectLoggers.set(level, logger);
}
}
/**
* Un-redirect specify level log
* @param {String} level - log level
*/
unredirect(level) {
level = level.toUpperCase();
this.redirectLoggers.delete(level);
}
/**
* Duplicate specify level log to the other logger
* @param {String} level - log level
* @param {Logger} logger - target logger instance
* @param {Object} [options] - { excludes: [] }
*/
duplicate(level, logger, options = {}) {
level = level.toUpperCase();
if (!this.duplicateLoggers.has(level) && logger instanceof Logger) {
this.duplicateLoggers.set(level, { logger, options });
}
}
/**
* Un-duplicate specify level log
* @param {String} level - log level
*/
unduplicate(level) {
level = level.toUpperCase();
this.duplicateLoggers.delete(level);
}
/**
* Reload all transports
*/
reload() {
for (const transport of this.values()) {
transport.reload();
}
}
/**
* End all transports
*/
close() {
for (const transport of this.values()) {
transport.close();
}
}
/**
* @deprecated
*/
end() {
depd('logger.end() is deprecated, use logger.close()');
this.close();
}
}
[ 'error', 'warn', 'info', 'debug' ].forEach(level => {
const LEVEL = level.toUpperCase();
Logger.prototype[level] = function(...args) {
this.log(LEVEL, args);
};
});
module.exports = Logger;