@mojojs/core
Version:
Real-time web framework
221 lines • 5.75 kB
JavaScript
import assert from 'node:assert';
import chalk from 'chalk';
const LEVEL = {
fatal: 2,
error: 3,
warn: 4,
info: 5,
debug: 6,
trace: 7
};
/**
* A simple logger class.
*/
export class Logger {
constructor(options = {}) {
/**
* The last few logged messages.
*/
this.history = [];
this._capture = undefined;
this._level = 7;
this.destination = options.destination ?? process.stderr;
this.formatter = options.formatter ?? Logger.colorFormatter;
this.level = process.env.MOJO_LOG_LEVEL ?? options.level ?? 'trace';
this._historySize = options.historySize;
}
/**
* Capture log messages for as long as the returned object has not been stopped, useful for testing log messages.
*/
capture(level = this.level) {
if (this._capture !== undefined)
throw new Error('Log messages are already being captured');
const original = this.level;
this.level = level;
this._capture = new CapturedLogs(() => {
this.level = original;
this._capture = undefined;
});
return this._capture;
}
/**
* Create a child logger that will include context information with every log message.
*/
child(context) {
return new ChildLogger(this, context);
}
/**
* Log formatter with color highlighting.
*/
static colorFormatter(data) {
const formatted = Logger.stringFormatter(data);
if (data.level === 'error' || data.level === 'fatal')
return chalk.red(formatted);
if (data.level === 'warn')
return chalk.yellow(formatted);
return formatted;
}
/**
* Log `debug` message.
*/
debug(msg, context) {
if (this._level >= LEVEL.debug)
this._log('debug', msg, context);
}
/**
* Log formatter without color highlighting.
*/
static stringFormatter(data) {
if (data.requestId !== undefined)
return `[${data.time}] [${data.level}] [${data.requestId}] ${data.msg}\n`;
return `[${data.time}] [${data.level}] ${data.msg}\n`;
}
/**
* Log formatter for systemd.
*/
static systemdFormatter(data) {
if (data.requestId === undefined)
return `<${LEVEL[data.level]}>[${data.level.substring(0, 1)}] ${data.msg}\n`;
return `<${LEVEL[data.level]}>[${data.level.substring(0, 1)}] [${data.requestId}] ${data.msg}\n`;
}
/**
* Log `error` message.
*/
error(msg, context) {
if (this._level >= LEVEL.error)
this._log('error', msg, context);
}
/**
* Log `fatal` message.
*/
fatal(msg, context) {
if (this._level >= LEVEL.fatal)
this._log('fatal', msg, context);
}
/**
* Log `infor` message.
*/
info(msg, context) {
if (this._level >= LEVEL.info)
this._log('info', msg, context);
}
/**
* JSON log formatter.
*/
static jsonFormatter(data) {
return JSON.stringify(data);
}
/**
* Currently active log level.
*/
get level() {
return Object.keys(LEVEL).find(key => LEVEL[key] === this._level);
}
set level(level) {
assert(LEVEL[level] !== undefined, `Unsupported log level "${level}"`);
this._level = LEVEL[level];
}
/**
* Log `trace` message.
*/
trace(msg, context) {
if (this._level >= LEVEL.trace)
this._log('trace', msg, context);
}
/**
* Log `warn` message.
*/
warn(msg, context) {
if (this._level >= LEVEL.warn)
this._log('warn', msg, context);
}
_log(level, msg, context) {
const data = { ...context, time: new Date().toISOString(), msg, level };
if (this._historySize !== undefined) {
const history = this.history;
history.push(data);
const maxHistorySize = this._historySize;
const historySize = history.length;
if (historySize > maxHistorySize)
history.splice(0, historySize - maxHistorySize);
}
const formatted = this.formatter(data);
if (this._capture === undefined) {
this.destination.write(formatted);
}
else {
this._capture.push(formatted);
}
}
}
/**
* Captured log message class.
*/
class CapturedLogs extends Array {
constructor(cb) {
super();
this._stopped = false;
this._cb = cb;
}
/**
* Stop capturing log messages.
*/
stop() {
if (this._stopped === true)
return;
this._cb();
this._stopped = true;
}
/**
* Turn log messages into a string.
*/
toString() {
return this.join('');
}
}
/**
* Child logger class.
*/
export class ChildLogger {
constructor(parent, context) {
this.parent = parent;
this.context = context;
}
/**
* Log `debug` message.
*/
debug(msg) {
this.parent.debug(msg, this.context);
}
/**
* Log `error` message.
*/
error(msg) {
this.parent.error(msg, this.context);
}
/**
* Log `fatal` message.
*/
fatal(msg) {
this.parent.fatal(msg, this.context);
}
/**
* Log `info` message.
*/
info(msg) {
this.parent.info(msg, this.context);
}
/**
* Log `trace` message.
*/
trace(msg) {
this.parent.trace(msg, this.context);
}
/**
* Log `warn` message.
*/
warn(msg) {
this.parent.warn(msg, this.context);
}
}
//# sourceMappingURL=logger.js.map