logger.ts•2.22 kB
import * as fs from 'fs';
import * as path from 'path';
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
export class Logger {
private level: LogLevel;
private logFile?: string;
private logStream?: fs.WriteStream;
private readonly levelPriority: Record<LogLevel, number> = {
debug: 0,
info: 1,
warn: 2,
error: 3
};
constructor(level: LogLevel = 'info', logFile?: string) {
this.level = level;
if (logFile) {
this.logFile = logFile;
this.initLogFile();
}
}
private initLogFile() {
if (this.logFile) {
const logDir = path.dirname(this.logFile);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
this.logStream = fs.createWriteStream(this.logFile, {
flags: 'a',
encoding: 'utf-8'
});
}
}
private shouldLog(level: LogLevel): boolean {
return this.levelPriority[level] >= this.levelPriority[this.level];
}
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}`;
}
private writeLog(formattedMessage: string) {
console.error(formattedMessage);
if (this.logStream) {
this.logStream.write(formattedMessage + '\n');
}
}
debug(message: string, data?: any) {
if (this.shouldLog('debug')) {
this.writeLog(this.formatMessage('debug', message, data));
}
}
info(message: string, data?: any) {
if (this.shouldLog('info')) {
this.writeLog(this.formatMessage('info', message, data));
}
}
warn(message: string, data?: any) {
if (this.shouldLog('warn')) {
this.writeLog(this.formatMessage('warn', message, data));
}
}
error(message: string, data?: any) {
if (this.shouldLog('error')) {
this.writeLog(this.formatMessage('error', message, data));
}
}
setLevel(level: LogLevel) {
this.level = level;
}
close() {
if (this.logStream) {
this.logStream.end();
this.logStream = undefined;
}
}
}