/** * 日志工具 * 统一输出 [INFO] / [WARN] / [ERROR] + 时间戳 * 同时写入 logs/ 目录下的日期文件 */ const fs = require('fs'); const path = require('path'); const config = require('../config'); // 确保日志目录存在 const logDir = path.resolve(config.dirs.logs); if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } // 今日日志文件 const today = new Date().toISOString().slice(0, 10); const logFile = path.join(logDir, `${today}.log`); /** * 写入文件(异步追加) */ function writeToFile(message) { try { fs.appendFileSync(logFile, message + '\n', 'utf-8'); } catch (err) { // 日志写入失败不应影响主流程,静默处理 console.error(`[LOGGER] 写入日志文件失败: ${err.message}`); } } /** * 获取当前时间戳字符串 */ function timestamp() { const now = new Date(); const pad = (n) => String(n).padStart(2, '0'); return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ` + `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; } /** * 格式化日志行 */ function format(level, message) { return `[${level}] ${timestamp()} ${message}`; } const logger = { info(message) { const line = format('INFO', message); console.log(line); writeToFile(line); }, warn(message) { const line = format('WARN', message); console.warn(line); writeToFile(line); }, error(message) { const line = format('ERROR', message); console.error(line); writeToFile(line); }, /** * 打印空行分隔 */ divider() { const line = '─'.repeat(60); console.log(line); writeToFile(line); }, }; module.exports = logger;