UNPKG

cnb-mcp-server

Version:

MCP Server for the cnb API, enabling file operations, repository management, search functionality, and more.

167 lines (166 loc) 5.1 kB
/** * 日志模块,支持将日志写入本地文件 */ import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; // 日志级别 export var LogLevel; (function (LogLevel) { LogLevel["DEBUG"] = "DEBUG"; LogLevel["INFO"] = "INFO"; LogLevel["WARN"] = "WARN"; LogLevel["ERROR"] = "ERROR"; })(LogLevel || (LogLevel = {})); class Logger { _level; _filePath; console; logStream = null; initialized = false; pendingLogs = []; constructor(config) { this._level = config.level; this.console = config.console !== false; this._filePath = config.filePath || path.join(process.cwd(), 'log.txt'); // 不在构造函数中初始化文件,而是在initialize()中执行 } initLogFile() { try { // 关闭现有的流 if (this.logStream) { this.logStream.end(); this.logStream = null; } // 确保目录存在 const dir = path.dirname(this._filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } // 创建写入流 this.logStream = fs.createWriteStream(this._filePath, { flags: 'a' }); // 添加错误处理 this.logStream.on('error', (err) => { console.error(`Log stream error: ${err.message}`); this.logStream = null; }); // 处理待写入的日志 if (this.pendingLogs.length > 0) { this.pendingLogs.forEach(log => { if (this.logStream) { this.logStream.write(log); } }); this.pendingLogs = []; } this.initialized = true; return true; } catch (error) { console.error(`Failed to initialize log file: ${error instanceof Error ? error.message : String(error)}`); return false; } } formatDate() { const date = new Date(); return date.toISOString(); } shouldLog(level) { const levels = Object.values(LogLevel); return levels.indexOf(level) >= levels.indexOf(this._level); } writeLog(level, message, meta) { if (!this.shouldLog(level)) return; const timestamp = this.formatDate(); let logMessage = `[${timestamp}] [${level}] ${message}`; if (meta) { const metaStr = typeof meta === 'object' ? JSON.stringify(meta) : String(meta); logMessage += ` - ${metaStr}`; } // 添加换行符 logMessage += os.EOL; // 输出到控制台 if (this.console) { if (level === LogLevel.ERROR) { console.error(logMessage); } else if (level === LogLevel.WARN) { console.warn(logMessage); } else { console.log(logMessage); } } // 写入文件 if (this.logStream) { this.logStream.write(logMessage); } else if (!this.initialized) { // 如果日志流未初始化,先缓存日志 this.pendingLogs.push(logMessage); // 尝试初始化日志文件 this.initialize(); } else { // 日志流初始化失败但已尝试过,只输出到控制台 console.log(`[Warning] 无法写入日志文件: ${this._filePath}`); } } debug(message, meta) { this.writeLog(LogLevel.DEBUG, message, meta); } info(message, meta) { this.writeLog(LogLevel.INFO, message, meta); } warn(message, meta) { this.writeLog(LogLevel.WARN, message, meta); } error(message, meta) { this.writeLog(LogLevel.ERROR, message, meta); } close() { if (this.logStream) { this.logStream.end(); this.logStream = null; } this.initialized = false; } /** * 重新初始化日志文件,确保在程序启动时正确创建 */ initialize() { this.close(); const success = this.initLogFile(); if (success) { this.info(`Logger initialized with file: ${this._filePath}`); } else { console.error(`Failed to initialize logger with file: ${this._filePath}`); } return success; } // Getter和Setter get level() { return this._level; } set level(value) { this._level = value; } get filePath() { return this._filePath; } set filePath(value) { this._filePath = value; this.initLogFile(); // 重新初始化日志文件 } } // 默认日志实例 const defaultLogger = new Logger({ level: LogLevel.DEBUG, // 改为DEBUG级别方便调试 console: true, filePath: path.join(process.cwd(), 'log.txt') }); export { Logger, defaultLogger };