package handler import ( "encoding/json" "fmt" "net/http" "runtime" "strings" "sync/atomic" "time" ) type Metrics struct { // 基础指标 Uptime string `json:"uptime"` ActiveRequests int64 `json:"active_requests"` TotalRequests int64 `json:"total_requests"` TotalErrors int64 `json:"total_errors"` ErrorRate float64 `json:"error_rate"` // 系统指标 NumGoroutine int `json:"num_goroutine"` MemoryUsage string `json:"memory_usage"` // 性能指标 AverageResponseTime string `json:"avg_response_time"` RequestsPerSecond float64 `json:"requests_per_second"` // 新增字段 TotalBytes int64 `json:"total_bytes"` BytesPerSecond float64 `json:"bytes_per_second"` StatusCodeStats map[string]int64 `json:"status_code_stats"` LatencyPercentiles map[string]float64 `json:"latency_percentiles"` TopPaths []PathMetrics `json:"top_paths"` RecentRequests []RequestLog `json:"recent_requests"` } type PathMetrics struct { Path string `json:"path"` RequestCount int64 `json:"request_count"` ErrorCount int64 `json:"error_count"` AvgLatency string `json:"avg_latency"` BytesTransferred int64 `json:"bytes_transferred"` } // 添加格式化字节的辅助函数 func formatBytes(bytes uint64) string { const ( MB = 1024 * 1024 KB = 1024 ) switch { case bytes >= MB: return fmt.Sprintf("%.2f MB", float64(bytes)/MB) case bytes >= KB: return fmt.Sprintf("%.2f KB", float64(bytes)/KB) default: return fmt.Sprintf("%d Bytes", bytes) } } func (h *ProxyHandler) MetricsHandler(w http.ResponseWriter, r *http.Request) { var m runtime.MemStats runtime.ReadMemStats(&m) // 获取状态码统计 statusStats := make(map[string]int64) for i, v := range h.metrics.statusStats { statusStats[fmt.Sprintf("%dxx", i+1)] = v.Load() } // 获取Top 10路径统计 var pathMetrics []PathMetrics h.metrics.pathStats.Range(func(key, value interface{}) bool { stats := value.(*PathStats) pathMetrics = append(pathMetrics, PathMetrics{ Path: key.(string), RequestCount: stats.requests.Load(), ErrorCount: stats.errors.Load(), AvgLatency: formatDuration(time.Duration(stats.latencySum.Load() / stats.requests.Load())), BytesTransferred: stats.bytes.Load(), }) return len(pathMetrics) < 10 }) // 获取最近的请求 var recentReqs []RequestLog h.recentRequests.RLock() cursor := h.recentRequests.cursor.Load() for i := 0; i < 10; i++ { idx := (cursor - int64(i) + 1000) % 1000 if h.recentRequests.items[idx] != nil { recentReqs = append(recentReqs, *h.recentRequests.items[idx]) } } h.recentRequests.RUnlock() metrics := Metrics{ Uptime: time.Since(h.startTime).String(), ActiveRequests: atomic.LoadInt64(&h.metrics.activeRequests), TotalRequests: atomic.LoadInt64(&h.metrics.totalRequests), TotalErrors: atomic.LoadInt64(&h.metrics.totalErrors), ErrorRate: float64(h.metrics.totalErrors) / float64(h.metrics.totalRequests), NumGoroutine: runtime.NumGoroutine(), MemoryUsage: formatBytes(m.Alloc), TotalBytes: h.metrics.totalBytes.Load(), BytesPerSecond: float64(h.metrics.totalBytes.Load()) / time.Since(h.startTime).Seconds(), StatusCodeStats: statusStats, TopPaths: pathMetrics, RecentRequests: recentReqs, } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(metrics) } // 添加格式化时间的辅助函数 func formatDuration(d time.Duration) string { if d < time.Millisecond { return fmt.Sprintf("%.2f μs", float64(d.Microseconds())) } if d < time.Second { return fmt.Sprintf("%.2f ms", float64(d.Milliseconds())) } return fmt.Sprintf("%.2f s", d.Seconds()) } // 修改模板,添加登录页面 var loginTemplate = `