document.addEventListener('DOMContentLoaded', function () { const ctx = document.getElementById('peerHistoryChart').getContext('2d'); let chart; let currentRange = '24h'; const timeRangeButtons = document.querySelectorAll('.btn-group .btn'); timeRangeButtons.forEach(button => { button.addEventListener('click', () => { currentRange = button.getAttribute('data-range'); timeRangeButtons.forEach(btn => btn.classList.remove('active')); button.classList.add('active'); fetchDataAndRenderChart(currentRange); }); }); function updateChartScale(chartInstance) { const visibleDatasets = chartInstance.data.datasets.filter(dataset => !dataset.hidden); let pointsForScaling = []; visibleDatasets.forEach(dataset => { const validData = (dataset.data || []).filter(val => typeof val === 'number'); pointsForScaling.push(...validData); }); let suggestedMin, suggestedMax; if (pointsForScaling.length > 0) { const minValue = Math.min(...pointsForScaling); const maxValue = Math.max(...pointsForScaling); const padding = 200; suggestedMin = Math.floor(minValue - padding); suggestedMax = Math.ceil(maxValue + padding); } else { const allPoints = chartInstance.data.datasets.flatMap(d => d.data || []).filter(v => typeof v === 'number'); if (allPoints.length > 0) { const maxVal = Math.max(...allPoints); suggestedMin = 0; suggestedMax = maxVal + 200; } else { suggestedMin = 0; suggestedMax = 1000; } } chartInstance.options.scales.y.min = suggestedMin; chartInstance.options.scales.y.max = suggestedMax; chartInstance.update(); } async function fetchDataAndRenderChart(range) { try { const response = await fetch(`/bgp/peer/${neighborIp}/history?range=${range}`); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); renderChart(data); } catch (error) { console.error('Error fetching chart data:', error); const chartContainer = document.querySelector('.achart-wrapper-chart'); if (chartContainer) { chartContainer.innerHTML = '

Could not load chart data.

'; } } } function renderChart(data) { if (chart) { chart.destroy(); } const findLastValue = (arr) => { if (!arr) return 'N/A'; for (let i = arr.length - 1; i >= 0; i--) { if (arr[i] !== null && typeof arr[i] !== 'undefined') { return arr[i]; } } return 'N/A'; }; const receivedLastValue = findLastValue(data.received); const sentLastValue = findLastValue(data.sent); const receivedLabel = `Prefixes Received: ${receivedLastValue.toLocaleString()}`; const sentLabel = `Prefixes Sent: ${sentLastValue.toLocaleString()}`; const receivedData = (data.received || []).filter(val => typeof val === 'number'); const sentData = (data.sent || []).filter(val => typeof val === 'number'); const maxReceived = receivedData.length > 0 ? Math.max(...receivedData) : -Infinity; const maxSent = sentData.length > 0 ? Math.max(...sentData) : -Infinity; const isReceivedHidden = maxReceived < maxSent; chart = new Chart(ctx, { type: 'line', data: { labels: data.labels || [], datasets: [ { label: receivedLabel, data: data.received || [], borderColor: 'rgb(54, 162, 235)', backgroundColor: 'rgba(54, 162, 235, 0.1)', borderWidth: 1.5, fill: true, pointRadius: 2, pointHoverRadius: 5, hidden: isReceivedHidden }, { label: sentLabel, data: data.sent || [], borderColor: 'rgb(255, 99, 132)', backgroundColor: 'rgba(255, 99, 132, 0.1)', borderWidth: 1.5, fill: true, pointRadius: 2, pointHoverRadius: 5, hidden: !isReceivedHidden } ] }, options: { responsive: true, maintainAspectRatio: false, interaction: { intersect: false, mode: 'index', }, scales: { x: { type: 'time', time: { unit: 'minute', stepSize: 10, displayFormats: { millisecond: 'HH:mm:ss.SSS', second: 'HH:mm:ss', minute: 'HH:mm', hour: 'HH:mm' } } }, y: { } }, plugins: { legend: { position: 'top', onClick: (e, legendItem, legend) => { const chartInstance = legend.chart; const index = legendItem.datasetIndex; chartInstance.data.datasets[index].hidden = !chartInstance.data.datasets[index].hidden; updateChartScale(chartInstance); } }, tooltip: { callbacks: { title: function(context) { if (!context[0]) return ''; const date = new Date(context[0].parsed.x); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); return `${day}-${month}-${year} ${hour}:${minute}`; }, label: function(context) { let label = context.dataset.label.split(':')[0] || ''; if (label) label += ': '; if (context.parsed.y !== null) { label += context.parsed.y.toLocaleString(); } return label; } } } } } }); updateChartScale(chart); } fetchDataAndRenderChart(currentRange); });