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]>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/* =====================================================================
|
||||
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;
|
||||
Reference in New Issue
Block a user