/** * Logger Utility * Provides structured logging for sync operations */ export enum LogLevel { DEBUG = 'DEBUG', INFO = 'INFO', WARN = 'WARN', ERROR = 'ERROR', } export interface LogContext { syncId?: string; entity?: string; operation?: string; duration?: number; recordCount?: number; [key: string]: any; } /** * Logger class for structured logging */ export class Logger { private context: LogContext; private minLevel: LogLevel; constructor(context: LogContext = {}, minLevel: LogLevel = LogLevel.INFO) { this.context = context; this.minLevel = minLevel; } /** * Create a child logger with additional context */ child(additionalContext: LogContext): Logger { return new Logger({ ...this.context, ...additionalContext }, this.minLevel); } /** * Log debug message */ debug(message: string, data?: any): void { this.log(LogLevel.DEBUG, message, data); } /** * Log info message */ info(message: string, data?: any): void { this.log(LogLevel.INFO, message, data); } /** * Log warning message */ warn(message: string, data?: any): void { this.log(LogLevel.WARN, message, data); } /** * Log error message */ error(message: string, error?: Error | any, data?: any): void { const errorData = { ...data, error: error instanceof Error ? { message: error.message, stack: error.stack, name: error.name, } : error, }; this.log(LogLevel.ERROR, message, errorData); } /** * Internal log method */ private log(level: LogLevel, message: string, data?: any): void { if (!this.shouldLog(level)) { return; } const timestamp = new Date().toISOString(); const contextStr = Object.keys(this.context).length > 0 ? ` [${this.formatContext()}]` : ''; const logMessage = `[${timestamp}] [${level}]${contextStr} ${message}`; switch (level) { case LogLevel.DEBUG: console.debug(logMessage, data || ''); break; case LogLevel.INFO: console.log(logMessage, data || ''); break; case LogLevel.WARN: console.warn(logMessage, data || ''); break; case LogLevel.ERROR: console.error(logMessage, data || ''); break; } } /** * Check if log level should be logged */ private shouldLog(level: LogLevel): boolean { const levels = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR]; const currentIndex = levels.indexOf(this.minLevel); const messageIndex = levels.indexOf(level); return messageIndex >= currentIndex; } /** * Format context for logging */ private formatContext(): string { return Object.entries(this.context) .map(([key, value]) => `${key}=${value}`) .join(', '); } } /** * Create a logger instance */ export function createLogger(context?: LogContext, minLevel?: LogLevel): Logger { return new Logger(context, minLevel); } /** * Default logger instance */ export const logger = new Logger(); export default logger;