"feat: Update database configuration and documentation for monitoring system"

This commit is contained in:
Till Tomczak 2025-05-29 18:28:35 +02:00
parent d2a9a42651
commit 8b77ded3af
4 changed files with 480 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,272 @@
# MYP Error-Monitoring System - Dokumentation
## Übersicht
Das Error-Monitoring System ist eine umfassende Lösung zur automatischen Erkennung, Meldung und Behebung kritischer Systemfehler im MYP (Mercedes-Benz Your Platform) System. Es wurde entwickelt, um Administratoren sofortige Benachrichtigungen über Datenbankfehler, Schema-Probleme und andere kritische Systemprobleme zu geben.
## Problemstellung
**Ursprünglicher Fehler:**
```
sqlite3.OperationalError: no such column: guest_requests.duration_minutes
```
Dieser Fehler trat auf, weil das Datenmodell `GuestRequest` sowohl `duration_min` als auch `duration_minutes` definierte, aber die Datenbank nur die `duration_min` Spalte enthielt. Solche Schema-Inkonsistenzen führten zu Anwendungsfehlern und waren für Admins nicht sichtbar.
## Lösung
### 1. Automatische Datenbank-Migration ⚡
**Datei:** `utils/database_schema_migration.py`
**Erweiterte Funktionalität:**
- Vollständige Schema-Überprüfung für alle Tabellen
- Automatisches Hinzufügen fehlender Spalten
- Backup-Erstellung vor jeder Migration
- Datenmigration (kopiert `duration_min``duration_minutes`)
**Neue Spalten hinzugefügt:**
```python
required_columns = {
'duration_minutes': 'INTEGER', # ← Lösung für ursprünglichen Fehler
'file_name': 'VARCHAR(255)',
'file_path': 'VARCHAR(500)',
'copies': 'INTEGER DEFAULT 1',
'updated_at': 'DATETIME DEFAULT CURRENT_TIMESTAMP',
'approved_at': 'DATETIME',
'rejected_at': 'DATETIME',
'approved_by': 'INTEGER',
'rejected_by': 'INTEGER',
'otp_expires_at': 'DATETIME',
'assigned_printer_id': 'INTEGER'
}
```
### 2. Real-Time Error-Monitoring Dashboard 📊
**Datei:** `templates/admin.html`
**Neue Komponenten:**
- **Critical Errors Alert System**: Rote Warnmeldungen für kritische Fehler
- **Database Health Status**: Echtzeit-Überwachung der Datenbankgesundheit
- **Automatic Fix Button**: Ein-Klick-Reparatur für häufige Probleme
**Features:**
- 🚨 Sofortige Benachrichtigungen bei kritischen Fehlern
- 🗄️ Datenbank-Gesundheitsstatus mit Live-Indikatoren
- 🔧 Automatische Reparatur-Buttons
- 📊 System-Metriken (CPU, RAM, Festplatte)
### 3. Comprehensive Health Check API 🔍
**Datei:** `app.py` - Neue Endpoints:
#### `/api/admin/system-health` (GET)
**Funktionalität:**
```python
def api_admin_system_health():
# 1. Datenbank-Schema-Integrität prüfen
# 2. Kritische Spalten in wichtigen Tabellen überprüfen
# 3. Log-Dateien nach wiederkehrenden Fehlern durchsuchen
# 4. Drucker-Konnektivität überprüfen
# 5. System-Performance-Metriken sammeln
# 6. Letzte Migration-Informationen abrufen
```
**Response-Format:**
```json
{
"success": true,
"health_status": "healthy|warning|critical",
"critical_errors": [
{
"type": "database_schema",
"message": "Datenbank-Schema-Fehler erkannt",
"severity": "critical",
"suggested_fix": "Datenbank-Migration ausführen",
"timestamp": "2025-05-29T18:22:03"
}
],
"warnings": [...],
"schema_integrity": "OK|FEHLER",
"last_migration": "20250529_182203",
"recent_errors_count": 0,
"system_metrics": {
"cpu_usage": 15.2,
"memory_usage": 42.1,
"disk_usage": 68.9
}
}
```
#### `/api/admin/fix-errors` (POST)
**Funktionalität:**
- Führt automatische Datenbank-Migration aus
- Erstellt Backup vor Reparatur
- Protokolliert alle Aktionen
- Gibt detaillierte Ergebnis-Informationen zurück
### 4. Live JavaScript Error-Monitor 🔄
**Datei:** `static/js/admin-live.js`
**Neue Klassen-Methoden:**
- `initErrorMonitoring()`: Startet das Monitoring-System
- `checkSystemHealth()`: Prüft System alle 30 Sekunden
- `updateHealthDisplay()`: Aktualisiert UI-Indikatoren
- `updateErrorAlerts()`: Zeigt/versteckt Error-Alerts
- `fixErrors()`: Führt automatische Reparatur aus
- `showNotification()`: Toast-Benachrichtigungen
**Live-Features:**
- ⏱️ Automatische Überprüfung alle 30 Sekunden
- 🔴 Rote Indikatoren bei kritischen Fehlern
- 🟡 Gelbe Indikatoren bei Warnungen
- 🟢 Grüne Indikatoren bei gesundem System
- 📱 Toast-Benachrichtigungen für Aktionen
## Technische Details
### Schema-Migration-Prozess
1. **Backup-Erstellung:**
```sql
VACUUM INTO 'database/myp.db.backup_YYYYMMDD_HHMMSS'
```
2. **Spalten-Überprüfung:**
```python
cursor.execute("PRAGMA table_info(guest_requests)")
existing_columns = {row[1]: row[2] for row in cursor.fetchall()}
```
3. **Automatisches Hinzufügen:**
```sql
ALTER TABLE guest_requests ADD COLUMN duration_minutes INTEGER
UPDATE guest_requests SET duration_minutes = duration_min WHERE duration_minutes IS NULL
```
### Error-Detection-Algorithmus
1. **Schema-Integrität:** Testet kritische Spalten mit `SELECT ... LIMIT 1`
2. **Log-Analyse:** Durchsucht letzte 100 Log-Zeilen nach "OperationalError"
3. **Performance-Monitoring:** Nutzt `psutil` für System-Metriken
4. **Drucker-Status:** Überprüft offline/online Status
5. **Migration-Historie:** Analysiert Backup-Dateien für letzte Änderungen
## Admin-Interface
### Darstellung im Dashboard
```html
<!-- Critical Error Alert -->
🚨 Kritische Systemfehler erkannt
├── Datenbank-Schema-Fehler: no such column: duration_minutes
│ 💡 Suggested Fix: Datenbank-Migration ausführen
│ 📅 29.05.2025, 18:22:03
│ 🔧 [Automatisch reparieren] ❌ [Verwerfen] 📊 [Details]
<!-- Database Health Status -->
🗄️ Datenbank-Gesundheitsstatus 🟢 Gesund
├── Letzte Migration: 20250529_182203
├── Schema-Integrität: OK
└── Letzte Fehler: 0
```
### Benutzerinteraktion
1. **Fehler erkannt** → Alert wird automatisch angezeigt
2. **Admin klickt "Automatisch reparieren"** → Migration wird ausgeführt
3. **Erfolgsmeldung** → ✅ Grüne Toast-Benachrichtigung
4. **System aktualisiert sich** → Health-Check läuft erneut
## Konfiguration
### Monitoring-Intervalle
```javascript
// System Health Check alle 30 Sekunden
setInterval(() => this.checkSystemHealth(), 30000);
// Toast-Notifications verschwinden nach 5 Sekunden
setTimeout(() => notification.remove(), 5000);
```
### Schwellenwerte
```python
# Performance-Warnungen
cpu_usage > 90% # Warnung bei hoher CPU-Last
memory_usage > 85% # Warnung bei hohem RAM-Verbrauch
recent_db_errors > 5 # Kritisch bei vielen DB-Fehlern
```
## Deployment
### Automatische Aktivierung
Das Error-Monitoring System ist automatisch aktiv sobald:
1. Ein Administrator das Admin-Dashboard öffnet
2. Das JavaScript `admin-live.js` geladen wird
3. Die Health-Check-APIs verfügbar sind
### Voraussetzungen
```python
# Python-Dependencies
import psutil # Für System-Metriken
import subprocess # Für automatische Migration
import os # Für Log-Datei-Zugriff
```
## Logging und Dokumentation
### Error-Logging
```python
app_logger.error(f"Datenbank-Transaktion fehlgeschlagen: {str(e)}")
app_logger.info(f"Automatische Migration erfolgreich ausgeführt von Admin {current_user.email}")
```
### Admin-Aktionen
Alle Admin-Aktionen werden protokolliert:
- Wer hat welche Reparatur ausgeführt
- Zeitstempel aller Aktionen
- Erfolg/Fehlschlag-Status
- Detaillierte Fehlermeldungen
## Wartung
### Regelmäßige Aufgaben
1. **Log-Rotation:** Alte Log-Dateien archivieren
2. **Backup-Cleanup:** Alte Backup-Dateien löschen
3. **Performance-Monitoring:** System-Metriken überwachen
4. **Schema-Updates:** Neue Migrations bei Model-Änderungen
### Troubleshooting
**Problem:** Error-Monitor zeigt nichts an
**Lösung:**
1. Browser-Konsole überprüfen
2. `/api/admin/system-health` manuell testen
3. Admin-Berechtigung überprüfen
**Problem:** Automatische Reparatur schlägt fehl
**Lösung:**
1. Manuelle Migration: `python utils/database_schema_migration.py`
2. Log-Dateien überprüfen
3. Datenbank-Berechtigungen prüfen
## Ergebnis
**Problem gelöst:** Der ursprüngliche `duration_minutes` Fehler wurde behoben
**Proaktiv:** Zukünftige Schema-Probleme werden automatisch erkannt
**Benutzerfreundlich:** Admins sehen Probleme sofort und können sie mit einem Klick beheben
**Umfassend:** Monitoring von DB, Performance, Logs und System-Gesundheit
**Automatisiert:** Selbst-reparierendes System für häufige Probleme
Das Error-Monitoring System stellt sicher, dass kritische Systemfehler nicht unbemerkt bleiben und Administratoren die Werkzeuge haben, um schnell und effektiv zu reagieren.

View File

@ -49,6 +49,9 @@ class AdminLiveDashboard {
// Initial Load
this.loadLiveStats();
// Error Monitoring System
this.initErrorMonitoring();
}
bindEvents() {
@ -366,6 +369,211 @@ class AdminLiveDashboard {
const meta = document.querySelector('meta[name="csrf-token"]');
return meta ? meta.getAttribute('content') : '';
}
// Error Monitoring System
initErrorMonitoring() {
// Check system health every 30 seconds
this.checkSystemHealth();
setInterval(() => this.checkSystemHealth(), 30000);
// Setup error alert event handlers
this.setupErrorAlertHandlers();
}
async checkSystemHealth() {
try {
const response = await fetch('/api/admin/system-health');
const data = await response.json();
if (data.success) {
this.updateHealthDisplay(data);
this.updateErrorAlerts(data);
} else {
console.error('System health check failed:', data.error);
}
} catch (error) {
console.error('Error checking system health:', error);
}
}
updateHealthDisplay(data) {
// Update database health status
const statusIndicator = document.getElementById('db-status-indicator');
const statusText = document.getElementById('db-status-text');
const lastMigration = document.getElementById('last-migration');
const schemaIntegrity = document.getElementById('schema-integrity');
const recentErrorsCount = document.getElementById('recent-errors-count');
if (statusIndicator && statusText) {
if (data.health_status === 'critical') {
statusIndicator.className = 'w-3 h-3 bg-red-500 rounded-full animate-pulse';
statusText.textContent = 'Kritisch';
statusText.className = 'text-sm font-medium text-red-600 dark:text-red-400';
} else if (data.health_status === 'warning') {
statusIndicator.className = 'w-3 h-3 bg-yellow-500 rounded-full animate-pulse';
statusText.textContent = 'Warnung';
statusText.className = 'text-sm font-medium text-yellow-600 dark:text-yellow-400';
} else {
statusIndicator.className = 'w-3 h-3 bg-green-400 rounded-full animate-pulse';
statusText.textContent = 'Gesund';
statusText.className = 'text-sm font-medium text-green-600 dark:text-green-400';
}
}
if (lastMigration) {
lastMigration.textContent = data.last_migration || 'Unbekannt';
}
if (schemaIntegrity) {
schemaIntegrity.textContent = data.schema_integrity || 'Prüfung';
if (data.schema_integrity === 'FEHLER') {
schemaIntegrity.className = 'text-lg font-semibold text-red-600 dark:text-red-400';
} else {
schemaIntegrity.className = 'text-lg font-semibold text-green-600 dark:text-green-400';
}
}
if (recentErrorsCount) {
const errorCount = data.recent_errors_count || 0;
recentErrorsCount.textContent = errorCount;
if (errorCount > 0) {
recentErrorsCount.className = 'text-lg font-semibold text-red-600 dark:text-red-400';
} else {
recentErrorsCount.className = 'text-lg font-semibold text-green-600 dark:text-green-400';
}
}
}
updateErrorAlerts(data) {
const alertContainer = document.getElementById('critical-errors-alert');
const errorList = document.getElementById('error-list');
if (!alertContainer || !errorList) return;
const allErrors = [...(data.critical_errors || []), ...(data.warnings || [])];
if (allErrors.length > 0) {
// Show alert container
alertContainer.classList.remove('hidden');
// Clear previous errors
errorList.innerHTML = '';
// Add each error
allErrors.forEach(error => {
const errorElement = document.createElement('div');
errorElement.className = `p-3 rounded-lg border-l-4 ${
error.severity === 'critical' ? 'bg-red-50 dark:bg-red-900/30 border-red-500' :
error.severity === 'high' ? 'bg-orange-50 dark:bg-orange-900/30 border-orange-500' :
'bg-yellow-50 dark:bg-yellow-900/30 border-yellow-500'
}`;
errorElement.innerHTML = `
<div class="flex items-start justify-between">
<div class="flex-1">
<h4 class="font-medium ${
error.severity === 'critical' ? 'text-red-800 dark:text-red-200' :
error.severity === 'high' ? 'text-orange-800 dark:text-orange-200' :
'text-yellow-800 dark:text-yellow-200'
}">${error.message}</h4>
<p class="text-sm mt-1 ${
error.severity === 'critical' ? 'text-red-600 dark:text-red-300' :
error.severity === 'high' ? 'text-orange-600 dark:text-orange-300' :
'text-yellow-600 dark:text-yellow-300'
}">💡 ${error.suggested_fix}</p>
<p class="text-xs mt-1 text-gray-500 dark:text-gray-400">
📅 ${new Date(error.timestamp).toLocaleString('de-DE')}
</p>
</div>
<span class="ml-2 px-2 py-1 text-xs font-medium rounded-full ${
error.severity === 'critical' ? 'bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-100' :
error.severity === 'high' ? 'bg-orange-100 text-orange-800 dark:bg-orange-800 dark:text-orange-100' :
'bg-yellow-100 text-yellow-800 dark:bg-yellow-800 dark:text-yellow-100'
}">
${error.severity.toUpperCase()}
</span>
</div>
`;
errorList.appendChild(errorElement);
});
} else {
// Hide alert container
alertContainer.classList.add('hidden');
}
}
setupErrorAlertHandlers() {
// Fix errors button
const fixErrorsBtn = document.getElementById('fix-errors-btn');
if (fixErrorsBtn) {
fixErrorsBtn.addEventListener('click', async () => {
await this.fixErrors();
});
}
// Dismiss errors button
const dismissErrorsBtn = document.getElementById('dismiss-errors-btn');
if (dismissErrorsBtn) {
dismissErrorsBtn.addEventListener('click', () => {
const alertContainer = document.getElementById('critical-errors-alert');
if (alertContainer) {
alertContainer.classList.add('hidden');
}
});
}
// View details button
const viewDetailsBtn = document.getElementById('view-error-details-btn');
if (viewDetailsBtn) {
viewDetailsBtn.addEventListener('click', () => {
// Redirect to logs tab
window.location.href = '/admin-dashboard?tab=logs';
});
}
}
async fixErrors() {
const fixBtn = document.getElementById('fix-errors-btn');
if (!fixBtn) return;
// Show loading state
const originalText = fixBtn.innerHTML;
fixBtn.innerHTML = '🔄 Repariere...';
fixBtn.disabled = true;
try {
const response = await fetch('/api/admin/fix-errors', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.success) {
// Show success message
this.showNotification('✅ Automatische Reparatur erfolgreich durchgeführt!', 'success');
// Refresh health check
setTimeout(() => {
this.checkSystemHealth();
}, 2000);
} else {
// Show error message
this.showNotification(`❌ Reparatur fehlgeschlagen: ${data.error}`, 'error');
}
} catch (error) {
console.error('Error fixing errors:', error);
this.showNotification('❌ Fehler bei der automatischen Reparatur', 'error');
} finally {
// Restore button
fixBtn.innerHTML = originalText;
fixBtn.disabled = false;
}
}
}
// Initialize when DOM is ready