From 68a0ea234b069bcae6b26516fb3f43724b05940f Mon Sep 17 00:00:00 2001 From: wood chen Date: Thu, 5 Dec 2024 01:28:17 +0800 Subject: [PATCH] fix(metrics): refine chart handling and data validation in metrics dashboard - Updated chart management logic to ensure proper destruction of existing charts before creating new ones, preventing memory leaks. - Enhanced data validation by adding a check for the data format returned from the API, ensuring it is an array before processing. - Consolidated chart options into a common configuration for improved consistency across different charts. - Improved the updateChart function to handle canvas element existence checks and streamline chart creation. These changes enhance the performance and reliability of the metrics dashboard, providing clearer visualizations and better data handling. --- internal/handler/metrics.go | 127 +++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/internal/handler/metrics.go b/internal/handler/metrics.go index a3e024e..6b02cad 100644 --- a/internal/handler/metrics.go +++ b/internal/handler/metrics.go @@ -629,7 +629,7 @@ var metricsTemplate = ` // 每5秒自动刷新 setInterval(refreshMetrics, 5000); - // 修改图表加载相关代码 + // 修改图表相关代码 let currentCharts = { requests: null, errorRate: null, @@ -644,6 +644,11 @@ var metricsTemplate = ` }) .then(response => response.json()) .then(data => { + if (!Array.isArray(data)) { + console.error('Invalid data format'); + return; + } + // 反转数据顺序,使时间从左到右 data.reverse(); @@ -658,27 +663,64 @@ var metricsTemplate = ` } }); - // 更新图表配置,添加时间轴方向设置 - const chartOptions = { + const commonOptions = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false + } + }, scales: { x: { - reverse: false // 确保时间轴从左到右 + display: true, + grid: { + display: false + } + }, + y: { + beginAtZero: true, + grid: { + drawBorder: false + } + } + }, + elements: { + line: { + tension: 0.4 + }, + point: { + radius: 2 } } }; // 更新或创建图表 - updateChart('requestsChart', currentCharts.requests, labels, data, '请求数', - m => m.total_requests, '#007bff', chartOptions); - updateChart('errorRateChart', currentCharts.errorRate, labels, data, '错误率 (%)', - m => m.error_rate * 100, '#dc3545', chartOptions); - updateChart('bytesChart', currentCharts.bytes, labels, data, '流量 (MB)', - m => m.total_bytes / (1024 * 1024), '#28a745', chartOptions); - }); + updateChart('requestsChart', 'requests', labels, data, '请求数', + m => m.total_requests, '#007bff', commonOptions); + updateChart('errorRateChart', 'errorRate', labels, data, '错误率 (%)', + m => m.error_rate * 100, '#dc3545', commonOptions); + updateChart('bytesChart', 'bytes', labels, data, '流量 (MB)', + m => m.total_bytes / (1024 * 1024), '#28a745', commonOptions); + }) + .catch(error => console.error('Error:', error)); } - function updateChart(canvasId, chartInstance, labels, data, label, valueGetter, color, options = {}) { - const ctx = document.getElementById(canvasId).getContext('2d'); + function updateChart(canvasId, chartKey, labels, data, label, valueGetter, color, options) { + // 确保 canvas 元素存在 + const canvas = document.getElementById(canvasId); + if (!canvas) { + console.error('Canvas element ' + canvasId + ' not found'); + return; + } + + // 如果存在旧图表,销毁它 + if (currentCharts[chartKey]) { + currentCharts[chartKey].destroy(); + currentCharts[chartKey] = null; + } + + const ctx = canvas.getContext('2d'); const chartData = { labels: labels, datasets: [{ @@ -686,52 +728,16 @@ var metricsTemplate = ` data: data.map(valueGetter), borderColor: color, backgroundColor: color + '20', - fill: true, - tension: 0.4 + fill: true }] }; - if (chartInstance) { - chartInstance.data = chartData; - chartInstance.options = { - ...chartInstance.options, - ...options, - animation: false - }; - chartInstance.update(); - } else { - // 创建新图表前先销毁旧的 - if (currentCharts[canvasId.replace('Chart', '')]) { - currentCharts[canvasId.replace('Chart', '')].destroy(); - } - - // 创建新图表 - const newChart = new Chart(ctx, { - type: 'line', - data: chartData, - options: { - ...options, - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - display: false - } - }, - scales: { - y: { - beginAtZero: true - }, - x: { - reverse: false - } - } - } - }); - - // 更新 currentCharts 对象 - currentCharts[canvasId.replace('Chart', '')] = newChart; - } + // 创建新图表 + currentCharts[chartKey] = new Chart(ctx, { + type: 'line', + data: chartData, + options: options + }); } // 时间范围按钮处理 @@ -739,16 +745,19 @@ var metricsTemplate = ` btn.addEventListener('click', function() { document.querySelectorAll('.time-btn').forEach(b => b.classList.remove('active')); this.classList.add('active'); - loadHistoryData(this.dataset.hours); + loadHistoryData(parseInt(this.dataset.hours)); }); }); // 初始加载历史数据 - loadHistoryData(24); + document.addEventListener('DOMContentLoaded', function() { + loadHistoryData(24); + }); - + + `