From 8df86387ac804c5ff41e6a50cd946b248dee78f3 Mon Sep 17 00:00:00 2001 From: wood chen Date: Thu, 5 Dec 2024 09:22:33 +0800 Subject: [PATCH] refactor(metrics): enhance dashboard styles and optimize SQL queries - Updated CSS styles for the metrics dashboard, improving layout with flex properties and enhanced item presentation. - Modified the status code display to use a more organized structure, allowing for better alignment and spacing. - Changed the data type for avgLatency in SaveMetrics to int64 for consistency. - Implemented a context with timeout for database queries in GetRecentMetrics, improving performance and reliability. - Optimized SQL queries to limit result sets and enhance data retrieval efficiency. These changes improve the user experience and data presentation in the metrics dashboard, providing clearer insights into performance metrics. --- internal/handler/metrics.go | 39 ++++++++++++++++++------------------- internal/models/metrics.go | 25 +++++++++++++++--------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/internal/handler/metrics.go b/internal/handler/metrics.go index 23f2f54..d3275cb 100644 --- a/internal/handler/metrics.go +++ b/internal/handler/metrics.go @@ -396,30 +396,35 @@ var metricsTemplate = ` .status-row { display: flex; - flex-direction: column; - gap: 12px; + flex-wrap: wrap; + gap: 15px; + justify-content: flex-start; } - .status-labels, .status-values { + .status-item { display: flex; - justify-content: flex-start; - gap: 20px; + flex-direction: column; + align-items: center; + background: white; + padding: 10px; + border-radius: 6px; + min-width: 80px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .status-badge { - flex: 0 0 auto; text-align: center; padding: 4px 12px; border-radius: 4px; font-size: 12px; color: white; - min-width: 60px; + margin-bottom: 5px; } .metric-value { - flex: 0 0 auto; text-align: center; - min-width: 60px; + font-weight: bold; + color: #666; } .loading { position: relative; @@ -687,24 +692,18 @@ var metricsTemplate = ` // 更新状态码计 const statusCodesHtml = '
' + - '
' + Object.entries(data.status_code_stats) .sort((a, b) => a[0].localeCompare(b[0])) - .map(([status, _]) => { + .map(([status, count]) => { const firstDigit = status.charAt(0); const statusClass = (firstDigit >= '2' && firstDigit <= '5') ? 'status-' + firstDigit + 'xx' : 'status-other'; - return '' + status + ''; + return '
' + + '' + status + '' + + '' + count.toLocaleString() + '' + + '
'; }).join('') + - '
' + - '
' + - Object.entries(data.status_code_stats) - .sort((a, b) => a[0].localeCompare(b[0])) - .map(([_, count]) => { - return '' + count.toLocaleString() + ''; - }).join('') + - '
' + '
'; const statusCodesContainer = document.getElementById('statusCodes'); diff --git a/internal/models/metrics.go b/internal/models/metrics.go index 12e3560..fdd6311 100644 --- a/internal/models/metrics.go +++ b/internal/models/metrics.go @@ -1,6 +1,7 @@ package models import ( + "context" "database/sql" "fmt" "log" @@ -405,7 +406,7 @@ func (db *MetricsDB) SaveMetrics(stats map[string]interface{}) error { if !ok { return fmt.Errorf("invalid total_bytes type") } - avgLatency, ok := stats["avg_latency"].(float64) + avgLatency, ok := stats["avg_latency"].(int64) if !ok { return fmt.Errorf("invalid avg_latency type") } @@ -421,7 +422,7 @@ func (db *MetricsDB) SaveMetrics(stats map[string]interface{}) error { totalReqs, totalErrs, totalBytes, - int64(avgLatency), + avgLatency, errorRate, ) if err != nil { @@ -443,6 +444,10 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error cacheSize int64 } + // 添加查询超时 + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + // 处理小于1小时的情况 if hours <= 0 { hours = 0.5 // 30分钟 @@ -469,8 +474,8 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error timeStep = 1440 // 1天 } - // 修改查询逻辑,使用 strftime 来处理时间 - rows, err := db.DB.Query(` + // 修改查询逻辑,优化性能 + rows, err := db.DB.QueryContext(ctx, ` WITH RECURSIVE time_points(ts) AS ( SELECT strftime(?, 'now', 'localtime') @@ -478,18 +483,20 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error SELECT strftime(?, datetime(ts, '-' || ? || ' minutes')) FROM time_points WHERE ts > strftime(?, datetime('now', '-' || ? || ' hours', 'localtime')) - LIMIT 1000 + LIMIT ? -- 限制时间点数量 ), grouped_metrics AS ( SELECT strftime(?, timestamp) as group_time, MAX(total_requests) as period_requests, MAX(total_errors) as period_errors, - MAX(total_bytes) as period_bytes, - AVG(avg_latency) as avg_latency + MAX(total_bytes) as period_bytes, + AVG(avg_latency) as avg_latency FROM metrics_history WHERE timestamp >= datetime('now', '-' || ? || ' hours', 'localtime') + AND timestamp < datetime('now', 'localtime') -- 添加上限 GROUP BY group_time + LIMIT ? -- 限制结果数量 ) SELECT tp.ts as timestamp, @@ -500,8 +507,8 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error FROM time_points tp LEFT JOIN grouped_metrics m ON tp.ts = m.group_time ORDER BY timestamp DESC - LIMIT 1000 - `, interval, interval, timeStep, interval, hours, interval, hours) + LIMIT ? + `, interval, interval, timeStep, interval, hours, 1000, interval, hours, 1000, 1000) if err != nil { return nil, err }