export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
interface Logger {
debug(message: string, ...args: unknown[]): void;
info(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
}
class ConsoleLogger implements Logger {
private level: LogLevel;
private readonly levels: Record<LogLevel, number> = {
debug: 0,
info: 1,
warn: 2,
error: 3,
};
constructor(level: LogLevel = 'info') {
this.level = level;
}
private shouldLog(level: LogLevel): boolean {
return this.levels[level] >= this.levels[this.level];
}
private formatMessage(level: LogLevel, message: string): string {
const timestamp = new Date().toISOString();
return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
}
debug(message: string, ...args: unknown[]): void {
if (this.shouldLog('debug')) {
console.debug(this.formatMessage('debug', message), ...args);
}
}
info(message: string, ...args: unknown[]): void {
if (this.shouldLog('info')) {
console.info(this.formatMessage('info', message), ...args);
}
}
warn(message: string, ...args: unknown[]): void {
if (this.shouldLog('warn')) {
console.warn(this.formatMessage('warn', message), ...args);
}
}
error(message: string, ...args: unknown[]): void {
if (this.shouldLog('error')) {
console.error(this.formatMessage('error', message), ...args);
}
}
}
let loggerInstance: ConsoleLogger | null = null;
export function createLogger(level: LogLevel = 'info'): Logger {
if (!loggerInstance) {
loggerInstance = new ConsoleLogger(level);
} else {
// Update level if logger already exists
loggerInstance = new ConsoleLogger(level);
}
return loggerInstance;
}
export function getLogger(): Logger {
if (!loggerInstance) {
loggerInstance = new ConsoleLogger('info');
}
return loggerInstance;
}
export { Logger };