/** * Task 8.1: Standardized Error Logging Utility * Provides consistent error logging across all components */ export class ErrorLogger { constructor(componentName) { this.componentName = componentName; } /** * Log an error with standardized format * @param {string} message - Error message * @param {Object} details - Additional error details * @param {Error} error - Original error object (optional) */ log(message, details = {}, error = null) { const logEntry = { timestamp: new Date().toISOString(), component: this.componentName, level: 'error', message: message, details: details, stack: error?.stack || new Error().stack }; // Log to console with formatting console.error(`[${logEntry.timestamp}] [${logEntry.component}] ERROR:`, message); if (Object.keys(details).length > 0) { console.error('Details:', details); } if (error) { console.error('Original error:', error.message); console.error('Stack trace:', error.stack); } return logEntry; } /** * Log a validation error with expected vs actual schema * @param {string} field - Field that failed validation * @param {*} expected - Expected value/type * @param {*} actual - Actual value/type */ logValidationError(field, expected, actual) { return this.log('Validation Error', { field: field, expected: expected, actual: actual, type: 'validation' }); } /** * Log a warning (non-fatal issue) * @param {string} message - Warning message * @param {Object} details - Additional details */ warn(message, details = {}) { const logEntry = { timestamp: new Date().toISOString(), component: this.componentName, level: 'warning', message: message, details: details }; console.warn(`[${logEntry.timestamp}] [${logEntry.component}] WARNING:`, message); if (Object.keys(details).length > 0) { console.warn('Details:', details); } return logEntry; } /** * Log an info message * @param {string} message - Info message * @param {Object} details - Additional details */ info(message, details = {}) { const logEntry = { timestamp: new Date().toISOString(), component: this.componentName, level: 'info', message: message, details: details }; console.log(`[${logEntry.timestamp}] [${logEntry.component}] INFO:`, message); if (Object.keys(details).length > 0) { console.log('Details:', details); } return logEntry; } } /** * Create a logger instance for a component * @param {string} componentName - Name of the component * @returns {ErrorLogger} Logger instance */ export function createLogger(componentName) { return new ErrorLogger(componentName); } /** * Format validation errors with expected vs actual schema * @param {Array} errors - Array of validation errors * @returns {string} Formatted error message */ export function formatValidationErrors(errors) { if (!errors || errors.length === 0) { return 'No validation errors'; } return errors.map((err, index) => { return `${index + 1}. ${err.field}: Expected ${err.expected}, got ${err.actual}`; }).join('\n'); }