logging
This commit is contained in:
75
docs/application-error-logging.md
Normal file
75
docs/application-error-logging.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Application Error Logging
|
||||
|
||||
Das Backend speichert technische Fehler zentral in `application_error_logs`. Die Tabelle ist fuer Fehleranalyse gedacht, nicht fuer fachliches Audit-Logging; bestehende Audit-Events bleiben unveraendert.
|
||||
|
||||
## Felder
|
||||
|
||||
- `level`: technischer Schweregrad, aktuell `error` oder `warning`.
|
||||
- `category`: grobe Fehlergruppe, z. B. `EMAIL`, `EXTERNAL_API`, `DATABASE`, `BACKGROUND_JOB`, `FILE`, `UNHANDLED`.
|
||||
- `code`: stabiler maschinenlesbarer Fehlercode, z. B. `PASSWORD_RESET_EMAIL_SEND_FAILED`.
|
||||
- `message`, `stackTrace`, `errorType`: technische Fehlerdaten aus `Error`, `HttpException` oder unbekannten Fehlerwerten.
|
||||
- `backendModule`, `service`, `operation`: fachliche Herkunft im Backend.
|
||||
- `httpMethod`, `apiPath`, `httpStatusCode`: HTTP-Kontext, sofern vorhanden.
|
||||
- `correlationId`: Request-ID aus `X-Correlation-ID` oder eine pro Request erzeugte UUID.
|
||||
- `userId`, `tenantId`: Benutzer- und Mandantenkontext, sofern vorhanden.
|
||||
- `environment`, `host`: Laufzeitumgebung und Instanz.
|
||||
- `context`: bereinigte strukturierte Zusatzdaten.
|
||||
- `handled`: `true`, wenn der Fehler gezielt behandelt und protokolliert wurde; `false` fuer unerwartete globale Exceptions.
|
||||
|
||||
## Erfassung
|
||||
|
||||
Der globale NestJS-Exception-Filter protokolliert unerwartete Exceptions und technische HTTP-Fehler ab Status 500. Erwartete fachliche Fehler wie Validierung, fehlende Berechtigungen, bewusstes 404 oder Konflikte werden nicht automatisch als Systemfehler gespeichert.
|
||||
|
||||
Explizit protokolliert werden derzeit:
|
||||
|
||||
- Passwort-Reset-Mailfehler mit `PASSWORD_RESET_EMAIL_SEND_FAILED`.
|
||||
- Registrierungs-Bestaetigungs-Mailfehler mit `REGISTRATION_VERIFICATION_EMAIL_SEND_FAILED`.
|
||||
- Benachrichtigung an User-Manager mit `REGISTRATION_APPROVAL_NOTIFICATION_FAILED`.
|
||||
- LLDAP/GraphQL- und LDAP-Integrationsfehler mit `EXTERNAL_API_REQUEST_FAILED`.
|
||||
|
||||
Asynchrone Prozesse ohne HTTP-Request sollen den `ApplicationErrorLoggerService` direkt verwenden und `handled: true` setzen.
|
||||
|
||||
## Datenschutz
|
||||
|
||||
Der Logger entfernt sensible Schluessel rekursiv und case-insensitive, darunter `password`, `currentPassword`, `newPassword`, `token`, `accessToken`, `refreshToken`, `idToken`, `authorization`, `cookie`, `secret`, `apiKey`, `clientSecret`, `resetToken` und `sessionId`.
|
||||
|
||||
Kontextdaten werden in Tiefe, Array-Laenge, Schluesselanzahl und String-Laenge begrenzt. Zirkulaere Objekte werden sicher ersetzt. E-Mail-Adressen in freien Texten werden maskiert, z. B. `m***@example.com`.
|
||||
|
||||
## Fehlersuche
|
||||
|
||||
1. Korrelations-ID aus Response-Header `X-Correlation-ID` oder Backend-Log notieren.
|
||||
2. In `application_error_logs` nach `correlationId`, `code`, `category`, `userId` oder Zeitraum suchen.
|
||||
3. `handled` pruefen: `false` weist auf einen unerwarteten globalen Fehler hin, `true` auf einen gezielt behandelten technischen Fehler.
|
||||
4. `context` fuer Provider-Status, maskierte Empfaenger oder Integrationsdetails verwenden.
|
||||
|
||||
## Beispiel
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await this.mail.sendPasswordResetMail(user.email, token);
|
||||
} catch (error) {
|
||||
await this.applicationErrorLogger.log({
|
||||
error,
|
||||
category: ApplicationErrorCategory.EMAIL,
|
||||
code: ApplicationErrorCode.PASSWORD_RESET_EMAIL_SEND_FAILED,
|
||||
module: 'PasswordModule',
|
||||
service: PasswordService.name,
|
||||
operation: 'sendPasswordResetEmail',
|
||||
requestContext: {
|
||||
correlationId,
|
||||
userId: user.id,
|
||||
},
|
||||
context: {
|
||||
maskedRecipient: maskEmail(user.email),
|
||||
mailProvider,
|
||||
},
|
||||
handled: true,
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
## Aufbewahrung
|
||||
|
||||
Es gibt im Projekt derzeit keinen Scheduler oder Queue-Mechanismus. Empfohlen ist ein spaeterer, begrenzter Cleanup-Job, der Fehler aelter als 180 Tage in Batches loescht und kritische Kategorien bei Bedarf laenger aufbewahrt. Die Tabelle besitzt Indizes auf `createdAt`, `code`, `category`, `correlationId`, `userId`, `tenantId` und `httpStatusCode`.
|
||||
Reference in New Issue
Block a user