/** * 日志总类,用于记录日志信息 * 支持基于位运算的自定义日志级别控制 */ class Logger { static LOG_HEADER_DEBUG = '[DEBUG]'; static LOG_HEADER_INFO = '[INFO]'; static LOG_HEADER_WARN = '[WARN]'; static LOG_HEADER_ERROR = '[ERROR]'; static LOG_LEVEL_CODE = { none: 0, debug: 1 << 0, // 1 info: 1 << 1, // 2 warn: 1 << 2, // 4 error: 1 << 3, // 8 all: (1 << 4) - 1 // 15 }; constructor() { // 全局默认级别 (默认开启 info, warn, error) this.globalLevel = Logger.LOG_LEVEL_CODE.info | Logger.LOG_LEVEL_CODE.warn | Logger.LOG_LEVEL_CODE.error; // 针对特定插件或模块的配置 // 结构示例: // { // "PluginA": 3, // PluginA 下所有模块掩码为 3 (debug | info) // "PluginB::ModuleX": 8 // 仅 PluginB 下的 ModuleX 掩码为 8 (error) // } this.levelConfig = {}; } /** * 将输入转换为对应的日志级别掩码 * @param {number|string|string[]} levelInput * @returns {number} 掩码 */ _parseLevelInput(levelInput) { if (typeof levelInput === 'number') { return levelInput; } if (typeof levelInput === 'string') { if (Logger.LOG_LEVEL_CODE.hasOwnProperty(levelInput)) { return Logger.LOG_LEVEL_CODE[levelInput]; } // 支持 "debug|info" 这种写法 if (levelInput.includes('|')) { return levelInput.split('|').reduce((mask, l) => mask | (Logger.LOG_LEVEL_CODE[l.trim()] || 0), 0); } console.warn(`[Logger] Unknown log level string: ${levelInput}`); return 0; } if (Array.isArray(levelInput)) { return levelInput.reduce((mask, l) => mask | (Logger.LOG_LEVEL_CODE[l] || 0), 0); } return 0; } /** * 设置日志级别(覆盖模式) * @param {string} target 目标范围,可以是 'Global'、'PluginName' 或 'PluginName::ModuleName' * @param {number|string|string[]} level 输入的级别配置 */ setLevel(target, level) { const mask = this._parseLevelInput(level); if (target === 'Global') { this.globalLevel = mask; console.log(`[Logger] Global log level mask set to: ${mask.toString(2)}`); } else { this.levelConfig[target] = mask; console.log(`[Logger] Log level mask for '${target}' set to: ${mask.toString(2)}`); } } /** * 添加日志级别(增量模式) * @param {string} target * @param {number|string|string[]} level */ addLevel(target, level) { const maskToAdd = this._parseLevelInput(level); let currentMask; if (target === 'Global') { currentMask = this.globalLevel; this.globalLevel = currentMask | maskToAdd; console.log(`[Logger] Added level to Global. New mask: ${this.globalLevel.toString(2)}`); } else { currentMask = this.levelConfig[target] !== undefined ? this.levelConfig[target] : this.globalLevel; this.levelConfig[target] = currentMask | maskToAdd; console.log(`[Logger] Added level to '${target}'. New mask: ${this.levelConfig[target].toString(2)}`); } } /** * 移除日志级别(减量模式) * @param {string} target * @param {number|string|string[]} level */ removeLevel(target, level) { const maskToRemove = this._parseLevelInput(level); let currentMask; if (target === 'Global') { currentMask = this.globalLevel; // 使用 & ~mask 实现移除 this.globalLevel = currentMask & ~maskToRemove; console.log(`[Logger] Removed level from Global. New mask: ${this.globalLevel.toString(2)}`); } else { currentMask = this.levelConfig[target] !== undefined ? this.levelConfig[target] : this.globalLevel; this.levelConfig[target] = currentMask & ~maskToRemove; console.log(`[Logger] Removed level from '${target}'. New mask: ${this.levelConfig[target].toString(2)}`); } } /** * 获取指定上下文的生效日志级别掩码(级联查找) * @param {string} plugin * @param {string} origin (Module) */ _getEffectiveLevelMask(plugin, origin) { // 1. 检查精确匹配 "Plugin::Module" const specificKey = `${plugin}::${origin}`; if (this.levelConfig.hasOwnProperty(specificKey)) { return this.levelConfig[specificKey]; } // 2. 检查插件级匹配 "Plugin" if (this.levelConfig.hasOwnProperty(plugin)) { return this.levelConfig[plugin]; } // 3. 返回全局默认 return this.globalLevel; } log(plugin, origin, type, message, inFile = false) { // 获取当前上下文生效的日志级别掩码 const effectiveMask = this._getEffectiveLevelMask(plugin, origin); // 获取当前日志类型的位码 const typeCode = Logger.LOG_LEVEL_CODE[type]; // 级别筛选:位与运算结果为0则表示该级别未开启 if (typeCode === undefined || (effectiveMask & typeCode) === 0) { return; } const timestamp = new Date().toLocaleTimeString(); // 格式: [12:00:00] [PluginName::ClassName] [INFO]: message const fullMessage = `[${timestamp}] [${plugin}::${origin}] [${type.toUpperCase()}]: ${message}`; // 1. Console Output switch (type) { case 'debug': console.debug(fullMessage); break; case 'info': console.info(fullMessage); break; case 'warn': console.warn(fullMessage); break; case 'error': console.error(fullMessage); break; default: console.log(fullMessage); break; } // 2. File Output (via FilePipe) if (inFile) { // Logger 自身也需要作为系统组件注册,获取写入权限 if (!this.sysBus) { if (window.Amily2Bus && window.Amily2Bus.register) { this.sysBus = window.Amily2Bus.register('SystemLogger'); } } if (this.sysBus && this.sysBus.file) { // 使用注册后的安全接口写入,无需再手动传 'SystemLogger' this.sysBus.file.write('runtime.log', fullMessage + '\n'); } else { // Fallback: 如果总线未就绪,仅在控制台警告一次,避免死循环 if (!this._warned) { console.warn('[Logger] FilePipe system not linked. Log not saved to file.'); this._warned = true; } } } } } // Ensure Amily2Bus namespace exists to prevent crash if loaded out of order window.Amily2Bus = window.Amily2Bus || {}; window.Amily2Bus.Logger = new Logger(); export default Logger;