import winston from 'winston'; import DailyRotateFile from 'winston-daily-rotate-file'; import chalk from 'chalk'; const { combine, timestamp, printf, colorize, errors, json } = winston.format; // Define log levels const levels = { error: 0, warn: 1, info: 2, http: 3, debug: 4, }; // Colors for different log levels const colors = { error: 'red', warn: 'yellow', info: 'green', http: 'magenta', debug: 'white', }; // Add colors to winston winston.addColors(colors); // Custom log format for console const consoleFormat = printf(({ level, message, timestamp, stack, label }) => { let color; switch (level) { case 'error': color = chalk.red.bold; break; case 'warn': color = chalk.yellow; break; case 'info': color = chalk.green; break; case 'http': color = chalk.magenta; break; case 'debug': color = chalk.blue; break; default: color = chalk.white; } let logMessage = `${chalk.gray(timestamp)} ${color(`[${level.toUpperCase()}]`)}`; if (label) { logMessage += ` ${chalk.cyan(`(${label})`)}`; } logMessage += `: ${message}`; if (stack) { logMessage += `\n${chalk.red(stack)}`; } return logMessage; }); // Custom log format for files const fileFormat = combine( errors({ stack: true }), timestamp(), json() ); // Create transports array const transports = [ new winston.transports.Console({ format: combine( colorize({ level: true }), timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), errors({ stack: true }), consoleFormat ), }), new DailyRotateFile({ filename: 'logs/error-%DATE%.log', datePattern: 'YYYY-MM-DD', zippedArchive: true, maxSize: '20m', maxFiles: '14d', level: 'error', format: fileFormat, }), new DailyRotateFile({ filename: 'logs/combined-%DATE%.log', datePattern: 'YYYY-MM-DD', zippedArchive: true, maxSize: '20m', maxFiles: '14d', format: fileFormat, }), ]; // Create the logger instance const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', levels, format: combine( timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), errors({ stack: true }) ), transports, exitOnError: false, }); // Create a child logger with default metadata export const createLogger = (label: string) => { return logger.child({ label }); }; // Stream for morgan HTTP logging export const httpLogStream = { write: (message: string) => { logger.http(message.trim()); }, }; export default logger;