'use strict'; (function() { let chartInstance = null; /** * Berechnet statistische Kennzahlen aus den Spike-Daten. * @param {Array<{timestamp:number, type:string, cpu:int, value:number}>} spikeData * @returns {{median:number, p99:number, deltaTail:number}} */ function computeStats(spikeData) { if (!Array.isArray(spikeData) || spikeData.length === 0) { return { median: 0, p99: 0, deltaTail: 0 }; } const sorted = [...spikeData].sort((a, b) => a.value - b.value); const n = sorted.length; const median = sorted[Math.floor(n / 2)].value; const p99 = sorted[Math.floor(n * 0.99) - 1 >= 0 ? Math.floor(n * 0.99) - 1 : 0].value; const deltaTail = p99 - median; return { median, p99, deltaTail }; } /** * Erstellt oder aktualisiert das Diagramm mit neuen Spikedaten. * @param {Array<{timestamp:number, type:string, cpu:int, value:number}>} spikeData */ function renderSpikeChart(spikeData) { const container = document.getElementById('chart-container'); if (!container) return; // Falls eine vorhandene Instanz existiert, diese löschen if (chartInstance && typeof chartInstance.destroy === 'function') { chartInstance.destroy(); } // Daten für Chart.js vorbereiten const labels = spikeData.map(d => new Date(d.timestamp).toLocaleTimeString()); const values = spikeData.map(d => d.value); const canvas = document.createElement('canvas'); container.innerHTML = ''; container.appendChild(canvas); // Chart.js Initialisierung if (window.Chart) { chartInstance = new Chart(canvas.getContext('2d'), { type: 'line', data: { labels: labels, datasets: [{ label: 'P99 Spike Werte', data: values, borderColor: '#007ACC', backgroundColor: 'rgba(0, 122, 204, 0.2)', fill: true, pointRadius: 2 }] }, options: { responsive: true, scales: { x: { title: { display: true, text: 'Zeit' } }, y: { title: { display: true, text: 'Spike Wert' } } } } }); } else { // Fallback: einfache Textanzeige const info = document.createElement('div'); info.textContent = 'Chart-Komponente nicht verfügbar. Werteanzeige deaktiviert.'; container.innerHTML = ''; container.appendChild(info); } const stats = computeStats(spikeData); updateStatsPanel(stats); } /** * Aktualisiert statistische Kennwerte im UI. * @param {{median:number, p99:number, deltaTail:number}} stats */ function updateStatsPanel(stats) { const panel = document.querySelector('.stats-panel'); if (!panel) return; const medianEl = panel.querySelector('.stat-median'); const p99El = panel.querySelector('.stat-p99'); const deltaEl = panel.querySelector('.stat-delta'); if (medianEl) medianEl.textContent = stats.median.toFixed(2); if (p99El) p99El.textContent = stats.p99.toFixed(2); if (deltaEl) deltaEl.textContent = stats.deltaTail.toFixed(2); } window.ui = { renderSpikeChart, updateStatsPanel }; })();