type LogLevel = 'debug' | 'info' | 'warn' | 'error';
export class Logger {
private static instance: Logger;
private logLevel: LogLevel;
private constructor() {
this.logLevel = (process.env.LOG_LEVEL as LogLevel) || 'info';
}
public static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
private shouldLog(level: LogLevel): boolean {
const levels: Record<LogLevel, number> = {
debug: 0,
info: 1,
warn: 2,
error: 3,
};
return levels[level] >= levels[this.logLevel];
}
private formatMessage(level: LogLevel, message: string, data?: any): string {
const timestamp = new Date().toISOString();
const dataStr = data ? ` ${JSON.stringify(data)}` : '';
return `[${timestamp}] [${level.toUpperCase()}] ${message}${dataStr}`;
}
public debug(message: string, data?: any): void {
if (this.shouldLog('debug')) {
console.error(this.formatMessage('debug', message, data));
}
}
public info(message: string, data?: any): void {
if (this.shouldLog('info')) {
console.log(this.formatMessage('info', message, data));
}
}
public warn(message: string, data?: any): void {
if (this.shouldLog('warn')) {
console.warn(this.formatMessage('warn', message, data));
}
}
public error(message: string, error?: any): void {
if (this.shouldLog('error')) {
console.error(this.formatMessage('error', message));
if (error && error.stack) {
console.error(error.stack);
}
}
}
}