import winston from 'winston';
// Create log format
const logFormat = winston.format.combine(
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}),
winston.format.errors({ stack: true }),
winston.format.json()
);
// Create console format
const consoleFormat = winston.format.combine(
winston.format.colorize(),
winston.format.timestamp({
format: 'HH:mm:ss'
}),
winston.format.printf(({ timestamp, level, message, ...meta }) => {
let metaStr = '';
if (Object.keys(meta).length > 0) {
try {
// Safely serialize meta object, avoid circular references
metaStr = JSON.stringify(meta, (key, value) => {
// Filter out properties that may cause circular references
if (key === 'socket' || key === 'parser' || key === 'response' || key === 'request' || key === 'config') {
return '[Circular Reference]';
}
return value;
}, 2);
} catch (err) {
// If serialization fails, just log basic info
metaStr = `[Meta serialization failed: ${err.message}]`;
}
}
return `${timestamp} [${level}]: ${message} ${metaStr}`;
})
);
// Create logger instance
const createLogger = () => {
const transports = [
// Console output
new winston.transports.Console({
format: consoleFormat
})
];
// Try to add file output, fallback to console only if fails
try {
// Ensure logs directory exists
const fs = require('fs');
const path = require('path');
const logsDir = path.join(process.cwd(), 'logs');
if (!fs.existsSync(logsDir)) {
fs.mkdirSync(logsDir, { recursive: true });
}
// File output - error logs
transports.push(new winston.transports.File({
filename: path.join(logsDir, 'error.log'),
level: 'error',
maxsize: 5242880, // 5MB
maxFiles: 5
}));
// File output - all logs
transports.push(new winston.transports.File({
filename: path.join(logsDir, 'combined.log'),
maxsize: 5242880, // 5MB
maxFiles: 5
}));
} catch (error) {
console.warn('Warning: Could not create log files, using console only:', error.message);
}
return winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: logFormat,
transports
});
};
export const logger = createLogger();
// Extra config for development environment
if (process.env.NODE_ENV === 'development') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
export default logger;