Files
ldap-identidy/docs/application-error-logging.md
Bastian Wagner edd88acd98 mail und logging
2026-07-17 11:50:12 +02:00

80 lines
3.8 KiB
Markdown

# 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({
recipient: user.email,
token,
expiresAt: resetToken.expiresAt,
});
} 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`.