/** * @file js/app.js * @description Entry logic: Initialisiert Anwendung, lädt Daten und orchestriert UI-Aktualisierungen. */ /** * Lädt Retry-Statistiken anhand optionaler Filterparameter. * @param {Object} [filters={}] - Optionale Filter (z.B. {stratum, policy_hash}). * @returns {Promise} Statistikdaten aus der API. */ const fetchRetryStats = async (filters = {}) => { const params = new URLSearchParams(filters); const url = params.toString() ? `/api/retry-stats?${params}` : '/api/retry-stats'; try { const response = await fetch(url); if (!response.ok) throw new Error(`API Error: ${response.status}`); return await response.json(); } catch (err) { console.error('Fehler beim Abrufen der Retry-Statistiken:', err); return null; } }; /** * Bindet Event-Listener an UI-Elemente für interaktive Filterung. * @returns {void} */ const bindUIEvents = () => { const stratumSelect = document.getElementById('filter-stratum'); const policySelect = document.getElementById('filter-policy'); if (stratumSelect) { stratumSelect.addEventListener('change', () => { refreshData({ stratum: stratumSelect.value, policy_hash: policySelect?.value }); }); } if (policySelect) { policySelect.addEventListener('change', () => { refreshData({ stratum: stratumSelect?.value, policy_hash: policySelect.value }); }); } const refreshButton = document.getElementById('btn-refresh'); if (refreshButton) { refreshButton.addEventListener('click', () => { refreshData({ stratum: stratumSelect?.value, policy_hash: policySelect?.value }); }); } }; /** * Aktualisiert Dashboard-Daten durch Abrufen und Rendern neuer Statistiken. * @param {Object} [filters={}] - Aktuelle Filterparameter. * @returns {Promise} */ const refreshData = async (filters = {}) => { const container = document.getElementById('dashboard'); if (!container) return; container.setAttribute('aria-busy', 'true'); const data = await fetchRetryStats(filters); if (!data) { container.innerHTML = '

Fehler beim Laden der Daten.

'; container.removeAttribute('aria-busy'); return; } renderDashboard(data); container.removeAttribute('aria-busy'); }; /** * Rendert die geladenen Daten ins Dashboard. * @param {Object} data - Datenobjekt aus API. */ const renderDashboard = (data) => { const { p95, p99, unknown_rate, healing_rate, stats } = data; const statsContainer = document.getElementById('dashboard'); if (!statsContainer) return; statsContainer.innerHTML = `

Performance-Kennzahlen

  • P95: ${p95 ?? '-'} ms
  • P99: ${p99 ?? '-'} ms

Raten

  • Unknown Rate: ${(unknown_rate * 100).toFixed(2)}%
  • Heilungsrate: ${(healing_rate * 100).toFixed(2)}%

Statistikdetails

Δt<0
Warnrate
Status
${Array.isArray(stats) && stats.length > 0 ? stats.map(s => `
${s.delta_negative}
${(s.warn_rate * 100).toFixed(2)}%
${s.status ?? 'n/a'}
`).join('') : '
Keine Daten
'}
`; }; /** * Initialisiert die Anwendung: Datenabruf und Event-Bindings. * @returns {Promise} */ const initApp = async () => { await refreshData(); bindUIEvents(); }; window.addEventListener('load', initApp);