100 lines
2.8 KiB
JavaScript
100 lines
2.8 KiB
JavaScript
|
|
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'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (res.statusCode >= 400) {
|
|||
|
|
log('error', 'Request failed', logData);
|
|||
|
|
} else if (res.statusCode >= 300) {
|
|||
|
|
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
|
|||
|
|
};
|
|||
|
|
|