Files
vf_react/src/utils/logger.js

188 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;