urspruenglichesVerzeichnis = (string)Config::get('log_dir'); $verzeichnis = $this->tempPfad('_logs'); mkdir($verzeichnis, 0775, true); Config::set('log_dir', $verzeichnis); try { $this->ausgeschaltetSchreibtNichts($verzeichnis); $this->eingeschaltetSchreibt($verzeichnis); $this->maskiertGeheimnisse(); $this->fehlerImmerProtokolliert($verzeichnis); } finally { Config::set('log_dir', $this->urspruenglichesVerzeichnis); DebugLog::setAktiv(false); } } private function ausgeschaltetSchreibtNichts(string $verzeichnis): void { DebugLog::setAktiv(false); DebugLog::schreibe('test', 'darf nicht auftauchen'); $this->assert( glob($verzeichnis . '/debug-*.log') === [], 'Bei ausgeschaltetem Log entsteht keine Datei' ); } private function eingeschaltetSchreibt(string $verzeichnis): void { DebugLog::setAktiv(true); DebugLog::schreibe('test', 'eine Nachricht', ['zahl' => 42]); $pfad = DebugLog::pfad(); $this->assert(file_exists($pfad), 'Eingeschaltet entsteht eine Logdatei'); $inhalt = (string)file_get_contents($pfad); $this->assert(str_contains($inhalt, 'eine Nachricht'), 'Die Nachricht steht im Log'); $this->assert(str_contains($inhalt, '"zahl":42'), 'Der Kontext steht im Log'); $this->assert(str_contains($inhalt, '[test]'), 'Die Kategorie steht im Log'); } private function maskiertGeheimnisse(): void { $maskiert = DebugLog::maskiere([ 'benutzer' => 'felix', 'pin' => '123456', 'passwort' => 'streng geheim', 'daten' => ['api_key' => 'abc', 'betrag' => 12.5], ]); $this->assertEquals('felix', $maskiert['benutzer'], 'Harmlose Werte bleiben lesbar'); $this->assertEquals('***', $maskiert['pin'], 'PIN wird maskiert'); $this->assertEquals('***', $maskiert['passwort'], 'Passwort wird maskiert'); $this->assertEquals('***', $maskiert['daten']['api_key'], 'Verschachtelter API-Key wird maskiert'); $this->assertEquals(12.5, $maskiert['daten']['betrag'], 'Betrag bleibt unverändert'); // Der Weg über schreibe() muss ebenfalls maskieren – sonst landet eine // Banking-PIN über einen SQL-Parameter im Klartext im Log. DebugLog::setAktiv(true); DebugLog::schreibe('test', 'mit Geheimnis', ['pin' => '999888']); $inhalt = (string)file_get_contents(DebugLog::pfad()); $this->assert(!str_contains($inhalt, '999888'), 'Die PIN taucht nicht im Log auf'); } private function fehlerImmerProtokolliert(string $verzeichnis): void { DebugLog::setAktiv(false); DebugLog::fehler(new RuntimeException('Testfehler')); $inhalt = (string)file_get_contents(DebugLog::pfad()); $this->assert( str_contains($inhalt, 'Testfehler'), 'Ausnahmen werden auch bei ausgeschaltetem Log protokolliert' ); } }