const _ = require('lodash');
const {defaultBehaviorTreeOptions} = require('../constants');
/**
* There are two types of logger
* 1. logger for logging debug messages in this library
* 2. logger for logging customizable user log
*/
/**
* Default Log levels - syslog
* @see RFC 5424: https://www.rfc-editor.org/info/rfc5424
* @typedef {'emerg'|'alert'|'crit'|'err'|'warning'|'notice'|'info'|'debug'} SYSLOG_LEVEL
*/
/**
* Default logger
* @param tick
* @param level
* @param message
* @param extra
*/
/**
* @typedef {function} LogFunction
*/
/**
* @constant
* @type {{emerg: number, debug: number, crit: number, err: number, alert: number, warning: number, notice: number, info: number}}
*/
const severities = {
emerg: 1,
alert: 2,
crit: 3,
err: 4,
warning: 5,
notice: 6,
info: 7,
debug: 8
};
/**
* @class Logger
*/
class Logger {
/**
* @param {Context|{debug: boolean, debug_level: string}} context
* @param {LogFunction} logger
*/
constructor(context, logger) {
this.context = context;
this.options = _.defaults(context.options, defaultBehaviorTreeOptions);
this._log = logger || this.default_logger;
this._debugLog = this.options.debug && this.options.customLoggerForDebug ? logger || this.default_logger : this.default_logger;
// expends log
// for (const level in severities) {
// this[level] = function (message, extra) {
// return this.log(level, message, extra)
// };
// this['DEBUG_' + level] = function (message, extra) {
// return this.debugLog(level, message, extra);
// };
// }
}
get logger() {
return this._log;
}
set logger(logger) {
this._log = logger;
}
get debugLogger() {
return this._debugLog;
}
set debugLogger(dlogger) {
this._debugLog = dlogger;
}
checkDebugLogLevel(context, level) {
const level_debug = _.get(severities, _.get(this.context, 'debug_level')) || severities['warning'];
const level_log = _.get(severities, level) || _.get(severities, 'emerg');
if (!_.get(severities, level)) {
console.warn('invalid log level ' + level, console.trace());
}
return (context.debug && (level_log <= level_debug));
}
debugLog(level, message, extra) {
if (this.checkDebugLogLevel(this.context, level)) {
return this._debugLog(level, message, extra)
}
}
log(level, message, extra) {
return this._log(level, message, extra);
}
/**
* @param {string} level
* @param {string} message
* @param {object} [extra]
* @private
*/
default_logger(level, message, extra) {
let msg = `${level}: ${message}`;
if (extra) {
msg += `\n${JSON.stringify(extra, null, 4)}`;
}
switch (level) {
case 'emerg':
case 'alert':
case 'crit':
case 'err':
return console.error(msg);
case 'warning':
case 'notice':
return console.warn(msg);
case 'info':
return console.info(msg);
case 'debug':
default:
return console.log(msg);
}
}
debug(message, extra) {
this.log('debug', message, extra);
}
info(message, extra) {
this.log('info', message, extra);
}
notice(message, extra) {
this.log('notice', message, extra);
}
warning(message, extra) {
this.log('warning', message, extra);
}
err(message, extra) {
this.log('err', message, extra);
}
crit(message, extra) {
this.log('crit', message, extra);
}
alert(message, extra) {
this.log('alert', message, extra);
}
emerg(message, extra) {
this.log('emerg', message, extra);
}
// debug logger
DEBUG_debug(message, extra) {
this.debugLog('debug', message, extra);
}
DEBUG_info(message, extra) {
this.debugLog('info', message, extra);
}
DEBUG_notice(message, extra) {
this.debugLog('notice', message, extra);
}
DEBUG_warning(message, extra) {
this.debugLog('warning', message, extra);
}
DEBUG_err(message, extra) {
this.debugLog('err', message, extra);
}
DEBUG_crit(message, extra) {
this.debugLog('crit', message, extra);
}
DEBUG_alert(message, extra) {
this.debugLog('alert', message, extra);
}
DEBUG_emerg(message, extra) {
this.debugLog('emerg', message, extra);
}
}
module.exports = Logger;