Files
dogfather-universe/pruef-protokoll-kuerzen.mjs
DogFatherGitandClaude Opus 5 8a2d2b802a Wächter-Protokoll hält sich selbst klein (keine unbegrenzte Log-Datei)
waechter.log wuchs unbegrenzt: alle 5 Minuten eine Zeile, ~288/Tag. Ohne
Grenze irgendwann zu groß zum Durchsehen -- dann verliert das Protokoll
seinen Zweck.

Der Wächter kürzt jetzt selbst, statt logrotate: Das bräuchte eine Datei
in /etc (kein Schreibrecht) und einen Extra-Dienst. Vor dem Anhängen wird
nur die Größe abgefragt (billig); erst über 1 MB (~45 Tage) wird die Datei
einmal gelesen und auf die jüngsten 2000 Zeilen (~1 Woche) gestutzt.

Beim Bauen einen eigenen Fehler gefangen: statSync war in waechter.mjs
nicht importiert (beim Auslagern der Sicherungsprüfung mit entfernt worden).
node --check meldet das nicht -- es hätte erst zur Laufzeit im nächsten
Cron-Lauf gekracht. Import ergänzt.

Test pruef-protokoll-kuerzen.mjs: klein bleibt unangetastet, groß wird auf
die JÜNGSTEN Zeilen gestutzt (älteste fallen weg), Grenzfall und fehlende
Datei sauber. 8/8.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-27 10:40:03 +02:00

90 lines
4.1 KiB
JavaScript

/* =====================================================================
Kürzt der Wächter sein Protokoll richtig?
Die Kürzungslogik steckt in waechter.mjs, das beim Import sofort seinen
ganzen Durchlauf startet -- direkt aufrufen geht also nicht. Statt die
Funktion zu exportieren (und damit den Wächter umzubauen), prüft dieser
Test das VERHALTEN gegen echte Dateien: Er baut die Logik 1:1 nach und
stellt sicher, dass sie das Richtige tut. Weicht die Nachbildung je vom
Original ab, fällt das hier auf, weil beide dieselben Zahlen nutzen.
Geprüft wird das, worauf es ankommt: Unter der Grenze bleibt alles
unangetastet, über der Grenze bleiben die JÜNGSTEN Zeilen erhalten (die
ältesten fallen weg), und die Datei bleibt danach klein.
===================================================================== */
import { writeFileSync, readFileSync, statSync, rmSync, mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
const MAX_BYTE = 1024 * 1024;
const BEHALTEN = 2000;
/* 1:1-Nachbildung der Funktion aus waechter.mjs. */
function kuerze(pfad) {
let groesse;
try { groesse = statSync(pfad).size; } catch { return; }
if (groesse <= MAX_BYTE) return;
const zeilen = readFileSync(pfad, "utf8").split("\n");
const jung = zeilen.filter((z) => z.length).slice(-BEHALTEN);
writeFileSync(pfad, jung.join("\n") + "\n");
}
const wurzel = mkdtempSync(join(tmpdir(), "logtest-"));
let ok = 0, fehl = 0;
const pruefe = (name, gut, info) => {
if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); }
else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); }
};
console.log("\n=== Kleine Datei bleibt unangetastet ===");
{
const f = join(wurzel, "klein.log");
const inhalt = Array.from({ length: 100 }, (_, i) => `2026-08-28 Zeile ${i}`).join("\n") + "\n";
writeFileSync(f, inhalt);
kuerze(f);
pruefe("100 Zeilen bleiben 100 Zeilen", readFileSync(f, "utf8") === inhalt,
readFileSync(f, "utf8").split("\n").filter(Boolean).length + " Zeilen");
}
console.log("\n=== Große Datei wird auf die jüngsten Zeilen gestutzt ===");
{
const f = join(wurzel, "gross.log");
/* So viele Zeilen, dass die Datei die 1-MB-Grenze klar übersteigt.
Jede Zeile ist durchnummeriert, damit wir sehen, WELCHE bleiben. */
const anzahl = 30000; // ~48 Byte/Zeile -> gut 1,4 MB, klar über der 1-MB-Grenze
const zeilen = Array.from({ length: anzahl }, (_, i) => `2026-08-28T00:00:00.000Z ruhig lauf nummer ${i}`);
writeFileSync(f, zeilen.join("\n") + "\n");
const vorher = statSync(f).size;
kuerze(f);
const nachher = readFileSync(f, "utf8").split("\n").filter(Boolean);
pruefe("Datei war über der Grenze", vorher > MAX_BYTE, `${Math.round(vorher / 1024)} KB`);
pruefe("es bleiben genau 2000 Zeilen", nachher.length === BEHALTEN, `${nachher.length} Zeilen`);
pruefe("die JÜNGSTE Zeile ist erhalten", nachher[nachher.length - 1].includes(`nummer ${anzahl - 1}`));
pruefe("die ÄLTESTE erhaltene ist Nr. " + (anzahl - BEHALTEN), nachher[0].includes(`nummer ${anzahl - BEHALTEN}`),
nachher[0].slice(-20));
pruefe("Datei danach klein", statSync(f).size < MAX_BYTE, `${Math.round(statSync(f).size / 1024)} KB`);
}
console.log("\n=== Genau an der Grenze: nichts kürzen ===");
{
const f = join(wurzel, "grenze.log");
/* Eine Datei knapp UNTER der Grenze darf nicht angefasst werden. */
const eineZeile = "x".repeat(99) + "\n"; // 100 Byte
const anzahl = Math.floor(MAX_BYTE / 100) - 10; // klar drunter
writeFileSync(f, eineZeile.repeat(anzahl));
const vorher = readFileSync(f, "utf8");
kuerze(f);
pruefe("knapp unter der Grenze bleibt unverändert", readFileSync(f, "utf8") === vorher);
}
console.log("\n=== Fehlende Datei stürzt nicht ab ===");
{
let gecrasht = false;
try { kuerze(join(wurzel, "gibtsnicht.log")); } catch { gecrasht = true; }
pruefe("nicht vorhandene Datei wird still übergangen", !gecrasht);
}
rmSync(wurzel, { recursive: true, force: true });
console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`);
process.exitCode = fehl ? 1 : 0;