import AsyncStorage from '@/utils/kvStore'; interface LogEntry { id: string; timestamp: number; level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'; message: string; data?: any; } class Logger { private static instance: Logger; private readonly maxLogs = 1000; // 最多保存1000条日志 private readonly storageKey = '@app_logs'; static getInstance(): Logger { if (!Logger.instance) { Logger.instance = new Logger(); } return Logger.instance; } private async getLogs(): Promise { try { const logsJson = await AsyncStorage.getItem(this.storageKey); return logsJson ? JSON.parse(logsJson) : []; } catch (error) { console.error('Failed to get logs from storage:', error); return []; } } private async saveLogs(logs: LogEntry[]): Promise { try { // 只保留最新的maxLogs条日志 const trimmedLogs = logs.slice(-this.maxLogs); await AsyncStorage.setItem(this.storageKey, JSON.stringify(trimmedLogs)); } catch (error) { console.error('Failed to save logs to storage:', error); } } private async addLog(level: LogEntry['level'], message: string, data?: any): Promise { // 安全地处理数据,避免循环引用 let safeData = data; if (data && typeof data === 'object') { try { // 对于非 ERROR 级别的日志,也进行安全序列化 if (data instanceof Error) { safeData = { name: data.name, message: data.message, stack: data.stack }; } else { // 使用 JSON.stringify 的 replacer 函数处理循环引用 safeData = JSON.parse(JSON.stringify(data, (key, value) => { if (typeof value === 'object' && value !== null) { if (value.constructor === Object || Array.isArray(value)) { return value; } // 对于其他对象类型,转换为字符串表示 return value.toString ? value.toString() : '[Object]'; } return value; })); } } catch (serializeError) { // 如果序列化失败,只保存基本信息 safeData = { error: 'Failed to serialize data', type: typeof data, toString: data.toString ? data.toString() : 'N/A' }; } } const logEntry: LogEntry = { id: Date.now().toString() + Math.random().toString(36).substr(2, 9), timestamp: Date.now(), level, message, data: safeData }; // 同时在控制台输出 - 使用原生 console 方法避免循环调用 try { const logMethod = level === 'ERROR' ? console.error : level === 'WARN' ? console.warn : level === 'INFO' ? console.info : console.log; logMethod(`[${level}] ${message}`, safeData); } catch (consoleError) { // 如果控制台输出失败,使用最基本的 console.log console.log(`[${level}] ${message}`, typeof safeData === 'string' ? safeData : 'Object data'); } try { const logs = await this.getLogs(); logs.push(logEntry); await this.saveLogs(logs); } catch (error) { // 使用原生 console.error 避免循环调用 console.error('Failed to add log:', error); } } async debug(message: string, data?: any): Promise { await this.addLog('DEBUG', message, data); } async info(message: string, data?: any): Promise { await this.addLog('INFO', message, data); } async warn(message: string, data?: any): Promise { await this.addLog('WARN', message, data); } async error(message: string, data?: any): Promise { // addLog 方法已经包含了安全的数据处理逻辑 await this.addLog('ERROR', message, data); } async getAllLogs(): Promise { return await this.getLogs(); } async clearLogs(): Promise { try { await AsyncStorage.removeItem(this.storageKey); } catch (error) { console.error('Failed to clear logs:', error); } } async exportLogs(): Promise { const logs = await this.getLogs(); return JSON.stringify(logs, null, 2); } } // 导出全局日志实例和便捷函数 export const logger = Logger.getInstance(); // 便捷的全局日志函数 export const log = { debug: (message: string, data?: any) => logger.debug(message, data), info: (message: string, data?: any) => logger.info(message, data), warn: (message: string, data?: any) => logger.warn(message, data), error: (message: string, data?: any) => logger.error(message, data), }; export type { LogEntry };