@evojs/logger
Version:
Nodejs logger
199 lines (198 loc) • 5.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
/* eslint-disable lodash/prefer-lodash-typecheck */
const context_1 = require("@evojs/context");
const data_to_table_function_1 = require("./data-to-table.function");
const enums_1 = require("./enums");
const log_1 = require("./log");
const LOG_LEVELS = Object.values(enums_1.LogLevel);
const DEFAULT_LEVEL = enums_1.LogLevel.INFO;
class Logger {
/**
* Create new Logger with custom options
*/
constructor(options = {}) {
this._pipes = {};
this._startTimes = {};
const { name = Logger.logname, formats = Logger._formats, handler = Logger._handler, logLevel, callsiteDepth, } = options;
this.logname = name;
this._formats = formats;
this._handler = handler;
this._callsiteDepth = callsiteDepth ?? Logger._callsiteDepth;
this._loglevelindex = logLevel ? LOG_LEVELS.indexOf(logLevel) : Logger._loglevelindex;
Object.assign(this._pipes, Logger._pipes, options.pipes);
}
setName(nameOrConstructor) {
const logger = this.clone();
const name = typeof nameOrConstructor === 'function' ? nameOrConstructor.name : nameOrConstructor;
// @ts-ignore
logger.logname = [logger.logname, name].filter(Boolean).join('.');
return logger;
}
/**
* Create a new logger with options of current logger.
*/
clone() {
return new Logger({
name: this.logname,
formats: this._formats,
pipes: this._pipes,
handler: this._handler,
logLevel: LOG_LEVELS[this._loglevelindex],
callsiteDepth: this._callsiteDepth,
});
}
/**
* Create fatal log.
*/
fatal(...args) {
Logger.fatal.apply(this, args);
}
/**
* Create error log.
*/
error(...args) {
Logger.error.apply(this, args);
}
/**
* Create warn log.
*/
warn(...args) {
Logger.warn.apply(this, args);
}
/**
* Create info log.
*/
info(...args) {
Logger.info.apply(this, args);
}
/**
* Create debug log. Enable debug for working.
*/
debug(...args) {
Logger.debug.apply(this, args);
}
/**
* Create verbose log.
*/
verbose(...args) {
Logger.verbose.apply(this, args);
}
/**
* Create verbose log.
*/
log(level, name, ...args) {
Logger.log.call(this, level, name, ...args);
}
table(...args) {
Logger.table.apply(this, args);
}
start(label, level) {
Logger.start.call(this, label, level);
}
end(label, level) {
Logger.end.call(this, label, level);
}
static _handle(level, args, logname = this.logname) {
if (LOG_LEVELS.indexOf(level) > this._loglevelindex) {
return;
}
if (Logger._handling) {
process.nextTick(Logger._handle.bind(this), this, level, args, logname);
return;
}
Logger._handling = true;
const { _formats, _pipes, _handler, _callsiteDepth } = this;
try {
const log = new log_1.Log(logname, _formats, _pipes, level, args, _callsiteDepth);
_handler.call(this, log);
}
catch (err) {
console.error(err);
process.exit(1);
}
Logger._handling = false;
}
/**
* Set global options.
*/
static configure(options) {
this.logname = options.name || '';
this._callsiteDepth = options.callsiteDepth;
if (Array.isArray(options.formats)) {
this._formats.splice(0, this._formats.length, ...options.formats);
}
if (typeof options.handler === 'function') {
this._handler = options.handler;
}
Object.assign(this._pipes, options.pipes);
this._loglevelindex = LOG_LEVELS.indexOf(options.logLevel || enums_1.LogLevel.VERBOSE);
}
static setName(nameOrConstructor) {
const name = typeof nameOrConstructor === 'function' ? nameOrConstructor.name : nameOrConstructor;
const logname = [this.logname, name].filter(Boolean).join('.');
return new this({ name: logname });
}
static fatal(...args) {
Logger._handle.call(this, enums_1.LogLevel.FATAL, args);
}
static error(...args) {
Logger._handle.call(this, enums_1.LogLevel.ERROR, args);
}
static warn(...args) {
Logger._handle.call(this, enums_1.LogLevel.WARN, args);
}
static info(...args) {
Logger._handle.call(this, enums_1.LogLevel.INFO, args);
}
static debug(...args) {
Logger._handle.call(this, enums_1.LogLevel.DEBUG, args);
}
static verbose(...args) {
Logger._handle.call(this, enums_1.LogLevel.VERBOSE, args);
}
static log(level, name = this.logname, ...args) {
Logger._handle.call(this, level, args, name);
}
static table(...args) {
const [arg0, arg1, arg2] = args;
const [message, values, level] = (typeof arg0 === 'string'
? [arg0, arg1, arg2 || DEFAULT_LEVEL]
: [undefined, arg0, arg1 || DEFAULT_LEVEL]);
const table = (0, data_to_table_function_1.dataToTable)(values);
Logger._handle.call(this, level, message ? [message, table] : [table]);
}
static start(label, level = DEFAULT_LEVEL) {
const asyncContext = context_1.AsyncContext.get();
if (!asyncContext) {
throw new Error(`AsyncContext is not available`);
}
const { traceId } = asyncContext;
this._startTimes[`${label}_${traceId}`] = process.hrtime.bigint();
Logger._handle.call(this, level, [`Start of '${label}'`]);
}
static end(label, level = DEFAULT_LEVEL) {
const asyncContext = context_1.AsyncContext.get();
if (!asyncContext) {
throw new Error(`AsyncContext is not available`);
}
const { traceId } = asyncContext;
const startTime = this._startTimes[`${label}_${traceId}`];
if (!startTime) {
throw new Error(`No such label '${label}' for Logger#end`);
}
const endTime = process.hrtime.bigint();
const delta = Number((endTime - startTime) / 1000000n);
delete this._startTimes[`${label}_${traceId}`];
Logger._handle.call(this, level, [`End of '${label}' (${delta}ms)`]);
}
}
exports.Logger = Logger;
Logger.logname = '';
Logger._pipes = {};
Logger._formats = [];
Logger._startTimes = {};
Logger._loglevelindex = LOG_LEVELS.indexOf(enums_1.LogLevel.VERBOSE);
Logger._handling = false;
Logger._handler = (log) => { };