/** * TASKMATE - Logger * ================= * Einfaches Logging mit Datei-Ausgabe */ const fs = require('fs'); const path = require('path'); const LOG_DIR = process.env.LOG_DIR || path.join(__dirname, '..', 'logs'); const LOG_FILE = path.join(LOG_DIR, 'app.log'); // Log-Verzeichnis erstellen falls nicht vorhanden if (!fs.existsSync(LOG_DIR)) { fs.mkdirSync(LOG_DIR, { recursive: true }); } /** * Log-Level */ const LEVELS = { ERROR: 'ERROR', WARN: 'WARN', INFO: 'INFO', DEBUG: 'DEBUG' }; /** * Timestamp formatieren */ function getTimestamp() { return new Date().toISOString(); } /** * Log-Nachricht schreiben */ function log(level, message, meta = {}) { const timestamp = getTimestamp(); const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : ''; const logLine = `[${timestamp}] [${level}] ${message}${metaStr}`; // Konsole if (level === LEVELS.ERROR) { console.error(logLine); } else if (level === LEVELS.WARN) { console.warn(logLine); } else { console.log(logLine); } // Datei (async, non-blocking) fs.appendFile(LOG_FILE, logLine + '\n', (err) => { if (err) console.error('Log-Datei Fehler:', err); }); } /** * Log-Rotation (alte Logs löschen) */ function rotateLogsIfNeeded() { try { const stats = fs.statSync(LOG_FILE); const maxSize = 10 * 1024 * 1024; // 10 MB if (stats.size > maxSize) { const archiveName = `app.${Date.now()}.log`; fs.renameSync(LOG_FILE, path.join(LOG_DIR, archiveName)); // Alte Archive löschen (behalte nur die letzten 5) const files = fs.readdirSync(LOG_DIR) .filter(f => f.startsWith('app.') && f.endsWith('.log') && f !== 'app.log') .sort() .reverse(); files.slice(5).forEach(f => { fs.unlinkSync(path.join(LOG_DIR, f)); }); } } catch (err) { // Datei existiert noch nicht, ignorieren } } // Log-Rotation beim Start und alle 6 Stunden prüfen rotateLogsIfNeeded(); setInterval(rotateLogsIfNeeded, 6 * 60 * 60 * 1000); module.exports = { error: (message, meta) => log(LEVELS.ERROR, message, meta), warn: (message, meta) => log(LEVELS.WARN, message, meta), info: (message, meta) => log(LEVELS.INFO, message, meta), debug: (message, meta) => log(LEVELS.DEBUG, message, meta) };