const BaseService = require('./BaseService'); const cron = require('node-cron'); const os = require('os'); const fs = require('fs'); const path = require('path'); const ip = require('ip'); const si = require('systeminformation'); const fetch = require('node-fetch'); const packageJson = require('../package.json'); class ReportManagerService extends BaseService { constructor() { // Configuration par défaut const defaultConfig = { enabled: 'off', endpoint: 'https://cdn-apollon-p198-61m1.dinawo.fr/api/report/receive', cronSchedule: '0 0 * * *' // Par défaut, une fois par jour à minuit }; super('reportManager', defaultConfig); this.job = null; } async _startImplementation() { if (this.job) { return; } // Valider le cron schedule const schedule = this.config.cronSchedule || this.defaultConfig.cronSchedule; if (!cron.validate(schedule)) { throw new Error(`Schedule cron invalide: ${schedule}`); } this.job = cron.schedule(schedule, () => this.generateAndSendReport()); this.logger.info(`Service de rapport programmé avec le planning: ${schedule}`); } async _stopImplementation() { if (this.job) { this.job.stop(); this.job = null; } } formatUptime(uptime) { const days = Math.floor(uptime / (24 * 60 * 60)); uptime %= (24 * 60 * 60); const hours = Math.floor(uptime / (60 * 60)); uptime %= (60 * 60); const minutes = Math.floor(uptime / 60); return `${days}d ${hours}h ${minutes}m`; } async getInternalErrors() { const date = new Date(); date.setDate(date.getDate() - 1); const previousDate = date.toISOString().split('T')[0]; const logFile = path.join(__dirname, '..', 'logs', `log-${previousDate}.log`); try { const logs = fs.readFileSync(logFile, 'utf-8'); return logs.split('\n').filter(line => /\[38;5;9mInternal-Error/.test(line)); } catch (err) { this.logger.error('Erreur lors de la lecture des logs:', err); return []; } } async generateReport() { try { const internalErrors = await this.getInternalErrors(); if (internalErrors.length === 0) { this.logger.info('Pas d\'erreurs internes dans les logs d\'hier. Pas de rapport généré.'); return null; } const loadavg = os.loadavg().map(load => (load / os.cpus().length) * 100); const osInfo = { type: os.type(), platform: os.platform(), arch: os.arch(), release: os.release(), uptime: this.formatUptime(os.uptime()), loadavg: loadavg }; const networkInterfaces = os.networkInterfaces(); const diskUsage = await si.fsSize(); const cpuTemperature = await si.cpuTemperature(); const userInfo = os.userInfo(); const systemInfo = { memoryInfo: ((os.totalmem() - os.freemem()) / os.totalmem() * 100).toFixed(2), cpuInfo: (os.cpus().length / os.cpus().length * 100).toFixed(2), diskInfo: diskUsage.map(disk => ({ fs: disk.fs, type: disk.type, size: disk.size, used: disk.used, available: disk.available, use: disk.use })), ipAddress: ip.address(), cdnVersion: packageJson.version, osInfo: osInfo, userInfo: { username: userInfo.username, homedir: userInfo.homedir, shell: userInfo.shell }, errors: internalErrors, networkInterfaces: networkInterfaces, serverUptime: os.uptime(), systemLoad: loadavg, cpuTemperature: cpuTemperature }; const reportDate = new Date(); reportDate.setDate(reportDate.getDate() - 1); const reportFileName = `report_${reportDate.toISOString().split('T')[0]}_${ip.address()}.json`; // Sauvegarder le rapport localement const reportDir = path.join(__dirname, '..', 'report'); if (!fs.existsSync(reportDir)) { fs.mkdirSync(reportDir, { recursive: true }); } fs.writeFileSync( path.join(reportDir, reportFileName), JSON.stringify(systemInfo, null, 2) ); return systemInfo; } catch (error) { this.logger.error('Erreur lors de la génération du rapport:', error); throw error; } } async generateAndSendReport() { try { const report = await this.generateReport(); if (!report) { return; } this.logger.info("Envoi du rapport..."); const response = await fetch(this.config.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(report) }); if (!response.ok) { throw new Error(`Erreur HTTP! statut: ${response.status}`); } const responseData = await response.json(); this.logger.info('Rapport envoyé avec succès. Réponse:', responseData); return responseData; } catch (error) { this.logger.error('Échec de l\'envoi du rapport:', error); throw error; } } // Méthode pour forcer l'envoi d'un rapport immédiatement async forceSendReport() { return this.generateAndSendReport(); } } module.exports = new ReportManagerService();