fix(metrics): enhance metrics chart rendering and data handling

- Updated the metrics chart rendering logic to reverse the data order for a more intuitive time progression from left to right.
- Introduced chart options to ensure the x-axis is not reversed, improving the clarity of time-based data visualization.
- Modified the updateChart function to accept additional options, allowing for more flexible chart configurations.
- Added a safeguard in GetRecentMetrics to return a default empty record instead of null when no metrics are available, enhancing data reliability.

These changes improve the user experience by providing clearer visualizations and ensuring consistent data handling in the metrics dashboard.
This commit is contained in:
wood chen 2024-12-05 01:13:11 +08:00
parent 8858c41419
commit 660e60576d
2 changed files with 59 additions and 25 deletions

View File

@ -644,6 +644,9 @@ var metricsTemplate = `
})
.then(response => response.json())
.then(data => {
// 反转数据顺序,使时间从左到右
data.reverse();
const labels = data.map(m => {
const date = new Date(m.timestamp);
if (hours <= 24) {
@ -655,53 +658,70 @@ var metricsTemplate = `
}
});
// 更新图表配置,添加时间轴方向设置
const chartOptions = {
scales: {
x: {
reverse: false // 确保时间轴从左到右
}
}
};
// 更新或创建图表
updateChart('requestsChart', currentCharts.requests, labels, data, '请求数',
m => m.total_requests, '#007bff');
m => m.total_requests, '#007bff', chartOptions);
updateChart('errorRateChart', currentCharts.errorRate, labels, data, '错误率 (%)',
m => m.error_rate * 100, '#dc3545');
m => m.error_rate * 100, '#dc3545', chartOptions);
updateChart('bytesChart', currentCharts.bytes, labels, data, '流量 (MB)',
m => m.total_bytes / (1024 * 1024), '#28a745');
m => m.total_bytes / (1024 * 1024), '#28a745', chartOptions);
});
}
function updateChart(canvasId, chartInstance, labels, data, label, valueGetter, color) {
function updateChart(canvasId, chartInstance, labels, data, label, valueGetter, color, options = {}) {
const ctx = document.getElementById(canvasId).getContext('2d');
if (chartInstance) {
chartInstance.data.labels = labels;
chartInstance.data.datasets[0].data = data.map(valueGetter);
chartInstance.update();
} else {
chartInstance = new Chart(ctx, {
type: 'line',
data: {
const chartData = {
labels: labels,
datasets: [{
label: label,
data: data.map(valueGetter),
borderColor: color,
tension: 0.1,
fill: false
backgroundColor: color + '20',
fill: true,
tension: 0.4
}]
},
};
if (chartInstance) {
chartInstance.data = chartData;
chartInstance.options = {
...chartInstance.options,
...options,
animation: false
};
chartInstance.update();
} else {
chartInstance = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
...options,
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
ticks: {
maxRotation: 45,
minRotation: 45
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true
},
x: {
reverse: false
}
}
}
});
if (canvasId === 'requestsChart') currentCharts.requests = chartInstance;
if (canvasId === 'errorRateChart') currentCharts.errorRate = chartInstance;
if (canvasId === 'bytesChart') currentCharts.bytes = chartInstance;
}
}

View File

@ -279,5 +279,19 @@ func (db *MetricsDB) GetRecentMetrics(hours int) ([]HistoricalMetrics, error) {
}
metrics = append(metrics, m)
}
// 如果没有数据,返回一个空的记录而不是 null
if len(metrics) == 0 {
now := time.Now()
metrics = append(metrics, HistoricalMetrics{
Timestamp: now.Format("2006-01-02 15:04:05"),
TotalRequests: 0,
TotalErrors: 0,
TotalBytes: 0,
ErrorRate: 0,
AvgLatency: 0,
})
}
return metrics, rows.Err()
}