diff --git a/monitoring/metrics.go b/monitoring/metrics.go index 0aed431..cf16de8 100644 --- a/monitoring/metrics.go +++ b/monitoring/metrics.go @@ -1,6 +1,8 @@ package monitoring import ( + "fmt" + "net/url" "runtime" "strings" "sync" @@ -88,13 +90,31 @@ func CollectMetrics() *SystemMetrics { return &metrics } +func formatLatency(microseconds float64) string { + if microseconds < 1000 { + return fmt.Sprintf("%.2fµs", microseconds) + } + if microseconds < 1000000 { + return fmt.Sprintf("%.2fms", microseconds/1000) + } + return fmt.Sprintf("%.2fs", microseconds/1000000) +} + func LogRequest(log RequestLog) { mu.Lock() defer mu.Unlock() metrics.RequestCount++ metrics.StatusCodes[log.StatusCode]++ - metrics.TopReferers[log.Referer]++ + + // 处理 referer,只保留域名 + if log.Referer != "direct" { + if parsedURL, err := url.Parse(log.Referer); err == nil { + metrics.TopReferers[parsedURL.Host]++ + } + } else { + metrics.TopReferers["direct"]++ + } // 只记录 API 请求 if strings.HasPrefix(log.Path, "/pic/") || strings.HasPrefix(log.Path, "/video/") { @@ -105,10 +125,10 @@ func LogRequest(log RequestLog) { metrics.PathLatencies[log.Path] = log.Latency } - // 保存最近请求记录 - metrics.RecentRequests = append(metrics.RecentRequests, log) + // 保存最近请求记录,插入到开头 + metrics.RecentRequests = append([]RequestLog{log}, metrics.RecentRequests...) if len(metrics.RecentRequests) > 100 { - metrics.RecentRequests = metrics.RecentRequests[1:] + metrics.RecentRequests = metrics.RecentRequests[:100] } } } diff --git a/public/index.html b/public/index.html index 23d0628..d289413 100644 --- a/public/index.html +++ b/public/index.html @@ -218,6 +218,39 @@ } function updateMetricsDisplay(metrics) { + // 格式化延迟显示 + function formatLatency(microseconds) { + if (microseconds < 1000) { + return `${microseconds.toFixed(2)}µs`; + } + if (microseconds < 1000000) { + return `${(microseconds/1000).toFixed(2)}ms`; + } + return `${(microseconds/1000000).toFixed(2)}s`; + } + + // 最近请求 + const recentRequestsHtml = metrics.recent_requests.map(req => ` + + ${new Date(req.time).toLocaleString()} + ${req.path} + ${req.method} + ${req.status_code} + ${formatLatency(req.latency)} + + `).join(''); + + // 热门引用来源 + const topReferersHtml = Object.entries(metrics.top_referers) + .sort(([, a], [, b]) => b - a) + .slice(0, 10) + .map(([referer, count]) => ` +
+ ${referer} + ${count} +
+ `).join(''); + const metricsHtml = `
@@ -273,15 +306,7 @@ - ${metrics.recent_requests.slice(0, 10).map(req => ` - - ${new Date(req.time).toLocaleString()} - ${req.path} - ${req.method} - ${req.status_code} - ${req.latency.toFixed(2)}ms - - `).join('')} + ${recentRequestsHtml}
@@ -290,15 +315,7 @@

热门引用来源

- ${Object.entries(metrics.top_referers) - .sort(([,a], [,b]) => b - a) - .slice(0, 10) - .map(([referer, count]) => ` -
- ${referer || '直接访问'} - ${count} -
- `).join('')} + ${topReferersHtml}