// src/utils/logger.js // 统一日志工具 // 支持开发环境或显式开启调试模式 // 生产环境下可以通过设置 REACT_APP_ENABLE_DEBUG=true 来开启调试日志 const isDevelopment = process.env.NODE_ENV === 'development' || process.env.REACT_APP_ENABLE_DEBUG === 'true'; // ========== 日志限流配置 ========== const LOG_THROTTLE_TIME = 1000; // 1秒内相同日志只输出一次 const recentLogs = new Map(); // 日志缓存,用于去重 const MAX_CACHE_SIZE = 100; // 最大缓存数量 /** * 生成日志的唯一键 */ function getLogKey(component, message) { return `${component}:${message}`; } /** * 检查是否应该输出日志(限流检查) */ function shouldLog(component, message) { const key = getLogKey(component, message); const now = Date.now(); const lastLog = recentLogs.get(key); // 如果1秒内已经输出过相同日志,跳过 if (lastLog && now - lastLog < LOG_THROTTLE_TIME) { return false; } // 记录日志时间 recentLogs.set(key, now); // 限制缓存大小,避免内存泄漏 if (recentLogs.size > MAX_CACHE_SIZE) { const oldestKey = recentLogs.keys().next().value; recentLogs.delete(oldestKey); } return true; } /** * 统一日志工具 * 开发环境:输出详细日志 * 生产环境:仅输出错误日志 */ export const logger = { /** * API 相关日志 */ api: { /** * 记录 API 请求 * @param {string} method - 请求方法 (GET, POST, etc.) * @param {string} url - 请求 URL * @param {object} data - 请求参数/body */ request: (method, url, data = null) => { if (isDevelopment && shouldLog('API', `${method} ${url}`)) { console.group(`🌐 API Request: ${method} ${url}`); console.log('Timestamp:', new Date().toISOString()); if (data) console.log('Data:', data); console.groupEnd(); } }, /** * 记录 API 响应成功 * @param {string} method - 请求方法 * @param {string} url - 请求 URL * @param {number} status - HTTP 状态码 * @param {any} data - 响应数据 */ response: (method, url, status, data) => { if (isDevelopment && shouldLog('API', `${method} ${url} ${status}`)) { console.group(`✅ API Response: ${method} ${url}`); console.log('Status:', status); console.log('Data:', data); console.log('Timestamp:', new Date().toISOString()); console.groupEnd(); } }, /** * 记录 API 错误 * @param {string} method - 请求方法 * @param {string} url - 请求 URL * @param {Error|any} error - 错误对象 * @param {object} requestData - 请求参数(可选) */ error: (method, url, error, requestData = null) => { // API 错误始终输出,不做限流 console.group(`❌ API Error: ${method} ${url}`); console.error('Error:', error); console.error('Message:', error?.message || error); if (error?.response) { console.error('Response Status:', error.response.status); console.error('Response Data:', error.response.data); } if (requestData) console.error('Request Data:', requestData); console.error('Timestamp:', new Date().toISOString()); if (error?.stack) console.error('Stack:', error.stack); console.groupEnd(); } }, /** * 组件错误日志 * @param {string} component - 组件名称 * @param {string} method - 方法名称 * @param {Error|any} error - 错误对象 * @param {object} context - 上下文信息(可选) */ error: (component, method, error, context = {}) => { // 错误日志始终输出,不做限流 console.group(`🔴 Error in ${component}.${method}`); console.error('Error:', error); console.error('Message:', error?.message || error); if (Object.keys(context).length > 0) { console.error('Context:', context); } console.error('Timestamp:', new Date().toISOString()); if (error?.stack) console.error('Stack:', error.stack); console.groupEnd(); }, /** * 警告日志 * @param {string} component - 组件名称 * @param {string} message - 警告信息 * @param {object} data - 相关数据(可选) */ warn: (component, message, data = {}) => { if (isDevelopment && shouldLog(component, message)) { console.group(`⚠️ Warning: ${component}`); console.warn('Message:', message); if (Object.keys(data).length > 0) { console.warn('Data:', data); } console.warn('Timestamp:', new Date().toISOString()); console.groupEnd(); } }, /** * 调试日志(仅开发环境) * @param {string} component - 组件名称 * @param {string} message - 调试信息 * @param {object} data - 相关数据(可选) */ debug: (component, message, data = {}) => { if (isDevelopment && shouldLog(component, message)) { console.group(`🐛 Debug: ${component}`); console.log('Message:', message); if (Object.keys(data).length > 0) { console.log('Data:', data); } console.log('Timestamp:', new Date().toISOString()); console.groupEnd(); } }, /** * 信息日志(仅开发环境) * @param {string} component - 组件名称 * @param {string} message - 信息内容 * @param {object} data - 相关数据(可选) */ info: (component, message, data = {}) => { if (isDevelopment && shouldLog(component, message)) { console.group(`ℹ️ Info: ${component}`); console.log('Message:', message); if (Object.keys(data).length > 0) { console.log('Data:', data); } console.log('Timestamp:', new Date().toISOString()); console.groupEnd(); } } }; export default logger;