add changes
This commit is contained in:
148
config/logger.js
Normal file
148
config/logger.js
Normal file
@@ -0,0 +1,148 @@
|
||||
const winston = require('winston');
|
||||
const DailyRotateFile = require('winston-daily-rotate-file');
|
||||
const path = require('path');
|
||||
|
||||
// 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(({ timestamp, level, message, stack }) => {
|
||||
return stack
|
||||
? `${timestamp} [${level}]: ${message}\n${stack}`
|
||||
: `${timestamp} [${level}]: ${message}`;
|
||||
})
|
||||
);
|
||||
|
||||
// Create logs directory if it doesn't exist
|
||||
const fs = require('fs');
|
||||
const logsDir = path.join(__dirname, '../logs');
|
||||
if (!fs.existsSync(logsDir)) {
|
||||
fs.mkdirSync(logsDir);
|
||||
}
|
||||
|
||||
// Daily rotate file transport for error logs
|
||||
const errorRotateTransport = new DailyRotateFile({
|
||||
filename: path.join(logsDir, 'error-%DATE%.log'),
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
level: 'error',
|
||||
maxSize: '20m',
|
||||
maxFiles: '14d',
|
||||
format: logFormat
|
||||
});
|
||||
|
||||
// Daily rotate file transport for combined logs
|
||||
const combinedRotateTransport = new DailyRotateFile({
|
||||
filename: path.join(logsDir, 'combined-%DATE%.log'),
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
maxSize: '20m',
|
||||
maxFiles: '30d',
|
||||
format: logFormat
|
||||
});
|
||||
|
||||
// Daily rotate file transport for HTTP logs
|
||||
const httpRotateTransport = new DailyRotateFile({
|
||||
filename: path.join(logsDir, 'http-%DATE%.log'),
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
maxSize: '20m',
|
||||
maxFiles: '7d',
|
||||
format: logFormat
|
||||
});
|
||||
|
||||
// Create the Winston logger
|
||||
const logger = winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
format: logFormat,
|
||||
defaultMeta: { service: 'interview-quiz-api' },
|
||||
transports: [
|
||||
errorRotateTransport,
|
||||
combinedRotateTransport
|
||||
],
|
||||
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
|
||||
}));
|
||||
}
|
||||
|
||||
// HTTP logger for request logging
|
||||
const httpLogger = winston.createLogger({
|
||||
level: 'http',
|
||||
format: logFormat,
|
||||
defaultMeta: { service: 'interview-quiz-api' },
|
||||
transports: [httpRotateTransport]
|
||||
});
|
||||
|
||||
// Stream for Morgan middleware
|
||||
logger.stream = {
|
||||
write: (message) => {
|
||||
httpLogger.http(message.trim());
|
||||
}
|
||||
};
|
||||
|
||||
// Helper functions for structured logging
|
||||
logger.logRequest = (req, message) => {
|
||||
logger.info(message, {
|
||||
method: req.method,
|
||||
url: req.originalUrl,
|
||||
ip: req.ip,
|
||||
userId: req.user?.id,
|
||||
userAgent: req.get('user-agent')
|
||||
});
|
||||
};
|
||||
|
||||
logger.logError = (error, req = null) => {
|
||||
const errorLog = {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
statusCode: error.statusCode || 500
|
||||
};
|
||||
|
||||
if (req) {
|
||||
errorLog.method = req.method;
|
||||
errorLog.url = req.originalUrl;
|
||||
errorLog.ip = req.ip;
|
||||
errorLog.userId = req.user?.id;
|
||||
errorLog.body = req.body;
|
||||
}
|
||||
|
||||
logger.error('Application Error', errorLog);
|
||||
};
|
||||
|
||||
logger.logDatabaseQuery = (query, duration) => {
|
||||
logger.debug('Database Query', {
|
||||
query,
|
||||
duration: `${duration}ms`
|
||||
});
|
||||
};
|
||||
|
||||
logger.logSecurityEvent = (event, req) => {
|
||||
logger.warn('Security Event', {
|
||||
event,
|
||||
method: req.method,
|
||||
url: req.originalUrl,
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent')
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = logger;
|
||||
Reference in New Issue
Block a user