const fs = require('fs'); const path = require('path'); const { v4: uuid } = require('uuid'); const CONFIG_DIR = path.join(__dirname, '..', 'config'); const LOG_FILE = path.join(CONFIG_DIR, 'request-logs.json'); const TTL_MS = 14 * 24 * 60 * 60 * 1000; const MAX_BODY_CHARS = 10000; function ensureDir() { if (!fs.existsSync(CONFIG_DIR)) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); } } function readLogs() { try { ensureDir(); if (!fs.existsSync(LOG_FILE)) { return []; } const raw = fs.readFileSync(LOG_FILE, 'utf8'); const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch (error) { console.warn('[REQUEST-LOG] Konnte Logdatei nicht lesen:', error.message); return []; } } function persistLogs(logs) { try { ensureDir(); fs.writeFileSync(LOG_FILE, JSON.stringify(logs, null, 2)); } catch (error) { console.warn('[REQUEST-LOG] Konnte Logdatei nicht schreiben:', error.message); } } function prune(logs = []) { const cutoff = Date.now() - TTL_MS; return logs.filter((entry) => Number(entry?.timestamp) >= cutoff); } function serializeBodySnippet(body) { try { if (body === undefined || body === null) { return null; } let text = ''; if (typeof body === 'string') { text = body; } else if (Buffer.isBuffer(body)) { text = body.toString('utf8'); } else { text = JSON.stringify(body); } if (text.length > MAX_BODY_CHARS) { return `${text.slice(0, MAX_BODY_CHARS)}… (gekürzt)`; } return text; } catch (error) { return `<>`; } } function add(entry = {}) { const logs = prune(readLogs()); const record = { id: uuid(), timestamp: Date.now(), ...entry }; if ('responseBody' in record) { record.responseBody = serializeBodySnippet(record.responseBody); } logs.push(record); persistLogs(logs); return record; } function list(limit = 500) { const sanitizedLimit = Math.max(1, Math.min(Number(limit) || 500, 2000)); const logs = prune(readLogs()); persistLogs(logs); return logs.slice(-sanitizedLimit).reverse(); } module.exports = { add, list, serializeBodySnippet };