const winston = require('winston'); const path = require('path'); const fs = require('fs'); // Create logs directory if it doesn't exist const logsDir = path.join(__dirname, '../logs'); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir); } // Define log format const logFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.errors({ stack: true }), winston.format.splat(), winston.format.json() ); // Console format for development const consoleFormat = winston.format.combine( winston.format.colorize(), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.printf(({ level, message, timestamp, ...meta }) => { return `${timestamp} [${level}]: ${message} ${Object.keys(meta).length ? JSON.stringify(meta, null, 2) : ''}`; }) ); // Create the logger const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: logFormat, transports: [ // Write all logs to combined.log new winston.transports.File({ filename: path.join(logsDir, 'combined.log'), maxsize: 5242880, // 5MB maxFiles: 5 }), // Write error logs to error.log new winston.transports.File({ filename: path.join(logsDir, 'error.log'), level: 'error', maxsize: 5242880, // 5MB maxFiles: 5 }) ], // Handle exceptions and rejections exceptionHandlers: [ new winston.transports.File({ filename: path.join(logsDir, 'exceptions.log') }) ], rejectionHandlers: [ new winston.transports.File({ filename: path.join(logsDir, 'rejections.log') }) ] }); // Add console transport in development if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: consoleFormat })); } module.exports = logger;