mirror of
https://github.com/woodchen-ink/proxy-go.git
synced 2025-07-18 16:41:54 +08:00
fix(metrics): update metrics dashboard styles and optimize SQL queries
- Changed text color in the metrics dashboard from white to black for better visibility. - Modified the layout of status codes to display in a row with improved alignment and spacing. - Enhanced CSS styles for the metrics dashboard, including adjustments to flex properties and background settings. - Updated SQL query in GetRecentMetrics to sort status codes, ensuring a more organized display of metrics. These changes improve the user experience and data presentation in the metrics dashboard, providing clearer insights into performance metrics.
This commit is contained in:
parent
ba691431f4
commit
3270bb5f36
@ -298,7 +298,7 @@ var metricsTemplate = `
|
|||||||
padding: 3px 8px;
|
padding: 3px 8px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: white;
|
color: black;
|
||||||
}
|
}
|
||||||
.status-2xx { background: #28a745; }
|
.status-2xx { background: #28a745; }
|
||||||
.status-3xx { background: #17a2b8; }
|
.status-3xx { background: #17a2b8; }
|
||||||
@ -389,18 +389,20 @@ var metricsTemplate = `
|
|||||||
}
|
}
|
||||||
+ #statusCodes {
|
+ #statusCodes {
|
||||||
+ display: flex;
|
+ display: flex;
|
||||||
+ flex-direction: column;
|
+ flex-direction: row;
|
||||||
+ gap: 10px;
|
+ gap: 10px;
|
||||||
+ align-items: flex-start;
|
+ align-items: center;
|
||||||
+ padding: 10px;
|
+ padding: 10px;
|
||||||
+ background: #f8f9fa;
|
+ background: #f8f9fa;
|
||||||
+ border-radius: 8px;
|
+ border-radius: 8px;
|
||||||
+ flex-wrap: nowrap; // 防止换行
|
+ flex-wrap: nowrap;
|
||||||
+ overflow-x: auto; // 在小屏幕上可以滚动
|
+ overflow-x: auto;
|
||||||
|
+ white-space: nowrap;
|
||||||
|
+ justify-content: flex-start;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ #statusCodes .metric {
|
+ #statusCodes .metric {
|
||||||
+ flex: 0 0 auto; // 不伸缩,保持原始大小
|
+ flex: 0 0 auto;
|
||||||
+ display: flex;
|
+ display: flex;
|
||||||
+ align-items: center;
|
+ align-items: center;
|
||||||
+ justify-content: space-between;
|
+ justify-content: space-between;
|
||||||
@ -408,15 +410,19 @@ var metricsTemplate = `
|
|||||||
+ background: white;
|
+ background: white;
|
||||||
+ border-radius: 4px;
|
+ border-radius: 4px;
|
||||||
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
+ min-width: 120px; // 设置最小宽度
|
+ margin-right: 10px;
|
||||||
+ margin-right: 10px; // 格子之间的间距
|
+ min-width: 100px;
|
||||||
|
+ height: 32px;
|
||||||
|
+ }
|
||||||
|
+ #statusCodes .metric:last-child {
|
||||||
|
+ margin-right: 0;
|
||||||
+ }
|
+ }
|
||||||
+ .status-badge {
|
+ .status-badge {
|
||||||
+ padding: 3px 8px;
|
+ padding: 3px 8px;
|
||||||
+ border-radius: 12px;
|
+ border-radius: 12px;
|
||||||
+ font-size: 12px;
|
+ font-size: 12px;
|
||||||
+ color: white;
|
+ color: white;
|
||||||
+ margin-right: 8px; // 状态码和数字之间的间距
|
+ margin-right: 8px;
|
||||||
+ }
|
+ }
|
||||||
+ .loading {
|
+ .loading {
|
||||||
+ position: relative;
|
+ position: relative;
|
||||||
@ -684,6 +690,7 @@ var metricsTemplate = `
|
|||||||
|
|
||||||
// 更新状态码计
|
// 更新状态码计
|
||||||
const statusCodesHtml = Object.entries(data.status_code_stats)
|
const statusCodesHtml = Object.entries(data.status_code_stats)
|
||||||
|
.sort((a, b) => a[0].localeCompare(b[0])) // 按状态码排序
|
||||||
.map(([status, count]) => {
|
.map(([status, count]) => {
|
||||||
const statusClass = 'status-' + status.charAt(0) + 'xx';
|
const statusClass = 'status-' + status.charAt(0) + 'xx';
|
||||||
return '<div class="metric">' +
|
return '<div class="metric">' +
|
||||||
@ -692,7 +699,9 @@ var metricsTemplate = `
|
|||||||
'</div>';
|
'</div>';
|
||||||
})
|
})
|
||||||
.join('');
|
.join('');
|
||||||
document.getElementById('statusCodes').innerHTML = statusCodesHtml;
|
const statusCodesContainer = document.getElementById('statusCodes');
|
||||||
|
statusCodesContainer.style.flexDirection = 'row'; // 强制横向排列
|
||||||
|
statusCodesContainer.innerHTML = statusCodesHtml;
|
||||||
|
|
||||||
// 更新热门路径
|
// 更新热门路径
|
||||||
const topPathsHtml = data.top_paths.map(path =>
|
const topPathsHtml = data.top_paths.map(path =>
|
||||||
|
@ -443,27 +443,6 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error
|
|||||||
cacheSize int64
|
cacheSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置查询优化参数
|
|
||||||
tx, err := db.DB.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to begin transaction: %v", err)
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
if _, err := tx.Exec("PRAGMA temp_store = MEMORY"); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to set temp_store: %v", err)
|
|
||||||
}
|
|
||||||
if _, err := tx.Exec("PRAGMA cache_size = -4000"); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to set cache_size: %v", err)
|
|
||||||
}
|
|
||||||
if _, err := tx.Exec("PRAGMA mmap_size = 268435456"); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to set mmap_size: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to commit transaction: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理小于1小时的情况
|
// 处理小于1小时的情况
|
||||||
if hours <= 0 {
|
if hours <= 0 {
|
||||||
hours = 0.5 // 30分钟
|
hours = 0.5 // 30分钟
|
||||||
@ -490,44 +469,39 @@ func (db *MetricsDB) GetRecentMetrics(hours float64) ([]HistoricalMetrics, error
|
|||||||
timeStep = 1440 // 1天
|
timeStep = 1440 // 1天
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取查询统计
|
// 修改查询逻辑,使用 strftime 来处理时间
|
||||||
row := db.DB.QueryRow("SELECT cache_hits, cache_misses, cache_size FROM pragma_stats")
|
|
||||||
var cacheMisses int64
|
|
||||||
row.Scan(&queryStats.cacheHits, &cacheMisses, &queryStats.cacheSize)
|
|
||||||
|
|
||||||
// 修改查询逻辑
|
|
||||||
rows, err := db.DB.Query(`
|
rows, err := db.DB.Query(`
|
||||||
WITH RECURSIVE
|
WITH RECURSIVE
|
||||||
time_series(time_point) AS (
|
time_points(ts) AS (
|
||||||
SELECT datetime('now', 'localtime')
|
SELECT strftime(?, 'now', 'localtime')
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT datetime(time_point, '-' || ? || ' minutes')
|
SELECT strftime(?, datetime(ts, '-' || ? || ' minutes'))
|
||||||
FROM time_series
|
FROM time_points
|
||||||
WHERE time_point > datetime('now', '-' || ? || ' hours', 'localtime')
|
WHERE ts > strftime(?, datetime('now', '-' || ? || ' hours', 'localtime'))
|
||||||
LIMIT 1000
|
LIMIT 1000
|
||||||
),
|
),
|
||||||
grouped_metrics AS (
|
grouped_metrics AS (
|
||||||
SELECT
|
SELECT
|
||||||
strftime(?, timestamp, 'localtime') as group_time,
|
strftime(?, timestamp) as group_time,
|
||||||
MAX(total_requests) as period_requests,
|
MAX(total_requests) as period_requests,
|
||||||
MAX(total_errors) as period_errors,
|
MAX(total_errors) as period_errors,
|
||||||
MAX(total_bytes) as period_bytes,
|
MAX(total_bytes) as period_bytes,
|
||||||
AVG(avg_latency) as avg_latency
|
AVG(avg_latency) as avg_latency
|
||||||
FROM metrics_history
|
FROM metrics_history
|
||||||
WHERE timestamp >= datetime('now', '-' || ? || ' hours', 'localtime')
|
WHERE timestamp >= datetime('now', '-' || ? || ' hours', 'localtime')
|
||||||
GROUP BY group_time
|
GROUP BY group_time
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
strftime(?, ts.time_point, 'localtime') as timestamp,
|
tp.ts as timestamp,
|
||||||
COALESCE(m.period_requests - LAG(m.period_requests, 1) OVER (ORDER BY ts.time_point), 0) as total_requests,
|
COALESCE(m.period_requests - LAG(m.period_requests, 1) OVER (ORDER BY tp.ts), 0) as total_requests,
|
||||||
COALESCE(m.period_errors - LAG(m.period_errors, 1) OVER (ORDER BY ts.time_point), 0) as total_errors,
|
COALESCE(m.period_errors - LAG(m.period_errors, 1) OVER (ORDER BY tp.ts), 0) as total_errors,
|
||||||
COALESCE(m.period_bytes - LAG(m.period_bytes, 1) OVER (ORDER BY ts.time_point), 0) as total_bytes,
|
COALESCE(m.period_bytes - LAG(m.period_bytes, 1) OVER (ORDER BY tp.ts), 0) as total_bytes,
|
||||||
COALESCE(m.avg_latency, 0) as avg_latency
|
COALESCE(m.avg_latency, 0) as avg_latency
|
||||||
FROM time_series ts
|
FROM time_points tp
|
||||||
LEFT JOIN grouped_metrics m ON strftime(?, ts.time_point, 'localtime') = m.group_time
|
LEFT JOIN grouped_metrics m ON tp.ts = m.group_time
|
||||||
ORDER BY timestamp DESC
|
ORDER BY timestamp DESC
|
||||||
LIMIT 1000
|
LIMIT 1000
|
||||||
`, timeStep, hours, interval, hours, interval, interval)
|
`, interval, interval, timeStep, interval, hours, interval, hours)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user