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

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

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