import winston from 'winston'; const { combine, timestamp, printf, colorize, errors } = winston.format; // Custom log format const logFormat = printf(({ level, message, timestamp, stack, ...metadata }) => { let msg = `${timestamp} [${level}] ${message}`; if (stack) { msg += `\n${stack}`; } if (Object.keys(metadata).length > 0) { msg += ` ${JSON.stringify(metadata)}`; } return msg; }); // Create logger instance export const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: combine( errors({ stack: true }), timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), logFormat ), transports: [ // Console transport new winston.transports.Console({ format: combine( colorize(), logFormat ) }), // File transport for errors new winston.transports.File({ filename: 'logs/error.log', level: 'error', maxsize: 10485760, // 10MB maxFiles: 5 }), // File transport for all logs new winston.transports.File({ filename: 'logs/combined.log', maxsize: 10485760, // 10MB maxFiles: 10 }) ], exceptionHandlers: [ new winston.transports.File({ filename: 'logs/exceptions.log' }) ], rejectionHandlers: [ new winston.transports.File({ filename: 'logs/rejections.log' }) ] });