import { MAX_LOG_MESSAGE_COUNT } from "../consts"; export enum LogLevel { DEBUG = "DEBUG", INFO = "INFO", WARNING = "WARNING", ERROR = "ERROR" } const LOG_LEVEL_ORDER = { [LogLevel.DEBUG]: 0, [LogLevel.INFO]: 1, [LogLevel.WARNING]: 2, [LogLevel.ERROR]: 3 }; export class LogLine { public timestamp = new Date(); public constructor( public level: LogLevel, public message: string ) {} } export class Logger { private readonly messages: LogLine[] = []; private readonly onMessageListeners: ((message: LogLine) => unknown)[] = []; public constructor( ...onMessageListeners: ((message: LogLine) => unknown)[] ) { this.onMessageListeners = onMessageListeners; } public debug(message: string): void { this.pushMessage(message, LogLevel.DEBUG); } public info(message: string): void { this.pushMessage(message, LogLevel.INFO); } public warn(message: string): void { this.pushMessage(message, LogLevel.WARNING); } public error(message: string): void { this.pushMessage(message, LogLevel.ERROR); } public getMessages(mininumSeverity: LogLevel): LogLine[] { return this.messages.filter( (message) => LOG_LEVEL_ORDER[message.level] >= LOG_LEVEL_ORDER[mininumSeverity] ); } public addOnMessageListener(listener: (message: LogLine) => unknown): void { this.onMessageListeners.push(listener); } public removeOnMessageListener( listener: (message: LogLine) => unknown ): void { const index = this.onMessageListeners.indexOf(listener); if (index !== -1) { this.onMessageListeners.splice(index, 1); } } public reset(): void { this.messages.length = 0; this.debug("Logger has been reset"); } private pushMessage(message: string, level: LogLevel): void { const logLine = new LogLine(level, message); this.messages.push(logLine); while (this.messages.length > MAX_LOG_MESSAGE_COUNT) { this.messages.shift(); } this.onMessageListeners.forEach((listener) => { listener(logLine); }); } }