Add static/js/pages/bgp_peer_graph.js

This commit is contained in:
Blackwhitebear8 2025-09-17 20:05:23 +02:00
parent d1e9e189a4
commit af95d2ec73

View file

@ -0,0 +1,187 @@
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 = '<p class="text-danger text-center">Could not load chart data.</p>';
}
}
}
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);
});