Files
CDN-APP-INSIDER/config/logs.js
Dinawo 51d11a6c36
Some checks failed
continuous-integration/drone/push Build is failing
Update v1.1.0-beta.1
2024-12-21 18:16:25 +01:00

194 lines
6.4 KiB
JavaScript

const { format } = require('winston');
const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file');
const fs = require('fs');
const path = require('path');
// Configuration des préfixes de logs avec couleurs
const logPrefix = (label) => {
const prefixes = {
'server': '[🖥️ \x1b[32mServer\x1b[0m]',
'client': '[🌐 \x1b[34mClient\x1b[0m]',
'Internal-Server-Error': '[❗️ \x1b[38;5;9mInternal-Error\x1b[0m]',
'Authentification': '[🔒 \x1b[33mAuthentification\x1b[0m]',
'Suspicious Request': '[⚠️ \x1b[38;5;208mSuspicious Request\x1b[0m]',
'API Request': '[⚙️ \x1b[38;5;9mAPI Request\x1b[0m]',
'File System': '[📁 \x1b[36mFile System\x1b[0m]',
'Database': '[🗄️ \x1b[35mDatabase\x1b[0m]'
};
return prefixes[label] || '';
};
// Configuration du transport de fichiers rotatifs
const createDailyRotateFileTransport = () => {
return new DailyRotateFile({
filename: 'logs/log-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
format: format.combine(
format.timestamp(),
format.json()
)
});
};
// Configuration du format de base pour tous les loggers
const createLoggerFormat = (label) => {
return format.combine(
format.label({ label }),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
format.printf(info => {
const { timestamp, label, message } = info;
const prefix = logPrefix(label);
return `${prefix} [\x1b[36m${timestamp}\x1b[0m] ${message}`;
})
);
};
// Création des différents loggers
const createLogger = (label) => {
return winston.createLogger({
format: createLoggerFormat(label),
transports: [
new winston.transports.Console(),
createDailyRotateFileTransport()
]
});
};
// Instanciation des loggers
const logger = createLogger('server');
const clientLogger = createLogger('client');
const ErrorLogger = createLogger('Internal-Server-Error');
const authLogger = createLogger('Authentification');
const suspiciousLogger = createLogger('Suspicious Request');
const apiLogger = createLogger('API Request');
const fileSystemLogger = createLogger('File System');
const databaseLogger = createLogger('Database');
// Fonction utilitaire pour vérifier les chemins
const checkPath = (url, paths) => {
return paths && paths.length > 0 && paths.some(p => url.startsWith(p.trim()));
};
// Middleware principal de logging
const logRequestInfo = (req, res, next) => {
try {
// Lire la configuration
const setup = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'data', 'setup.json'), 'utf-8'))[0];
const logsConfig = setup.logs || { enabled: 'off', level: 'info' };
// Vérifier si les logs sont activés
if (logsConfig.enabled !== 'on') {
return next();
}
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const userAgent = req.headers['user-agent'];
const url = req.originalUrl || req.url;
// Vérifier d'abord includeOnly
if (logsConfig.includeOnly && logsConfig.includeOnly.length > 0) {
const isIncluded = logsConfig.includeOnly.some(p => url.startsWith(p.trim()));
if (!isIncluded) {
return next(); // Ne pas logger si le chemin n'est pas dans includeOnly
}
}
// Ensuite vérifier excludePaths
if (logsConfig.excludePaths && logsConfig.excludePaths.length > 0) {
const isExcluded = logsConfig.excludePaths.some(p => url.startsWith(p.trim()));
if (isExcluded) {
return next(); // Ne pas logger si le chemin est dans excludePaths
}
}
// Sélectionner le logger approprié et le niveau
let selectedLogger = clientLogger;
let logLevel = logsConfig.level || 'info';
if (url.startsWith('/api')) {
selectedLogger = apiLogger;
} else if (url.startsWith('/auth')) {
selectedLogger = authLogger;
}
// Ne logger que si le niveau est activé
if (!logsConfig.levels || logsConfig.levels.includes(logLevel)) {
const logMessage = `[${ip}] - ${userAgent} - ${req.method} ${url}`;
selectedLogger[logLevel](logMessage);
}
} catch (err) {
console.error('Error in logRequestInfo:', err);
}
next();
}
// Middleware spécifique pour les requêtes API
const logApiRequest = (req, res, next) => {
if (!req.originalUrl.startsWith('/api')) {
return next();
}
const start = Date.now();
res.on('finish', () => {
try {
const setup = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'data', 'setup.json'), 'utf-8'))[0];
const logsConfig = setup.logs || { enabled: 'off' };
if (logsConfig.enabled !== 'on' ||
(logsConfig.levels && !logsConfig.levels.includes('info'))) {
return;
}
const duration = Date.now() - start;
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
apiLogger.info(`[${ip}] - ${req.method} ${req.originalUrl} - ${res.statusCode} - ${duration}ms`);
} catch (err) {
ErrorLogger.error(`Error in API logging: ${err.message}`);
}
});
next();
};
// Fonction utilitaire pour logger les erreurs système
const logSystemError = (error, context = '') => {
const errorMessage = `${context ? `[${context}] ` : ''}${error.message}`;
ErrorLogger.error(errorMessage);
if (error.stack) {
ErrorLogger.error(error.stack);
}
};
// Middleware pour logger les erreurs 404
const log404Error = (req, res, next) => {
suspiciousLogger.warn(`404 Not Found: ${req.method} ${req.originalUrl} from IP ${req.ip}`);
next();
};
// Middleware pour logger les erreurs 500
const log500Error = (error, req, res, next) => {
logSystemError(error, '500 Internal Server Error');
next(error);
};
// Export des fonctionnalités
module.exports = {
logger,
clientLogger,
ErrorLogger,
authLogger,
suspiciousLogger,
apiLogger,
fileSystemLogger,
databaseLogger,
logRequestInfo,
logApiRequest,
logSystemError,
log404Error,
log500Error
};