/** * DSS Logger - Structured Logging System * * Provides structured logging with categories and levels for the DSS admin UI. * * Log Categories: * 'storage' - Database operations and data persistence * 'validation' - Validation, analysis, and decision making * 'api' - API calls, webhooks, communication * 'parser' - Data ingestion, parsing, transformation * 'tokens' - Design token flow and distribution * 'transform' - Style-dictionary transformations * 'config' - Theme system and configuration * 'security' - Validation, error detection, security * 'assets' - Asset loading, Figma integration * 'ui' - UI rendering, Storybook output * 'schema' - Schema and structure validation */ const LOG_LEVELS = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, NONE: 4 }; class Logger { constructor(name = 'DSS', level = 'INFO') { this.name = name; this.level = LOG_LEVELS[level] || LOG_LEVELS.INFO; this.logs = []; this.maxLogs = 1000; this.remoteLoggingEnabled = false; } setLevel(level) { this.level = LOG_LEVELS[level] || LOG_LEVELS.INFO; } enableRemoteLogging() { this.remoteLoggingEnabled = true; } _shouldLog(level) { return LOG_LEVELS[level] >= this.level; } _formatMessage(level, category, message, data) { const timestamp = new Date().toISOString(); return { timestamp, level, category, name: this.name, message, data }; } _log(level, category, message, data = null) { if (!this._shouldLog(level)) return; const logEntry = this._formatMessage(level, category, message, data); // Store in memory this.logs.push(logEntry); if (this.logs.length > this.maxLogs) { this.logs.shift(); } const levelIcons = { DEBUG: '[D]', INFO: '[I]', WARN: '[W]', ERROR: '[E]' }; const colors = { DEBUG: 'color: #666; font-style: italic', INFO: 'color: #2196F3; font-weight: bold', WARN: 'color: #FF9800; font-weight: bold', ERROR: 'color: #F44336; font-weight: bold' }; const icon = levelIcons[level] || '[?]'; const prefix = `${icon} [${category}]`; const style = colors[level] || ''; if (data) { console.log(`%c${prefix} ${message}`, style, data); } else { console.log(`%c${prefix} ${message}`, style); } // Remote logging (if enabled) if (this.remoteLoggingEnabled && level === 'ERROR') { this._sendToServer(logEntry); } } async _sendToServer(logEntry) { try { await fetch('/api/logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(logEntry) }); } catch (e) { // Fail silently for logging errors } } /** * DEBUG - Detailed internal information */ debug(category, message, data) { this._log('DEBUG', category, message, data); } /** * INFO - General information */ info(category, message, data) { this._log('INFO', category, message, data); } /** * WARN - Warning, something unusual detected */ warn(category, message, data) { this._log('WARN', category, message, data); } /** * ERROR - Error, something went wrong */ error(category, message, data) { this._log('ERROR', category, message, data); } /** * Get recent log entries */ getRecentLogs(count = 50) { return this.logs.slice(-count); } /** * Clear all logs */ clear() { this.logs = []; } /** * Export logs to file */ export() { const dataStr = JSON.stringify(this.logs, null, 2); const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr); const exportFileDefaultName = `dss-logs-${Date.now()}.json`; const linkElement = document.createElement('a'); linkElement.setAttribute('href', dataUri); linkElement.setAttribute('download', exportFileDefaultName); linkElement.click(); } } /** * DSS Logger singleton */ const logger = new Logger('DSS', 'INFO'); // Set log level from localStorage or URL param const urlParams = new URLSearchParams(window.location.search); const logLevel = urlParams.get('log') || localStorage.getItem('dss_log_level') || 'INFO'; logger.setLevel(logLevel.toUpperCase()); export default logger; export { Logger, LOG_LEVELS };