UNPKG

cyberbot-core

Version:

cyberbot, 基于napcat-ts, nodejs,轻量qq机器人框架。

173 lines 5.81 kB
import pino from "pino"; import { join } from "path"; import { existsSync, mkdirSync, writeFileSync, readdirSync } from "fs"; // @ts-ignore import * as cron from "node-cron"; // 日志路径 const logPath = join(process.cwd(), "log"); // 确保日志目录存在 if (!existsSync(logPath)) { mkdirSync(logPath, { recursive: true }); } /** * 初始化日志系统 * @param config 应用配置 * @returns 配置好的日志记录器 */ export function initLogger(config) { // 创建Pino日志系统,使用更简单的配置确保稳定性 const loggerOptions = { level: config.logger.level, transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:yyyy-mm-dd HH:MM:ss', ignore: 'pid,hostname', messageFormat: '{level} {time} {msg}' } } }; // 确保Windows环境下正确显示中文 // 这只在启动时执行一次,不会影响性能 if (process.platform === 'win32') { // 设置控制台代码页为UTF-8 try { const { execSync } = require('child_process'); execSync('chcp 65001', { stdio: 'ignore' }); } catch (e) { // 忽略错误 } } // 创建日志记录器 // @ts-ignore - 解决TypeScript类型问题 const baseLogger = pino(loggerOptions); // 增强logger对象,添加文件写入功能 enhanceLogger(baseLogger); // 启动时清理一次过期日志,然后每天定时清理 cleanupOldLogs(config); // 每天凌晨2点执行清理 cron.schedule('0 2 * * *', () => cleanupOldLogs(config)); return baseLogger; } /** * 增强logger对象,添加文件写入功能 * @param logger pino日志记录器实例 */ function enhanceLogger(logger) { // 保存原始方法 const originalInfo = logger.info; const originalError = logger.error; const originalWarn = logger.warn; // 重写info方法 logger.info = function (obj, msg) { try { // 调用原始的info方法 originalInfo.apply(this, [obj, msg]); // 写入到文件 if (typeof obj === 'object' && msg) { writeLogToFile(`${msg} ${JSON.stringify(obj)}`, 'info'); } else if (typeof obj === 'string') { writeLogToFile(obj, 'info'); } } catch (error) { console.error("日志记录错误:", error); } return this; }; // 重写error方法 logger.error = function (obj, msg) { try { // 调用原始的error方法 originalError.apply(this, [obj, msg]); // 写入到文件 if (typeof obj === 'object' && msg) { writeLogToFile(`${msg} ${JSON.stringify(obj)}`, 'error'); } else if (typeof obj === 'string') { writeLogToFile(obj, 'error'); } } catch (error) { console.error("日志记录错误:", error); } return this; }; // 重写warn方法 logger.warn = function (obj, msg) { try { // 调用原始的warn方法 originalWarn.apply(this, [obj, msg]); // 写入到文件 if (typeof obj === 'object' && msg) { writeLogToFile(`${msg} ${JSON.stringify(obj)}`, 'warn'); } else if (typeof obj === 'string') { writeLogToFile(obj, 'warn'); } } catch (error) { console.error("日志记录错误:", error); } return this; }; } /** * 向日志文件写入消息 * @param msg 消息内容 * @param level 日志级别 */ function writeLogToFile(msg, level = 'info') { const now = new Date(); const dateStr = now.toISOString().split('T')[0]; // YYYY-MM-DD格式 const timeStr = now.toLocaleTimeString('zh-CN'); const logLine = `[${level.toUpperCase()}] ${timeStr} ${msg}\n`; try { const logFile = join(logPath, `${dateStr}.log`); // 显式指定UTF-8编码 writeFileSync(logFile, logLine, { flag: 'a', encoding: 'utf8' }); } catch (err) { console.error(`写入日志文件失败: ${err}`); } } /** * 清理过期日志文件 * @param config 应用配置 */ function cleanupOldLogs(config) { try { const logFiles = readdirSync(logPath) .filter(file => file.endsWith('.log') || file.endsWith('.log.gz')) .map(file => ({ name: file, path: join(logPath, file), // 从文件名中提取日期(格式假设为YYYY-MM-DD.log或YYYY-MM-DD.log.gz) date: new Date(file.replace(/\.log(\.gz)?$/, '')) })) .filter(file => !isNaN(file.date.getTime())); // 过滤掉无效日期的文件 // 根据日期进行排序(从新到旧) logFiles.sort((a, b) => b.date.getTime() - a.date.getTime()); // 保留最新的配置中指定天数的日志文件,删除其余的 const filesToKeep = config.logger.maxDays; if (logFiles.length > filesToKeep) { logFiles.slice(filesToKeep).forEach(file => { try { const { unlinkSync } = require('fs'); unlinkSync(file.path); console.log(`已删除过期日志文件: ${file.name}`); } catch (err) { console.error(`删除日志文件失败: ${file.name}`, err); } }); } } catch (err) { console.error('清理日志文件时出错:', err); } } //# sourceMappingURL=logger.js.map