--- model: sonnet --- # AP07 – Ausgabeartefakte: Berichtdatei und Log-Datei mit Suffix-Logik > **Meilenstein:** M1 > **Vorgänger:** AP04, AP05, AP06 ✅ erforderlich > **Nachfolger:** AP08, AP10 > **Grundlage:** `docs/specs/technik-und-architektur.md` v5, §§ „Ausgabeartefakte", „Zeichensätze", „Logging und Berichtserzeugung" > **Entscheidungsprotokoll:** `docs/arbeitspakete/m1/E00-entscheidungsprotokoll.md` (E-04 logs/-Verzeichnis) ## Ziel Pro Lauf werden **zwei Ausgabedateien** im **Verzeichnis der Eingabedatei** erzeugt: - eine **Berichtdatei** `.txt` - eine **Log-Datei** `.log` Beide in **UTF-8**. Der Bericht wird zusätzlich in die **Konsole** geschrieben. Bei bereits vorhandenen Dateien gleichen Namens werden neue mit laufendem Suffix `_v1`, `_v2`, … erzeugt. ## Voraussetzungen - AP04 (Logging-Adapter), AP05 (Befundmodell), AP06 (Bootstrap/CLI) ## Scope IN ### `SuffixResolver` im Paket `adapter.out.filesystem` ```java public class SuffixResolver { /** * Ermittelt den ersten freien Dateipfad für den gegebenen Basisnamen * und die gegebene Extension im Zielverzeichnis. * Probiert: ., dann _v1., _v2., ... */ public Path resolveNextFreePath(Path directory, String baseName, String extension) { ... } } ``` - Suffix-Zählung ist **pro Extension unabhängig** — `.txt` und `.log` haben getrennte Zähler - Unit-Tests mindestens für: keine Datei vorhanden, `.txt` vorhanden, `.txt` + `_v1` vorhanden ### `ReportFileWriter` im Paket `adapter.out.reporting` - Eingabe: `ValidationReport` (AP05) + Eingabedatei-Pfad - Ausgabe: UTF-8-Textdatei im Verzeichnis der Eingabedatei - Dateiname via `SuffixResolver` - **Berichtinhalt für M1** (absichtlich minimal, wird in M9 ausgebaut): - Kopfzeile: Zeitstempel, Eingabedatei, Verdict - Pro `Finding`: eine Zeile mit Severity, Kind, Layer, Feld-ID, deutscher Meldung - Fußzeile: Hinweis auf bewusst nicht geprüfte Bereiche Alle Texte auf **Deutsch**, Encoding **UTF-8** explizit — kein Plattform-Default. ### `LoggingConfigurator.configureLogFile(Path)` in `adapter.out.logging` - Methode wird im Bootstrap **vor** dem ersten fachlichen Log-Aufruf aufgerufen - Konfiguriert Log4j2-File-Appender programmatisch auf den gewünschten Pfad - Dateiname via `SuffixResolver` (analog zur Berichtdatei, eigene Zählung) - Log4j2-Typen (`LoggerContext`, `Appender` etc.) bleiben **ausschließlich** in `adapter.out.logging` und `bootstrap` - Statischer `logs/`-Pfad aus `log4j2.xml` (AP04) wird entfernt oder auf Fallback-Default gesetzt, der nur greift wenn `configureLogFile` nicht aufgerufen wurde (z.B. für Testläufe) - **Fallback:** Falls programmatische Log4j2-Umkonfiguration sich als instabil erweist, ist eine System-Property-basierte Konfiguration (`-Dasv.log.file=...`) ein zulässiger Ausweg — Entscheidung im Bericht dokumentieren ### Integration in `bootstrap.Main` Reihenfolge vor dem Validierungslauf: 1. Eingabedatei-Pfad bestimmen 2. Basisnamen und Zielverzeichnis ableiten 3. `SuffixResolver` für `.log` aufrufen 4. `LoggingConfigurator.configureLogFile(logPath)` aufrufen → ab jetzt gehen Logs in die Datei 5. Validierungslauf starten 6. `ReportFileWriter` schreiben 7. Konsolenausgabe (identisch zum Berichtinhalt) ### Konsolenausgabe - Schreibt denselben Text wie die Berichtdatei - Erfolgt **nach** der Berichtdatei-Erstellung, damit ein IO-Fehler beim Schreiben die Konsolenausgabe nicht verhindert ## Scope OUT - Hierarchische Berichtsgliederung (M9) - ANSI-Farben / Einfärbung in der Konsole - Log-Rotation - Minimalbericht bei Exit-Code `2` (AP08) ## Schritte 1. `SuffixResolver` implementieren inkl. Unit-Tests 2. `ReportFileWriter` implementieren mit einfachem Zeilenformat für M1 3. `LoggingConfigurator.configureLogFile(Path)` implementieren 4. Bootstrap erweitern: Log-Datei-Pfad bestimmen → `LoggingConfigurator` aufrufen 5. `CliRunner` erweitern: nach Lauf → Berichtdatei schreiben → Konsolenausgabe 6. End-to-End-Test: beide Ausgabedateien entstehen, Suffix-Logik funktioniert, UTF-8 7. `mvn clean verify` grün bekommen 8. Abschlussbericht schreiben ## Abnahmekriterien - [ ] Nach Lauf mit `foo/bar.auf` entstehen `foo/bar.auf.txt` und `foo/bar.auf.log` - [ ] Zweiter Lauf mit derselben Datei → `foo/bar.auf_v1.txt` und `foo/bar.auf_v1.log` - [ ] Dritter Lauf → `_v2` usw. - [ ] Beide Ausgabedateien sind UTF-8 - [ ] Konsolenausgabe ist identisch zum Inhalt der Berichtdatei - [ ] `SuffixResolver` hat mindestens drei Unit-Tests - [ ] Log4j2-Typen sind außerhalb von `adapter.out.logging` und `bootstrap` nicht sichtbar - [ ] Statischer `logs/`-Pfad aus `log4j2.xml` entfernt oder auf Fallback-Default gesetzt - [ ] `mvn clean verify` grün - [ ] Abschlussbericht unter `docs/arbeitspakete/m1/berichte/AP07-bericht.md` ## Rest-Risiken und offene Punkte - Race Conditions bei gleichzeitigen Läufen auf derselben Eingabedatei: laut `technik-und-architektur.md` bewusst nicht behandelt (kein Mehrbenutzerbetrieb in V1). - Das Bericht-Dateiformat ist in M1 absichtlich primitiv. In M9 wird es durch die finale hierarchische Struktur ersetzt. - Fallback bei instabiler programmatischer Log4j2-Umkonfiguration im Bericht dokumentieren. ## Bericht `docs/arbeitspakete/m1/berichte/AP07-bericht.md` nach `docs/arbeitspakete/m1/templates/ap-bericht.md`.