/** * Centralized logger utility for the session recorder * Provides consistent logging across all components */ import { LogLevel } from '../types'; export interface LoggerConfig { level: LogLevel; enabled: boolean; enablePrefix: boolean; prefix: string; } class Logger { private config: LoggerConfig = { level: LogLevel.INFO, enabled: true, enablePrefix: true, prefix: '[SessionRecorder]', }; private componentPrefixes: Map = new Map([ ['ScreenRecorder', '📸'], ['NativeGestureRecorder', '👆'], ['SessionRecorderContext', '🎯'], ['SocketService', '📤'], ['NavigationTracker', '📸'], ['RecorderReactNativeSDK', '📤'], ['DEBUGGER_LIB', '🔍'], ]); /** * Configure the logger * @param config - Logger configuration */ configure(config: Partial): void { this.config = { ...this.config, ...config }; } /** * Set the log level * @param level - Log level to set */ setLevel(level: LogLevel): void { this.config.level = level; } /** * Enable or disable console output * @param enabled - Whether to enable console output */ setConsoleEnabled(enabled: boolean): void { this.config.enabled = enabled; } /** * Add or update a component prefix * @param component - Component name * @param emoji - Emoji prefix for the component */ setComponentPrefix(component: string, emoji: string): void { this.componentPrefixes.set(component, emoji); } /** * Get the formatted prefix for a component * @param component - Component name * @returns Formatted prefix string */ private getPrefix(component: string): string { if (!this.config.enablePrefix) return ''; const emoji = this.componentPrefixes.get(component) || '📝'; return `${this.config.prefix} ${emoji} [${component}]`; } /** * Check if a log level should be output * @param level - Log level to check * @returns True if should output */ private shouldLog(level: LogLevel): boolean { return level >= this.config.level && this.config.enabled; } /** * Format the log message * @param component - Component name * @param level - Log level * @param message - Log message * @param data - Additional data to log * @returns Formatted log message */ private formatMessage( component: string, level: LogLevel, message: string, data?: any ): string { const prefix = this.getPrefix(component); const levelName = LogLevel[level]; let formattedMessage = `${prefix} ${levelName} ${message}`; if (data !== undefined) { formattedMessage += ` ${JSON.stringify(data)}`; } return formattedMessage; } /** * Log a debug message * @param component - Component name * @param message - Log message * @param data - Additional data to log */ debug(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.DEBUG)) return; const formattedMessage = this.formatMessage( component, LogLevel.DEBUG, message, data ); console.log(formattedMessage); } /** * Log an info message * @param component - Component name * @param message - Log message * @param data - Additional data to log */ info(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.INFO)) return; const formattedMessage = this.formatMessage( component, LogLevel.INFO, message, data ); console.log(formattedMessage); } /** * Log a warning message * @param component - Component name * @param message - Log message * @param data - Additional data to log */ warn(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.WARN)) return; const formattedMessage = this.formatMessage( component, LogLevel.WARN, message, data ); console.warn(formattedMessage); } /** * Log an error message * @param component - Component name * @param message - Log message * @param data - Additional data to log */ error(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.ERROR)) return; const formattedMessage = this.formatMessage( component, LogLevel.ERROR, message, data ); console.error(formattedMessage); } /** * Log a success message (info level with success emoji) * @param component - Component name * @param message - Log message * @param data - Additional data to log */ success(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.INFO)) return; const prefix = this.getPrefix(component); const formattedMessage = `${prefix} ✅ ${message}`; let fullMessage = formattedMessage; if (data !== undefined) { fullMessage += ` ${JSON.stringify(data)}`; } console.log(fullMessage); } /** * Log a failure message (error level with failure emoji) * @param component - Component name * @param message - Log message * @param data - Additional data to log */ failure(component: string, message: string, data?: any): void { if (!this.shouldLog(LogLevel.ERROR)) return; const prefix = this.getPrefix(component); const formattedMessage = `${prefix} ❌ ${message}`; let fullMessage = formattedMessage; if (data !== undefined) { fullMessage += ` ${JSON.stringify(data)}`; } console.error(fullMessage); } } // Export a singleton instance export const logger = new Logger(); // Export convenience functions for common use cases export const logDebug = (component: string, message: string, data?: any) => logger.debug(component, message, data); export const logInfo = (component: string, message: string, data?: any) => logger.info(component, message, data); export const logWarn = (component: string, message: string, data?: any) => logger.warn(component, message, data); export const logError = (component: string, message: string, data?: any) => logger.error(component, message, data); export const logSuccess = (component: string, message: string, data?: any) => logger.success(component, message, data); export const logFailure = (component: string, message: string, data?: any) => logger.failure(component, message, data);