2025-11-04 21:51:05 +00:00
|
|
|
|
const fs = require('fs');
|
|
|
|
|
|
const path = require('path');
|
|
|
|
|
|
// Создать директорию для логов если её нет
|
|
|
|
|
|
const logsDir = path.join(__dirname, '../logs');
|
|
|
|
|
|
if (!fs.existsSync(logsDir)) {
|
|
|
|
|
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 20:13:22 +00:00
|
|
|
|
const getDatePrefix = () => {
|
|
|
|
|
|
return new Date().toISOString().slice(0, 10);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const appendLog = (fileName, message) => {
|
|
|
|
|
|
const filePath = path.join(logsDir, fileName);
|
|
|
|
|
|
fs.appendFile(filePath, `${message}\n`, (err) => {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
console.error('Ошибка записи в лог файл:', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-04 21:51:05 +00:00
|
|
|
|
// Функция для логирования
|
|
|
|
|
|
const log = (level, message, data = {}) => {
|
|
|
|
|
|
const timestamp = new Date().toISOString();
|
|
|
|
|
|
const logMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
2025-11-10 20:13:22 +00:00
|
|
|
|
const serializedData = Object.keys(data).length ? ` ${JSON.stringify(data)}` : '';
|
|
|
|
|
|
const fullMessage = `${logMessage}${serializedData}`;
|
2025-11-04 21:51:05 +00:00
|
|
|
|
|
|
|
|
|
|
// Логирование в консоль
|
|
|
|
|
|
if (level === 'error') {
|
|
|
|
|
|
console.error(logMessage, data);
|
|
|
|
|
|
} else if (level === 'warn') {
|
|
|
|
|
|
console.warn(logMessage, data);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log(logMessage, data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 20:13:22 +00:00
|
|
|
|
const fileName = `${level}-${getDatePrefix()}.log`;
|
|
|
|
|
|
appendLog(fileName, fullMessage);
|
2025-11-04 21:51:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 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'
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-04 22:41:35 +00:00
|
|
|
|
// Пропустить логирование для публичных роутов (health, корневой роут)
|
|
|
|
|
|
if (req.path === '/health' || req.path === '/') {
|
|
|
|
|
|
// Логировать только ошибки для публичных роутов
|
|
|
|
|
|
if (res.statusCode >= 400) {
|
|
|
|
|
|
log('error', 'Request failed', logData);
|
|
|
|
|
|
}
|
|
|
|
|
|
return; // Не логировать успешные запросы к публичным роутам
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-04 21:51:05 +00:00
|
|
|
|
if (res.statusCode >= 400) {
|
|
|
|
|
|
log('error', 'Request failed', logData);
|
2025-11-04 22:41:35 +00:00
|
|
|
|
} else if (res.statusCode >= 300 && res.statusCode !== 304) {
|
|
|
|
|
|
// 304 - это нормально (кеш), не логируем
|
2025-11-04 21:51:05 +00:00
|
|
|
|
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 можно отправить уведомление
|
2025-11-10 20:13:22 +00:00
|
|
|
|
const securityMessage = `[${new Date().toISOString()}] [SECURITY] ${type}: ${JSON.stringify(securityData)}`;
|
|
|
|
|
|
appendLog(`security-${getDatePrefix()}.log`, securityMessage);
|
2025-11-04 21:51:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
|
log,
|
|
|
|
|
|
requestLogger,
|
|
|
|
|
|
logSecurityEvent
|
|
|
|
|
|
};
|
|
|
|
|
|
|