package handler import ( "encoding/json" "fmt" "log" "net/http" "proxy-go/internal/metrics" "proxy-go/internal/models" "runtime" "strings" "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 []models.PathMetrics `json:"top_paths"` RecentRequests []models.RequestLog `json:"recent_requests"` TopReferers []models.PathMetrics `json:"top_referers"` } func (h *ProxyHandler) MetricsHandler(w http.ResponseWriter, r *http.Request) { uptime := time.Since(h.startTime) collector := metrics.GetCollector() stats := collector.GetStats() if stats == nil { // 返回默认值而不是错误 stats = map[string]interface{}{ "uptime": uptime.String(), "active_requests": int64(0), "total_requests": int64(0), "total_errors": int64(0), "error_rate": float64(0), "num_goroutine": runtime.NumGoroutine(), "memory_usage": "0 B", "avg_response_time": "0 ms", "total_bytes": int64(0), "bytes_per_second": float64(0), "requests_per_second": float64(0), "status_code_stats": make(map[string]int64), "latency_percentiles": make([]float64, 0), "top_paths": make([]models.PathMetrics, 0), "recent_requests": make([]models.RequestLog, 0), "top_referers": make([]models.PathMetrics, 0), } } // 确保所有必要的字段都存在 metrics := Metrics{ Uptime: uptime.String(), ActiveRequests: safeInt64(stats["active_requests"]), TotalRequests: safeInt64(stats["total_requests"]), TotalErrors: safeInt64(stats["total_errors"]), ErrorRate: float64(safeInt64(stats["total_errors"])) / float64(max(safeInt64(stats["total_requests"]), 1)), NumGoroutine: safeInt(stats["num_goroutine"]), MemoryUsage: safeString(stats["memory_usage"]), AverageResponseTime: safeString(stats["avg_response_time"]), TotalBytes: safeInt64(stats["total_bytes"]), BytesPerSecond: float64(safeInt64(stats["total_bytes"])) / metrics.Max(uptime.Seconds(), 1), RequestsPerSecond: float64(safeInt64(stats["total_requests"])) / metrics.Max(uptime.Seconds(), 1), StatusCodeStats: safeStatusCodeStats(stats["status_code_stats"]), TopPaths: safePathMetrics(stats["top_paths"]), RecentRequests: safeRequestLogs(stats["recent_requests"]), TopReferers: safePathMetrics(stats["top_referers"]), } w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(metrics); err != nil { log.Printf("Error encoding metrics: %v", err) } } // 辅助函数 func max(a, b int64) int64 { if a > b { return a } return b } // 修改模板,添加登录页面 var loginTemplate = ` Proxy-Go Metrics Login

Metrics Login

密码错误
` // 修改原有的 metricsTemplate,添加 token 检查 var metricsTemplate = ` Proxy-Go Metrics

Proxy-Go Metrics

基础指标

运行时间
当前活跃请求
总请求数
错误数
错误率

系统指标

Goroutine数量
内存使用

性能指标

平均响应时间
每秒请求数

流量统计

总传输字节
每秒传输

状态统

热门路径 (Top 10)

路径 请求数 错误数 平均延迟 传输大小

最近请求

时间 路径 状态 延迟 大小 客户端IP

热门引用来源 (Top 10)

来源 请求数

历史数据

显示最近30天的数据
` // 添加认证中间件 func (h *ProxyHandler) AuthMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { auth := r.Header.Get("Authorization") if auth == "" || !strings.HasPrefix(auth, "Bearer ") { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } token := strings.TrimPrefix(auth, "Bearer ") if !h.auth.validateToken(token) { http.Error(w, "Invalid token", http.StatusUnauthorized) return } next(w, r) } } // 修改处理器 func (h *ProxyHandler) MetricsPageHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write([]byte(loginTemplate)) } func (h *ProxyHandler) MetricsDashboardHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write([]byte(metricsTemplate)) } func (h *ProxyHandler) MetricsAuthHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var req struct { Password string `json:"password"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid request", http.StatusBadRequest) return } if req.Password != h.config.Metrics.Password { http.Error(w, "Invalid password", http.StatusUnauthorized) return } token := h.auth.generateToken() h.auth.addToken(token, time.Duration(h.config.Metrics.TokenExpiry)*time.Second) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{ "token": token, }) } // 添加历史数据查询接口 func (h *ProxyHandler) MetricsHistoryHandler(w http.ResponseWriter, r *http.Request) { collector := metrics.GetCollector() metrics := collector.GetHistoricalData() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(metrics) } // 辅助函数:解析延迟字符串 func parseLatency(latency string) (float64, error) { var value float64 var unit string _, err := fmt.Sscanf(latency, "%f %s", &value, &unit) if err != nil { return 0, err } // 根据单位转换为毫秒 switch unit { case "μs": value = value / 1000 // 微秒转毫秒 case "ms": // 已经是毫秒 case "s": value = value * 1000 // 秒转毫秒 default: return 0, fmt.Errorf("unknown unit: %s", unit) } return value, nil } // 添加安全的类型转换辅助函数 func safeStatusCodeStats(v interface{}) map[string]int64 { if v == nil { return make(map[string]int64) } if m, ok := v.(map[string]int64); ok { return m } return make(map[string]int64) } func safePathMetrics(v interface{}) []models.PathMetrics { if v == nil { return []models.PathMetrics{} } if m, ok := v.([]models.PathMetrics); ok { return m } return []models.PathMetrics{} } func safeRequestLogs(v interface{}) []models.RequestLog { if v == nil { return []models.RequestLog{} } if m, ok := v.([]models.RequestLog); ok { return m } return []models.RequestLog{} } func safeInt64(v interface{}) int64 { if v == nil { return 0 } if i, ok := v.(int64); ok { return i } return 0 } func safeInt(v interface{}) int { if v == nil { return 0 } if i, ok := v.(int); ok { return i } return 0 } func safeString(v interface{}) string { if v == nil { return "0 B" // 返回默认值 } if s, ok := v.(string); ok { return s } return "0 B" // 返回默认值 }