const fs = require('fs'); const path = require('path'); // 日志级别枚举 const LOG_LEVELS = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3, }; // 创建logs目录 const logsDir = path.join(__dirname, 'logs'); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir); } // 日志记录器类 class Logger { constructor(level = 'INFO') { this.level = LOG_LEVELS[level.toUpperCase()] || LOG_LEVELS.INFO; this.logFilePath = path.join(logsDir, `server-${new Date().toISOString().split('T')[0]}.log`); } _shouldLog(level) { return LOG_LEVELS[level.toUpperCase()] <= this.level; } _writeLog(level, message, meta = {}) { if (!this._shouldLog(level)) return; const timestamp = new Date().toISOString(); const logEntry = { timestamp, level, message, ...meta, }; // 控制台输出 console.log(`[${timestamp}] [${level}] ${message}`, meta); // 文件输出 try { const logLine = JSON.stringify(logEntry) + '\n'; fs.appendFileSync(this.logFilePath, logLine); } catch (err) { console.error('Failed to write to log file:', err); } } error(message, meta = {}) { this._writeLog('ERROR', message, meta); } warn(message, meta = {}) { this._writeLog('WARN', message, meta); } info(message, meta = {}) { this._writeLog('INFO', message, meta); } debug(message, meta = {}) { this._writeLog('DEBUG', message, meta); } // HTTP请求日志专用方法 http(req, res, startTime, error = null) { const duration = Date.now() - startTime; const logMeta = { method: req.method, url: req.url, statusCode: res.statusCode, duration: `${duration}ms`, userAgent: req.headers['user-agent'], ip: req.ip || req.connection.remoteAddress, ...(error ? { error: error.message || error } : {}) }; const statusCategory = Math.floor(res.statusCode / 100); let level = 'INFO'; if (error || statusCategory >= 5) { level = 'ERROR'; } else if (statusCategory >= 4) { level = 'WARN'; } this._writeLog(level, `HTTP ${req.method} ${req.url} ${res.statusCode} ${duration}ms`, logMeta); } } // 创建全局日志实例 const logger = new Logger(process.env.LOG_LEVEL || 'INFO'); module.exports = { logger, LOG_LEVELS };