// 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 = `
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 = `
${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 += `
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 = `
${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 = `
`;
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);
});
}