Umsetzung von M1
This commit is contained in:
@@ -1,12 +1,21 @@
|
||||
---
|
||||
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** `<basename>.txt`
|
||||
- eine **Log-Datei** `<basename>.log`
|
||||
|
||||
Beide in **UTF-8**. Zusätzlich wird der Bericht weiterhin in die **Konsole** geschrieben. Wenn bereits gleichnamige Dateien existieren, werden neue mit laufendem Suffix `_v1`, `_v2`, … erzeugt, **pro Eingabedatei-Basisname**.
|
||||
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
|
||||
|
||||
@@ -14,69 +23,96 @@ Beide in **UTF-8**. Zusätzlich wird der Bericht weiterhin in die **Konsole** ge
|
||||
|
||||
## Scope IN
|
||||
|
||||
### Berichtdatei
|
||||
- Klasse `ReportFileWriter` oder ähnlich im Paket `adapter.out.reporting`
|
||||
- Eingabe: `ValidationReport` (aus AP05) und Eingabedatei-Pfad
|
||||
- Ausgabe: eine UTF-8-Textdatei im **selben Verzeichnis** wie die Eingabedatei
|
||||
- Dateiname: `<basename-der-eingabedatei>.txt`, bei Konflikt `<basename>_v1.txt`, `<basename>_v2.txt`, …
|
||||
- Inhalt für M1: **einfach gehalten**. Pro `Finding` eine Zeile mit den wichtigsten Metadaten (Severity, Kind, Layer, Feld-ID, deutsche Nachricht). Kopfzeile mit Dateiname, Zeitstempel, Verdict. Die fein strukturierte hierarchische Darstellung kommt erst in M9.
|
||||
### `SuffixResolver` im Paket `adapter.out.filesystem`
|
||||
|
||||
### Log-Datei
|
||||
- Wiederverwendung des `LoggingConfigurator` aus AP04
|
||||
- Methode `configureLogFile(Path logFile)` wird im Bootstrap **vor** dem CLI-Runner aufgerufen
|
||||
- Log-Datei liegt im **selben Verzeichnis** wie die Eingabedatei
|
||||
- Dateiname: `<basename>.log`, Suffix-Logik analog zur Berichtdatei
|
||||
- Log4j2 wird programmatisch umkonfiguriert: der File-Appender schreibt nach dem neuen Pfad. Die statische `log4j2.xml` aus AP04 ist nur der Fallback für „kein Eingabeargument".
|
||||
```java
|
||||
public class SuffixResolver {
|
||||
/**
|
||||
* Ermittelt den ersten freien Dateipfad für den gegebenen Basisnamen
|
||||
* und die gegebene Extension im Zielverzeichnis.
|
||||
* Probiert: <baseName>.<ext>, dann <baseName>_v1.<ext>, <baseName>_v2.<ext>, ...
|
||||
*/
|
||||
public Path resolveNextFreePath(Path directory, String baseName, String extension) { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### Suffix-Logik
|
||||
- eigene kleine Utility-Klasse `SuffixResolver` im Paket `adapter.out.filesystem`
|
||||
- Methode `Path resolveNextFreePath(Path baseDirectory, String baseName, String extension)`:
|
||||
- probiert `<baseName>.<ext>`, dann `<baseName>_v1.<ext>`, `<baseName>_v2.<ext>`, …
|
||||
- gibt den ersten freien Pfad zurück
|
||||
- wird sowohl für die Berichtdatei als auch für die Log-Datei verwendet
|
||||
- **Hinweis:** Die Zählung ist pro Basisname unabhängig. Wenn für `test.auf.txt` schon `test.auf_v1.txt` existiert, aber für `test.auf.log` noch keine `_v1`, kann das vorkommen — die Suffixe müssen **nicht synchron** sein.
|
||||
- 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
|
||||
- bleibt erhalten, schreibt denselben Bericht-Text wie die Berichtdatei
|
||||
- Konsolenausgabe erfolgt **nach** der Berichtdatei-Erstellung, damit ein IO-Fehler beim Schreiben der Berichtdatei nicht die Konsolenausgabe verhindert
|
||||
|
||||
- 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)
|
||||
- Einfärbung / ANSI-Codes in der Konsole
|
||||
- Hierarchische Berichtsgliederung (M9)
|
||||
- ANSI-Farben / Einfärbung in der Konsole
|
||||
- Log-Rotation
|
||||
- Minimalbericht bei Exit-Code 2 (AP08)
|
||||
- Minimalbericht bei Exit-Code `2` (AP08)
|
||||
|
||||
## Schritte
|
||||
|
||||
1. Branch `m1/ap07-ausgabeartefakte`
|
||||
2. `SuffixResolver` implementieren inkl. Unit-Tests für: keine Datei vorhanden, `.txt` vorhanden, `.txt` + `_v1` vorhanden, mehrere Lücken
|
||||
3. `ReportFileWriter` implementieren mit einfachem Zeilenformat für M1
|
||||
4. `LoggingConfigurator.configureLogFile(Path)` implementieren (programmatische Log4j2-Reconfiguration)
|
||||
5. Bootstrap erweitern: vor CLI-Lauf → Log-Datei-Pfad bestimmen → `LoggingConfigurator` aufrufen
|
||||
6. CLI-Runner erweitert: nach Lauf → Berichtdatei schreiben → Konsolenausgabe erzeugen
|
||||
7. End-to-End-Test mit Dummy-Eingabedatei: beide Ausgabedateien entstehen, Suffix-Logik funktioniert
|
||||
8. `mvn clean verify` grün
|
||||
9. Commit `M1-AP07: Berichtdatei und Log-Datei im Eingabeverzeichnis mit Suffix-Logik`
|
||||
10. Abschlussbericht schreiben
|
||||
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 einem Lauf mit Eingabedatei `foo/bar.auf` existieren `foo/bar.auf.txt` und `foo/bar.auf.log`
|
||||
- zweiter Lauf mit derselben Eingabedatei erzeugt `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 vier Unit-Tests
|
||||
- `mvn clean verify` ist grün
|
||||
- Abschlussbericht liegt vor
|
||||
- [ ] 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).
|
||||
- Die programmatische Log4j2-Reconfiguration ist technisch nicht ganz ohne. Falls sie sich als zu instabil erweist, ist eine **sys-property-basierte** Konfiguration der Log-Datei (`-Dasv.log.file=...`) ein zulässiger Fallback. Entscheidung im Bericht dokumentieren.
|
||||
- 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 `templates/ap-bericht.md`.
|
||||
`docs/arbeitspakete/m1/berichte/AP07-bericht.md` nach `docs/arbeitspakete/m1/templates/ap-bericht.md`.
|
||||
|
||||
Reference in New Issue
Block a user