Files
Pickup-Config/services/requestLogStore.js
Meik bd41e8c079 chore: sync running docker state
Commit the app code currently running in Docker, including scheduler, store status, journal reminder, maintenance mode, and Foodsharing API check updates. Remove generated runtime logs from version control and ignore local runtime captures.
2026-06-14 21:21:07 +02:00

97 lines
2.3 KiB
JavaScript

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 = 28 * 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 `<<Konnte Response nicht serialisieren: ${error.message}>>`;
}
}
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) {
const logs = prune(readLogs());
persistLogs(logs);
if (limit == null) {
return logs.slice().reverse();
}
const sanitizedLimit = Math.max(1, Math.min(Number(limit) || 500, 10000));
return logs.slice(-sanitizedLimit).reverse();
}
module.exports = {
add,
list,
serializeBodySnippet
};