const fs = require('fs'); // Persistenter Pfad (selbes Volume wie die DB), übersteht Container-Neustarts const LOG_FILE = process.env.CONSOLE_LOG_FILE || '/data/app-console.log'; const MAX_AGE_MS = 24 * 60 * 60 * 1000; const origLog = console.log.bind(console); const origError = console.error.bind(console); const origWarn = console.warn.bind(console); function stringifyArg(a) { if (typeof a === 'string') return a; if (a instanceof Error) return a.stack || a.message; try { return JSON.stringify(a); } catch { return String(a); } } function localTimestamp() { const d = new Date(); const pad = (n, len=2) => String(n).padStart(len, '0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(),3)}`; } function appendLine(level, args) { try { const msg = args.map(stringifyArg).join(' '); fs.appendFileSync(LOG_FILE, `[${localTimestamp()}] [${level}] ${msg}\n`); } catch { // Darf niemals die eigentliche Konsolen-Ausgabe verhindern } } // Entfernt Zeilen, die älter als MAX_AGE_MS sind. Zeilen ohne erkennbaren // Zeitstempel (z.B. Fortsetzungszeilen eines mehrzeiligen Stacktraces) werden // bewusst behalten, um nichts mittendrin abzuschneiden. function pruneOldLines() { try { if (!fs.existsSync(LOG_FILE)) return; const content = fs.readFileSync(LOG_FILE, 'utf8'); const cutoff = Date.now() - MAX_AGE_MS; const lines = content.split('\n').filter(line => { const m = line.match(/^\[([^\]]+)\]/); if (!m) return true; const t = new Date(m[1].replace(' ', 'T')).getTime(); return Number.isNaN(t) || t >= cutoff; }); fs.writeFileSync(LOG_FILE, lines.join('\n')); } catch (e) { origError('Konsolen-Log-Aufräumen fehlgeschlagen:', e.message); } } function installConsoleCapture() { console.log = (...args) => { origLog(...args); appendLine('LOG', args); }; console.error = (...args) => { origError(...args); appendLine('ERROR', args); }; console.warn = (...args) => { origWarn(...args); appendLine('WARN', args); }; pruneOldLines(); // einmal direkt beim Start setInterval(pruneOldLines, 60 * 60 * 1000); // danach stündlich } function getLogFilePath() { return LOG_FILE; } module.exports = { installConsoleCapture, getLogFilePath, pruneOldLines };