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
}