From 1440eec7ed1c07fcb2ac4316d7b9f29ba86fd772 Mon Sep 17 00:00:00 2001 From: wood chen Date: Thu, 5 Dec 2024 11:09:44 +0800 Subject: [PATCH] refactor(metrics): remove deprecated metrics history endpoint and clean up related code - Removed the MetricsHistoryHandler and associated historical data export functionality to streamline the metrics handling process. - Updated the metrics template to improve label translations and ensure default values are used for optional data fields. - Enhanced the JavaScript code for metrics display by adding checks for undefined data arrays, improving robustness. - Cleaned up unused variables and functions to maintain code clarity and reduce complexity. These changes simplify the metrics system by eliminating outdated features and improving the overall reliability of data presentation. --- internal/handler/metrics.go | 276 +----------------------------------- main.go | 3 - 2 files changed, 7 insertions(+), 272 deletions(-) diff --git a/internal/handler/metrics.go b/internal/handler/metrics.go index f4df1c8..9a41e81 100644 --- a/internal/handler/metrics.go +++ b/internal/handler/metrics.go @@ -2,7 +2,6 @@ package handler import ( "encoding/json" - "fmt" "log" "net/http" "proxy-go/internal/metrics" @@ -512,7 +511,7 @@ var metricsTemplate = `
- 每秒传输 + 每传输
@@ -571,7 +570,7 @@ var metricsTemplate = `

历史数据

-
+
-
- 显示最近30天的数据
@@ -646,7 +639,7 @@ var metricsTemplate = ` // 更新状态码计 const statusCodesHtml = '
' + - Object.entries(data.status_code_stats) + Object.entries(data.status_code_stats || {}) .sort((a, b) => a[0].localeCompare(b[0])) .map(([status, count]) => { const firstDigit = status.charAt(0); @@ -664,7 +657,7 @@ var metricsTemplate = ` statusCodesContainer.innerHTML = statusCodesHtml; // 更新热门路径 - const topPathsHtml = data.top_paths.map(path => + const topPathsHtml = (data.top_paths || []).map(path => '' + '' + path.path + '' + '' + path.request_count + '' + @@ -676,7 +669,7 @@ var metricsTemplate = ` document.querySelector('#topPaths tbody').innerHTML = topPathsHtml; // 更新最近请求 - const recentRequestsHtml = data.recent_requests.map(req => + const recentRequestsHtml = (data.recent_requests || []).map(req => '' + '' + formatDate(req.Time) + '' + '' + req.Path + '' + @@ -689,7 +682,7 @@ var metricsTemplate = ` document.querySelector('#recentRequests tbody').innerHTML = recentRequestsHtml; // 更新热门引用来源 - const topReferersHtml = data.top_referers.map(referer => + const topReferersHtml = (data.top_referers || []).map(referer => '' + '' + referer.path + '' + '' + referer.request_count + '' + @@ -732,187 +725,6 @@ var metricsTemplate = ` .catch(error => showError(error.message)); } - // 初始加载 - refreshMetrics(); - - // 每5秒自动刷新 - setInterval(refreshMetrics, 5000); - - // 修改图表相关代码 - let currentCharts = { - requests: null, - errorRate: null, - bytes: null - }; - - function loadHistoryData(hours) { - const chartContainer = document.getElementById('historyChart'); - chartContainer.classList.add('loading'); - - fetch('/metrics/history?hours=' + hours, { - headers: { - 'Authorization': 'Bearer ' + token - } - }) - .then(response => response.json()) - .then(data => { - if (!Array.isArray(data)) { - console.error('Invalid data format'); - return; - } - - // 反转数据顺序,使时间从左到右 - data.reverse(); - - const labels = data.map(m => { - const date = new Date(m.timestamp); - if (hours <= 24) { - return date.toLocaleTimeString(); - } else if (hours <= 168) { - return date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); - } else { - return date.toLocaleDateString(); - } - }); - - const commonOptions = { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { - display: false - }, - tooltip: { - callbacks: { - label: function(context) { - let label = context.dataset.label || ''; - if (label) { - label += ': '; - } - if (context.parsed.y !== null) { - if (context.chart.canvas.id === 'bytesChart') { - label += formatBytes(context.parsed.y * 1024 * 1024); - } else if (context.chart.canvas.id === 'errorRateChart') { - label += context.parsed.y.toFixed(2) + '%'; - } else { - label += context.parsed.y.toLocaleString(); - } - } - return label; - }, - title: function(tooltipItems) { - const date = new Date(tooltipItems[0].label); - return date.toLocaleString(); - } - } - } - }, - scales: { - x: { - display: true, - grid: { - display: false - }, - ticks: { - maxRotation: 45, - minRotation: 45, - autoSkip: true, - maxTicksLimit: 20 - } - }, - y: { - beginAtZero: true, - grid: { - drawBorder: false - }, - ticks: { - callback: function(value) { - if (this.chart.canvas.id === 'bytesChart') { - return formatBytes(value * 1024 * 1024); - } - return value; - } - } - } - }, - elements: { - line: { - tension: 0.4 - }, - point: { - radius: 2, - hitRadius: 10, - hoverRadius: 5 - } - }, - interaction: { - mode: 'nearest', - axis: 'x', - intersect: false - } - }; - - // 更新或创建图表 - 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); - }) - .finally(() => { - chartContainer.classList.remove('loading'); - }); - } - - 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: [{ - label: label, - data: data.map(valueGetter), - borderColor: color, - backgroundColor: color + '20', - fill: true - }] - }; - - // 创建新图表 - currentCharts[chartKey] = new Chart(ctx, { - type: 'line', - data: chartData, - options: options - }); - } - - // 时间范围按钮处理 - document.querySelectorAll('.time-btn').forEach(btn => { - btn.addEventListener('click', function() { - document.querySelectorAll('.time-btn').forEach(b => b.classList.remove('active')); - this.classList.add('active'); - loadHistoryData(parseFloat(this.dataset.hours)); - }); - }); - - // 初始加载历史数据 - document.addEventListener('DOMContentLoaded', function() { - loadHistoryData(24); - }); - let refreshTimer; function setupAutoRefresh() { @@ -935,51 +747,10 @@ var metricsTemplate = ` } document.addEventListener('DOMContentLoaded', function() { - loadHistoryData(24); + refreshMetrics(); // 立即加载一次数据 setupAutoRefresh(); }); - - function exportData() { - const activeBtn = document.querySelector('.time-btn.active'); - const hours = parseInt(activeBtn.dataset.hours); - - fetch('/metrics/history?hours=' + hours, { - headers: { - 'Authorization': 'Bearer ' + token - } - }) - .then(response => response.json()) - .then(data => { - const csv = convertToCSV(data); - downloadCSV(csv, 'metrics_' + hours + 'h_' + new Date().toISOString() + '.csv'); - }) - .catch(error => showError('导出失败: ' + error.message)); - } - - function convertToCSV(data) { - const headers = ['时间', '请求数', '错误数', '流量(MB)', '错误率(%)']; - const rows = data.map(row => [ - row.timestamp, - row.total_requests, - row.total_errors, - (row.total_bytes / (1024 * 1024)).toFixed(2), - (row.error_rate * 100).toFixed(2) - ]); - return [headers, ...rows].map(row => row.join(',')).join('\n'); - } - - function downloadCSV(csv, filename) { - const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = filename; - link.click(); - } - - - - ` @@ -1042,39 +813,6 @@ func (h *ProxyHandler) MetricsAuthHandler(w http.ResponseWriter, r *http.Request }) } -// 添加历史数据查询接口 -func (h *ProxyHandler) MetricsHistoryHandler(w http.ResponseWriter, r *http.Request) { - collector := metrics.GetCollector() - metrics := collector.GetHistoricalData() - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(metrics) -} - -// 辅助函数:解析延迟字符串 -func parseLatency(latency string) (float64, error) { - var value float64 - var unit string - _, err := fmt.Sscanf(latency, "%f %s", &value, &unit) - if err != nil { - return 0, err - } - - // 根据单位转换为毫秒 - switch unit { - case "μs": - value = value / 1000 // 微秒转毫秒 - case "ms": - // 已经是毫秒 - case "s": - value = value * 1000 // 秒转毫秒 - default: - return 0, fmt.Errorf("unknown unit: %s", unit) - } - - return value, nil -} - // 添加安全的类型转换辅助函数 func safeStatusCodeStats(v interface{}) map[string]int64 { if v == nil { diff --git a/main.go b/main.go index b873bb2..2a045e3 100644 --- a/main.go +++ b/main.go @@ -89,9 +89,6 @@ func main() { case "/metrics/dashboard": proxyHandler.MetricsDashboardHandler(w, r) return - case "/metrics/history": - proxyHandler.AuthMiddleware(proxyHandler.MetricsHistoryHandler)(w, r) - return } // 遍历所有处理器