// Debug-Dashboard JavaScript // Globale Variablen für Charts let cpuChart = null; let memoryChart = null; let diskChart = null; let containerStatusChart = null; // Speicher für historische Daten const cpuData = { labels: Array(20).fill(''), datasets: [{ label: 'CPU-Auslastung (%)', data: Array(20).fill(0), borderColor: '#3498db', backgroundColor: 'rgba(52, 152, 219, 0.2)', tension: 0.4, fill: true }] }; const memoryData = { labels: ['Verwendet', 'Frei'], datasets: [{ data: [0, 100], backgroundColor: ['#e74c3c', '#2ecc71'], hoverBackgroundColor: ['#c0392b', '#27ae60'] }] }; // Gemeinsame Chart-Optionen const lineChartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 500 }, scales: { y: { beginAtZero: true, max: 100, ticks: { callback: value => `${value}%` } } }, plugins: { legend: { display: true, position: 'top' } } }; const pieChartOptions = { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'right' } } }; // Helper-Funktionen function showMessage(message, isError = false) { const messageEl = document.getElementById('message'); messageEl.textContent = message; messageEl.className = isError ? 'message message-error' : 'message message-success'; messageEl.style.display = 'block'; // Verstecke Nachricht nach 5 Sekunden setTimeout(() => { messageEl.style.display = 'none'; }, 5000); } function formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } function formatUptime(seconds) { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); return `${days}d ${hours}h ${minutes}m`; } // Dashboard-Initialisierung document.addEventListener('DOMContentLoaded', function() { // Tab-Wechsel einrichten setupTabs(); // Charts initialisieren initCharts(); // Daten laden loadSystemMetrics(); loadDockerStatus(); refreshNetworkInterfaces(); refreshActiveConnections(); loadRouteTable(); // Regelmäßige Aktualisierungen setInterval(loadSystemMetrics, 5000); setInterval(loadDockerStatus, 10000); console.log('Debug-Dashboard initialisiert'); }); // Tab-Funktionalität function setupTabs() { document.querySelectorAll('.tab').forEach(tab => { tab.addEventListener('click', function() { // Aktiven Tab-Status wechseln document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); this.classList.add('active'); // Tab-Inhalte wechseln const tabId = this.getAttribute('data-tab'); document.querySelectorAll('.tab-content').forEach(content => { content.classList.remove('active'); }); document.getElementById(tabId + '-tab').classList.add('active'); }); }); } // Chart-Initialisierung function initCharts() { // CPU-Chart const cpuCtx = document.getElementById('cpu-usage-chart').getContext('2d'); cpuChart = new Chart(cpuCtx, { type: 'line', data: cpuData, options: lineChartOptions }); // Memory-Chart const memoryCtx = document.getElementById('memory-usage-chart').getContext('2d'); memoryChart = new Chart(memoryCtx, { type: 'doughnut', data: memoryData, options: pieChartOptions }); // Disk-Chart (Wird später initialisiert, wenn Daten verfügbar sind) // Container-Status-Chart (Wird später initialisiert, wenn Daten verfügbar sind) } // Daten-Lade-Funktionen function loadSystemMetrics() { fetch('/api/system/metrics') .then(response => response.json()) .then(data => { if (data.success) { updateSystemMetrics(data); } }) .catch(error => { console.error('Fehler beim Laden der Systemmetriken:', error); }); } function updateSystemMetrics(data) { // CPU-Auslastung aktualisieren document.getElementById('cpu-percent').textContent = `${data.cpu_percent.toFixed(1)}%`; // CPU-Chart aktualisieren cpuData.datasets[0].data.shift(); cpuData.datasets[0].data.push(data.cpu_percent); cpuChart.update(); // RAM-Auslastung aktualisieren document.getElementById('memory-percent').textContent = `${data.memory.percent.toFixed(1)}%`; document.getElementById('memory-used').textContent = formatBytes(data.memory.used); document.getElementById('memory-available').textContent = formatBytes(data.memory.available); document.getElementById('memory-total').textContent = formatBytes(data.memory.total); // Memory-Chart aktualisieren memoryData.datasets[0].data = [data.memory.percent, 100 - data.memory.percent]; memoryChart.update(); // Disk-Chart aktualisieren oder initialisieren, wenn noch nicht vorhanden if (data.disk_usage && data.disk_usage.length > 0) { updateDiskChart(data.disk_usage); } } function updateDiskChart(diskData) { if (!diskChart) { // Chart initialisieren, wenn noch nicht vorhanden const labels = diskData.map(disk => disk.mountpoint); const usedData = diskData.map(disk => disk.used); const freeData = diskData.map(disk => disk.free); const data = { labels: labels, datasets: [ { label: 'Verwendet', data: usedData, backgroundColor: 'rgba(231, 76, 60, 0.7)' }, { label: 'Frei', data: freeData, backgroundColor: 'rgba(46, 204, 113, 0.7)' } ] }; const options = { responsive: true, maintainAspectRatio: false, scales: { x: { stacked: true }, y: { stacked: true, ticks: { callback: value => formatBytes(value) } } } }; const diskCtx = document.getElementById('disk-usage-chart').getContext('2d'); diskChart = new Chart(diskCtx, { type: 'bar', data: data, options: options }); } else { // Chart aktualisieren diskChart.data.labels = diskData.map(disk => disk.mountpoint); diskChart.data.datasets[0].data = diskData.map(disk => disk.used); diskChart.data.datasets[1].data = diskData.map(disk => disk.free); diskChart.update(); } } // Docker-Informationen laden function loadDockerStatus() { fetch('/api/docker/status') .then(response => response.json()) .then(data => { if (data.success) { updateDockerStatus(data); } }) .catch(error => { console.error('Fehler beim Laden des Docker-Status:', error); }); } function updateDockerStatus(data) { // Docker-Version und Info aktualisieren document.getElementById('docker-version').textContent = data.info.version || 'Nicht verfügbar'; document.getElementById('docker-api-version').textContent = data.info.api_version || 'Nicht verfügbar'; document.getElementById('docker-os').textContent = data.info.os || 'Nicht verfügbar'; document.getElementById('docker-status').textContent = data.info.status || 'Nicht verfügbar'; // Anzahl aktiver Container aktualisieren const activeContainers = data.containers.filter(c => c.state === 'running').length; document.getElementById('active-containers').textContent = activeContainers; // Container-Status-Chart aktualisieren oder initialisieren updateContainerStatusChart(data.containers); // Container-Tabelle aktualisieren updateContainerTable(data.containers); // Container-Select für Logs aktualisieren updateContainerSelect(data.containers); } function updateContainerStatusChart(containers) { // Zähle Container nach Status const statusCounts = { running: 0, exited: 0, created: 0, other: 0 }; containers.forEach(container => { if (container.state === 'running') { statusCounts.running++; } else if (container.state === 'exited') { statusCounts.exited++; } else if (container.state === 'created') { statusCounts.created++; } else { statusCounts.other++; } }); if (!containerStatusChart) { // Chart initialisieren const data = { labels: ['Laufend', 'Beendet', 'Erstellt', 'Andere'], datasets: [{ data: [ statusCounts.running, statusCounts.exited, statusCounts.created, statusCounts.other ], backgroundColor: [ '#2ecc71', // Grün für laufende Container '#e74c3c', // Rot für beendete Container '#3498db', // Blau für erstellte Container '#95a5a6' // Grau für andere Status ] }] }; const ctx = document.getElementById('container-status-chart').getContext('2d'); containerStatusChart = new Chart(ctx, { type: 'doughnut', data: data, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'right' } } } }); } else { // Chart aktualisieren containerStatusChart.data.datasets[0].data = [ statusCounts.running, statusCounts.exited, statusCounts.created, statusCounts.other ]; containerStatusChart.update(); } } function updateContainerTable(containers) { const tableBody = document.querySelector('#container-table tbody'); if (containers.length === 0) { tableBody.innerHTML = 'Keine Container gefunden'; return; } tableBody.innerHTML = ''; containers.forEach(container => { const row = document.createElement('tr'); row.className = `container-row ${container.state}`; row.setAttribute('data-id', container.id); // Container-Status-Klasse let statusClass = ''; if (container.state === 'running') { statusClass = 'status-good'; } else if (container.state === 'exited') { statusClass = 'status-error'; } else { statusClass = 'status-warning'; } // Container-Name und Info row.innerHTML = `
${container.name}
${container.image}
${container.state} ${container.cpu || 'N/A'} ${container.memory ? formatBytes(container.memory) : 'N/A'} ${container.ports || 'N/A'} `; tableBody.appendChild(row); }); } function updateContainerSelect(containers) { const select = document.getElementById('log-container-select'); // Alle Einträge außer dem ersten leeren löschen while (select.options.length > 1) { select.remove(1); } // Container sortieren (laufende zuerst) const sortedContainers = [...containers].sort((a, b) => { if (a.state === 'running' && b.state !== 'running') return -1; if (a.state !== 'running' && b.state === 'running') return 1; return a.name.localeCompare(b.name); }); // Container zum Select hinzufügen sortedContainers.forEach(container => { const option = document.createElement('option'); option.value = container.id; option.textContent = `${container.name} (${container.state})`; // Laufende Container hervorheben if (container.state === 'running') { option.className = 'container-running'; } select.appendChild(option); }); } // Container-Aktionen function inspectContainer(containerId) { fetch(`/api/docker/inspect/${containerId}`) .then(response => response.json()) .then(data => { if (data.success) { showContainerInspect(data.data); } else { showMessage(`Fehler: ${data.error}`, true); } }) .catch(error => { showMessage(`Fehler bei der Container-Inspektion: ${error}`, true); }); } function showContainerInspect(inspectData) { // Hier können wir ein Modal oder einen anderen Bereich für die Anzeige der Inspektionsdaten implementieren const detailsHTML = `

${inspectData.name}

${inspectData.id.substring(0, 12)}

Allgemein

Image${inspectData.image}
Erstellt${new Date(inspectData.created).toLocaleString()}
Status${inspectData.state.Status}
Gestartet${inspectData.state.StartedAt ? new Date(inspectData.state.StartedAt).toLocaleString() : 'Nicht gestartet'}

Netzwerk

${Object.keys(inspectData.networks).map(net => `
${net}
IP: ${inspectData.networks[net].IPAddress}
Gateway: ${inspectData.networks[net].Gateway}
`).join('')}

Ports

${inspectData.ports ? Object.keys(inspectData.ports).map(port => `
${port} → ${inspectData.ports[port] ? inspectData.ports[port].map(p => `${p.HostIp}:${p.HostPort}`).join(', ') : 'Nicht gemappt'}
`).join('') : 'Keine Ports'}
`; // Hier könnten wir ein Modal anzeigen oder die Daten in einen bestimmten Bereich einfügen // Für dieses Beispiel verwenden wir ein einfaches Alert, aber in Produktion sollte ein ordentliches Modal verwendet werden alert(`Container-Details:\n${inspectData.name}\n${inspectData.image}\nStatus: ${inspectData.state.Status}`); } function restartContainer(containerId) { if (confirm('Möchten Sie diesen Container wirklich neu starten?')) { fetch(`/api/docker/restart/${containerId}`, { method: 'POST' }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(`Container erfolgreich neu gestartet`, false); setTimeout(() => loadDockerStatus(), 2000); } else { showMessage(`Fehler: ${data.error}`, true); } }) .catch(error => { showMessage(`Fehler beim Neustart des Containers: ${error}`, true); }); } } function viewContainerLogs(containerId) { // Container im Log-Select auswählen document.getElementById('log-container-select').value = containerId; // Logs laden loadContainerLogs(); } function loadContainerLogs() { const containerId = document.getElementById('log-container-select').value; const filter = document.getElementById('log-filter').value; if (!containerId) { showMessage('Bitte wählen Sie einen Container aus', true); return; } const logsContainer = document.getElementById('container-logs'); logsContainer.innerHTML = '
Lade Logs...
'; fetch(`/api/docker/logs/${containerId}${filter ? `?filter=${filter}` : ''}`) .then(response => response.json()) .then(data => { if (data.success) { if (data.logs.length === 0) { logsContainer.innerHTML = '
Keine Logs gefunden
'; } else { const logLines = data.logs.split('\n'); // Logs mit Syntax-Highlighting und Fehlerhervorhebung anzeigen logsContainer.innerHTML = `
Logs für Container: ${data.container_name}
Zeilen: ${logLines.length}
${formatLogs(logLines)}
`; } } else { logsContainer.innerHTML = `
Fehler: ${data.error}
`; } }) .catch(error => { logsContainer.innerHTML = `
Fehler beim Laden der Logs: ${error}
`; }); } function formatLogs(logLines) { return logLines.map(line => { // Zeitstempel hervorheben line = line.replace(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z)/g, '$1'); // Fehler hervorheben if (/error|exception|fail|critical/i.test(line)) { return `
${line}
`; } // Warnungen hervorheben if (/warning|warn/i.test(line)) { return `
${line}
`; } // Info-Meldungen hervorheben if (/info|information/i.test(line)) { return `
${line}
`; } return `
${line}
`; }).join(''); } function downloadContainerLogs() { const containerId = document.getElementById('log-container-select').value; if (!containerId) { showMessage('Bitte wählen Sie einen Container aus', true); return; } // Direkter Download über einen Link window.location.href = `/api/docker/logs/download/${containerId}`; } // Netzwerk-Funktionen function refreshNetworkInterfaces() { const container = document.getElementById('network-interfaces'); container.innerHTML = '
Lade Netzwerkschnittstellen...
'; fetch('/api/network/interfaces') .then(response => response.json()) .then(data => { if (data.success) { renderNetworkInterfaces(data.interfaces); } else { container.innerHTML = `
Fehler: ${data.error}
`; } }) .catch(error => { container.innerHTML = `
Fehler beim Laden der Netzwerkschnittstellen: ${error}
`; }); } function renderNetworkInterfaces(interfaces) { const container = document.getElementById('network-interfaces'); if (interfaces.length === 0) { container.innerHTML = '
Keine Netzwerkschnittstellen gefunden
'; return; } let html = ''; interfaces.forEach(iface => { html += `
${iface.name} ${iface.mac}

IPv4-Adressen

${iface.ipv4.length > 0 ? iface.ipv4.map(ip => `
IP: ${ip.addr}
Netzmaske: ${ip.netmask}
Broadcast: ${ip.broadcast || 'N/A'}
`).join('') : '
Keine IPv4-Adressen
'}
${iface.stats !== 'Nicht verfügbar' ? `

Statistiken

Gesendet: ${formatBytes(iface.stats.bytes_sent)}
Empfangen: ${formatBytes(iface.stats.bytes_recv)}
Pakete gesendet: ${iface.stats.packets_sent}
Pakete empfangen: ${iface.stats.packets_recv}
Fehler (Ein): ${iface.stats.errin}
Fehler (Aus): ${iface.stats.errout}
` : ''}
`; }); container.innerHTML = html; } function refreshActiveConnections() { const tableBody = document.querySelector('#connections-table tbody'); tableBody.innerHTML = 'Lade aktive Verbindungen...'; fetch('/api/network/active-connections') .then(response => response.json()) .then(data => { if (data.success) { renderActiveConnections(data.connections); } else { tableBody.innerHTML = `Fehler: ${data.error}`; } }) .catch(error => { tableBody.innerHTML = `Fehler beim Laden der aktiven Verbindungen: ${error}`; }); } function renderActiveConnections(connections) { const tableBody = document.querySelector('#connections-table tbody'); if (connections.length === 0) { tableBody.innerHTML = 'Keine aktiven Verbindungen gefunden'; return; } tableBody.innerHTML = ''; connections.forEach(conn => { const row = document.createElement('tr'); row.innerHTML = ` ${conn.local_address} ${conn.remote_address} ${conn.status} ${conn.process ? `${conn.process.name} (PID: ${conn.pid})` : `PID: ${conn.pid || 'N/A'}`} `; tableBody.appendChild(row); }); } function loadRouteTable() { const container = document.getElementById('route-table'); container.textContent = 'Lade Routing-Tabelle...'; fetch('/api/network/route-table') .then(response => response.json()) .then(data => { if (data.success) { container.textContent = data.route_table; } else { container.textContent = `Fehler: ${data.error}`; } }) .catch(error => { container.textContent = `Fehler beim Laden der Routing-Tabelle: ${error}`; }); } // Diagnose-Funktionen function pingHost() { const host = document.getElementById('ping-host').value; if (!host) { showMessage('Bitte geben Sie einen Host ein', true); return; } document.getElementById('ping-result').innerHTML = '
Ping wird durchgeführt...
'; document.getElementById('ping-result').className = 'status'; fetch(`/ping/${host}`) .then(response => response.json()) .then(data => { let html = `

Ping-Ergebnisse für ${host}

`; html += `
${data.output}
`; document.getElementById('ping-result').innerHTML = html; document.getElementById('ping-result').className = data.success ? 'status status-good' : 'status status-error'; }) .catch(error => { document.getElementById('ping-result').innerHTML = `
Fehler beim Durchführen des Ping-Tests: ${error}
`; document.getElementById('ping-result').className = 'status status-error'; }); } function tracerouteHost() { const host = document.getElementById('traceroute-host').value; if (!host) { showMessage('Bitte geben Sie einen Host ein', true); return; } document.getElementById('traceroute-result').innerHTML = '
Traceroute wird durchgeführt...
'; document.getElementById('traceroute-result').className = 'status'; fetch(`/traceroute/${host}`) .then(response => response.json()) .then(data => { let html = `

Traceroute-Ergebnisse für ${host}

`; html += `
${data.output}
`; if (data.error) { html += `
Fehler: ${data.error}
`; } document.getElementById('traceroute-result').innerHTML = html; document.getElementById('traceroute-result').className = 'status'; }) .catch(error => { document.getElementById('traceroute-result').innerHTML = `
Fehler beim Durchführen des Traceroute: ${error}
`; document.getElementById('traceroute-result').className = 'status status-error'; }); } function dnsLookup() { const host = document.getElementById('dns-host').value; if (!host) { showMessage('Bitte geben Sie einen Hostnamen ein', true); return; } document.getElementById('dns-result').innerHTML = '
DNS-Abfrage wird durchgeführt...
'; document.getElementById('dns-result').className = 'status'; fetch(`/nslookup/${host}`) .then(response => response.json()) .then(data => { let html = `

DNS-Abfrageergebnisse für ${host}

`; html += `
${data.output}
`; if (data.error) { html += `
Fehler: ${data.error}
`; } document.getElementById('dns-result').innerHTML = html; document.getElementById('dns-result').className = 'status'; }) .catch(error => { document.getElementById('dns-result').innerHTML = `
Fehler bei der DNS-Abfrage: ${error}
`; document.getElementById('dns-result').className = 'status status-error'; }); } function startPortScan() { const host = document.getElementById('port-scan-host').value; const portRange = document.getElementById('port-scan-range').value; if (!host) { showMessage('Bitte geben Sie einen Host ein', true); return; } document.getElementById('port-scan-status').innerHTML = '
Port-Scan wird gestartet...
'; document.getElementById('port-scan-status').className = 'status'; // Tabelle leeren document.querySelector('#port-scan-table tbody').innerHTML = ''; fetch('/api/network/scan-ports', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ host: host, port_range: portRange }) }) .then(response => response.json()) .then(data => { if (data.success) { document.getElementById('port-scan-status').innerHTML = data.message; document.getElementById('port-scan-status').className = 'status status-good'; // Status-Polling starten pollPortScanStatus(); } else { document.getElementById('port-scan-status').innerHTML = `
Fehler: ${data.error}
`; document.getElementById('port-scan-status').className = 'status status-error'; } }) .catch(error => { document.getElementById('port-scan-status').innerHTML = `
Fehler beim Starten des Port-Scans: ${error}
`; document.getElementById('port-scan-status').className = 'status status-error'; }); } function checkPortScanStatus() { fetch('/api/network/scan-status') .then(response => response.json()) .then(data => { if (data.success) { if (data.status === 'running') { document.getElementById('port-scan-status').innerHTML = '
Port-Scan läuft...
'; document.getElementById('port-scan-status').className = 'status status-warning'; } else if (data.status === 'completed' && data.results) { renderPortScanResults(data.results); } else { document.getElementById('port-scan-status').innerHTML = data.message; document.getElementById('port-scan-status').className = 'status'; } } else { document.getElementById('port-scan-status').innerHTML = `
Fehler: ${data.error}
`; document.getElementById('port-scan-status').className = 'status status-error'; } }) .catch(error => { document.getElementById('port-scan-status').innerHTML = `
Fehler beim Abrufen des Port-Scan-Status: ${error}
`; document.getElementById('port-scan-status').className = 'status status-error'; }); } function pollPortScanStatus() { const intervalId = setInterval(() => { fetch('/api/network/scan-status') .then(response => response.json()) .then(data => { if (data.success) { if (data.status === 'running') { document.getElementById('port-scan-status').innerHTML = '
Port-Scan läuft...
'; document.getElementById('port-scan-status').className = 'status status-warning'; } else { // Scan ist abgeschlossen oder anderweitig beendet clearInterval(intervalId); if (data.status === 'completed' && data.results) { renderPortScanResults(data.results); } else { document.getElementById('port-scan-status').innerHTML = data.message; document.getElementById('port-scan-status').className = 'status'; } } } else { clearInterval(intervalId); document.getElementById('port-scan-status').innerHTML = `
Fehler: ${data.error}
`; document.getElementById('port-scan-status').className = 'status status-error'; } }) .catch(error => { clearInterval(intervalId); document.getElementById('port-scan-status').innerHTML = `
Fehler beim Abrufen des Port-Scan-Status: ${error}
`; document.getElementById('port-scan-status').className = 'status status-error'; }); }, 1000); } function renderPortScanResults(results) { const tableBody = document.querySelector('#port-scan-table tbody'); tableBody.innerHTML = ''; document.getElementById('port-scan-status').innerHTML = `
Scan für ${results.host} abgeschlossen
Ports: ${results.start_port}-${results.end_port}
Zeit: ${new Date(results.timestamp).toLocaleString()}
Offene Ports: ${results.open_ports.length}
`; document.getElementById('port-scan-status').className = 'status status-good'; if (results.open_ports.length === 0) { tableBody.innerHTML = 'Keine offenen Ports gefunden'; return; } results.open_ports.forEach(port => { const row = document.createElement('tr'); row.innerHTML = ` ${port.port} ${port.status} ${port.service} `; tableBody.appendChild(row); }); } function loadLogs() { const logType = document.getElementById('log-type').value; const lines = document.getElementById('log-lines').value; const container = document.getElementById('log-content'); container.innerHTML = '
Lade Logs...
'; fetch(`/api/logs/tail/${logType}?lines=${lines}`) .then(response => response.json()) .then(data => { if (data.success) { if (data.entries.length === 0) { container.innerHTML = '
Keine Logs gefunden
'; } else { container.innerHTML = `
Logs für: ${logType}
Zeilen: ${data.count}
${formatLogEntries(data.entries)}
`; } } else { container.innerHTML = `
Fehler: ${data.error}
`; } }) .catch(error => { container.innerHTML = `
Fehler beim Laden der Logs: ${error}
`; }); } function formatLogEntries(entries) { return entries.map(line => { // Zeitstempel hervorheben line = line.replace(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(,\d+)?)/g, '$1'); // Fehler hervorheben if (/error|exception|fail|critical/i.test(line)) { return `
${line}
`; } // Warnungen hervorheben if (/warning|warn/i.test(line)) { return `
${line}
`; } // Info-Meldungen hervorheben if (/info|information/i.test(line)) { return `
${line}
`; } // Debug-Meldungen hervorheben if (/debug/i.test(line)) { return `
${line}
`; } return `
${line}
`; }).join(''); } function analyzeLogs() { const logType = document.getElementById('log-type').value; const container = document.getElementById('log-content'); container.innerHTML = '
Analysiere Logs...
'; fetch(`/api/logs/analyze?type=${logType}`) .then(response => response.json()) .then(data => { if (data.success) { if (data.analysis.error_count === 0 && data.analysis.warning_count === 0) { container.innerHTML = '
Keine Fehler oder Warnungen in den Logs gefunden
'; } else { let html = `
Log-Analyse für: ${logType}
Fehler: ${data.analysis.error_count}, Warnungen: ${data.analysis.warning_count}
`; if (data.analysis.errors.length > 0) { html += '

Fehler

'; html += '
'; data.analysis.errors.forEach(error => { html += `
${error.timestamp}
${error.message}
`; }); html += '
'; } if (data.analysis.warnings.length > 0) { html += '

Warnungen

'; html += '
'; data.analysis.warnings.forEach(warning => { html += `
${warning.timestamp}
${warning.message}
`; }); html += '
'; } container.innerHTML = html; } } else { container.innerHTML = `
Fehler: ${data.error}
`; } }) .catch(error => { container.innerHTML = `
Fehler bei der Log-Analyse: ${error}
`; }); } function checkHealth() { const banner = document.getElementById('systemHealthBanner'); banner.style.display = 'flex'; banner.className = 'system-health-banner checking'; banner.innerHTML = `
Systemstatus wird geprüft...
`; fetch('/healthcheck') .then(response => response.json()) .then(data => { let statusClass = ''; let icon = ''; if (data.status === 'healthy') { statusClass = 'healthy'; icon = ''; } else if (data.status === 'warning') { statusClass = 'warning'; icon = ''; } else { statusClass = 'critical'; icon = ''; } let statusHTML = `
${icon}
Systemstatus: ${data.status.toUpperCase()}
`; // Einzelne Komponenten hinzufügen Object.keys(data.checks).forEach(component => { const check = data.checks[component]; let componentIcon = ''; if (check.overall === 'healthy') { componentIcon = ''; } else if (check.overall === 'warning') { componentIcon = ''; } else { componentIcon = ''; } statusHTML += `
${componentIcon} ${component}: ${check.status}
`; }); statusHTML += `
`; banner.className = `system-health-banner ${statusClass}`; banner.innerHTML = statusHTML; // Banner nach 10 Sekunden ausblenden, wenn es nicht kritisch ist if (data.status !== 'critical') { setTimeout(() => { if (banner.className.includes(statusClass)) { banner.style.display = 'none'; } }, 10000); } }) .catch(error => { banner.className = 'system-health-banner critical'; banner.innerHTML = `
Fehler bei der Systemstatus-Prüfung: ${error}
`; }); } function refreshPage() { window.location.reload(); } // Konfiguration function saveConfig() { const config = { backend_hostname: document.getElementById('backend_hostname').value, backend_port: parseInt(document.getElementById('backend_port').value, 10), frontend_hostname: document.getElementById('frontend_hostname').value, frontend_port: parseInt(document.getElementById('frontend_port').value, 10) }; fetch('/save-config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }) .then(response => response.json()) .then(data => { if (data.success) { showMessage('Konfiguration erfolgreich gespeichert', false); // Nach kurzer Verzögerung die Seite neu laden setTimeout(() => { window.location.reload(); }, 1500); } else { showMessage(`Fehler: ${data.message}`, true); } }) .catch(error => { showMessage(`Fehler: ${error}`, true); }); } function testConnection() { const config = { backend_hostname: document.getElementById('backend_hostname').value, backend_port: parseInt(document.getElementById('backend_port').value, 10), frontend_hostname: document.getElementById('frontend_hostname').value, frontend_port: parseInt(document.getElementById('frontend_port').value, 10) }; fetch('/test-connection', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }) .then(response => response.json()) .then(data => { if (data.success) { let message = 'Backend: '; message += data.results.backend.ping ? 'Ping erfolgreich' : 'Ping fehlgeschlagen'; message += ', '; message += data.results.backend.connection ? 'Verbindung erfolgreich' : 'Verbindung fehlgeschlagen'; message += ' | Frontend: '; message += data.results.frontend.ping ? 'Ping erfolgreich' : 'Ping fehlgeschlagen'; message += ', '; message += data.results.frontend.connection ? 'Verbindung erfolgreich' : 'Verbindung fehlgeschlagen'; showMessage(message, false); } else { showMessage(`Fehler: ${data.message}`, true); } }) .catch(error => { showMessage(`Fehler: ${error}`, true); }); } function syncFrontend() { fetch('/sync-frontend', { method: 'POST' }) .then(response => response.json()) .then(data => { if (data.success) { showMessage('Frontend erfolgreich synchronisiert', false); } else { showMessage(`Fehler: ${data.message}`, true); } }) .catch(error => { showMessage(`Fehler: ${error}`, true); }); }