const fs = require('fs'); const path = require('path'); const config = require('../config'); // Создать директорию для логов если её нет const logsDir = path.join(__dirname, '../logs'); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir, { recursive: true }); } // Функция для логирования const log = (level, message, data = {}) => { const timestamp = new Date().toISOString(); const logMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`; // Логирование в консоль if (level === 'error') { console.error(logMessage, data); } else if (level === 'warn') { console.warn(logMessage, data); } else { console.log(logMessage, data); } // Логирование в файл (только в production) if (config.isProduction()) { const logFile = path.join(logsDir, `${level}.log`); const fileMessage = `${logMessage} ${JSON.stringify(data)}\n`; fs.appendFile(logFile, fileMessage, (err) => { if (err) { console.error('Ошибка записи в лог файл:', err); } }); } }; // Middleware для логирования запросов const requestLogger = (req, res, next) => { const start = Date.now(); // Логировать после завершения запроса res.on('finish', () => { const duration = Date.now() - start; const logData = { method: req.method, path: req.path, status: res.statusCode, duration: `${duration}ms`, ip: req.ip, userAgent: req.get('user-agent'), userId: req.user?.id || 'anonymous' }; // Пропустить логирование для публичных роутов (health, корневой роут) if (req.path === '/health' || req.path === '/') { // Логировать только ошибки для публичных роутов if (res.statusCode >= 400) { log('error', 'Request failed', logData); } return; // Не логировать успешные запросы к публичным роутам } if (res.statusCode >= 400) { log('error', 'Request failed', logData); } else if (res.statusCode >= 300 && res.statusCode !== 304) { // 304 - это нормально (кеш), не логируем log('warn', 'Request redirect', logData); } else { log('info', 'Request completed', logData); } }); next(); }; // Логирование подозрительной активности const logSecurityEvent = (type, req, details = {}) => { const securityData = { type, ip: req.ip, userAgent: req.get('user-agent'), path: req.path, method: req.method, userId: req.user?.id || 'anonymous', ...details }; log('warn', 'Security event', securityData); // В production можно отправить уведомление if (config.isProduction()) { const securityLogFile = path.join(logsDir, 'security.log'); const message = `[${new Date().toISOString()}] [SECURITY] ${type}: ${JSON.stringify(securityData)}\n`; fs.appendFile(securityLogFile, message, (err) => { if (err) { console.error('Ошибка записи в security лог:', err); } }); } }; module.exports = { log, requestLogger, logSecurityEvent };