Refactor configuration and key management

- Removed key management configuration from .env.example and related code.
- Updated Makefile to load environment variables for HOST and PORT.
- Modified main.go to handle request logging with a wait group for graceful shutdown.
- Simplified dashboard statistics handler to focus on key counts and request metrics.
- Removed key manager implementation and related interfaces.
- Updated proxy server to use atomic counters for round-robin key selection.
- Cleaned up unused types and configurations in types.go.
- Added package-lock.json for frontend dependencies.
This commit is contained in:
tbphp
2025-06-30 22:09:16 +08:00
parent 5f0990f22b
commit b9a833ceab
10 changed files with 130 additions and 669 deletions

View File

@@ -1,54 +1,39 @@
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"gpt-load/internal/db"
"gpt-load/internal/models"
"gpt-load/internal/response"
)
// GetDashboardStats godoc
// @Summary Get dashboard statistics
// @Description Get statistics for the dashboard, including total requests, success rate, and group distribution.
// @Description Get statistics for the dashboard, including key counts and request metrics.
// @Tags Dashboard
// @Accept json
// @Produce json
// @Success 200 {object} models.DashboardStats
// @Success 200 {object} map[string]interface{}
// @Router /api/dashboard/stats [get]
func GetDashboardStats(c *gin.Context) {
func (s *Server) Stats(c *gin.Context) {
var totalRequests, successRequests int64
var groupStats []models.GroupRequestStat
// Get total requests
if err := db.DB.Model(&models.RequestLog{}).Count(&totalRequests).Error; err != nil {
response.Error(c, http.StatusInternalServerError, "Failed to get total requests")
return
}
// 1. Get total and successful requests from the api_keys table
s.DB.Model(&models.APIKey{}).Select("SUM(request_count)").Row().Scan(&totalRequests)
s.DB.Model(&models.APIKey{}).Select("SUM(request_count) - SUM(failure_count)").Row().Scan(&successRequests)
// Get success requests (status code 2xx)
if err := db.DB.Model(&models.RequestLog{}).Where("status_code >= ? AND status_code < ?", 200, 300).Count(&successRequests).Error; err != nil {
response.Error(c, http.StatusInternalServerError, "Failed to get success requests")
return
}
// 2. Get request counts per group
s.DB.Table("api_keys").
Select("groups.name as group_name, SUM(api_keys.request_count) as request_count").
Joins("join groups on groups.id = api_keys.group_id").
Group("groups.name").
Order("request_count DESC").
Scan(&groupStats)
// Calculate success rate
// 3. Calculate success rate
var successRate float64
if totalRequests > 0 {
successRate = float64(successRequests) / float64(totalRequests)
}
// Get group stats
err := db.DB.Table("request_logs").
Select("groups.name as group_name, count(request_logs.id) as request_count").
Joins("join groups on groups.id = request_logs.group_id").
Group("groups.name").
Order("request_count desc").
Scan(&groupStats).Error
if err != nil {
response.Error(c, http.StatusInternalServerError, "Failed to get group stats")
return
successRate = float64(successRequests) / float64(totalRequests) * 100
}
stats := models.DashboardStats{

View File

@@ -3,7 +3,6 @@ package handler
import (
"net/http"
"runtime"
"time"
"gpt-load/internal/models"
@@ -53,7 +52,7 @@ func (s *Server) RegisterAPIRoutes(api *gin.RouterGroup) {
// Dashboard and logs routes
dashboard := api.Group("/dashboard")
{
dashboard.GET("/stats", GetDashboardStats)
dashboard.GET("/stats", s.Stats)
}
api.GET("/logs", GetLogs)
@@ -101,53 +100,6 @@ func (s *Server) Health(c *gin.Context) {
})
}
// Stats handles statistics requests
func (s *Server) Stats(c *gin.Context) {
var totalKeys, healthyKeys, disabledKeys int64
s.DB.Model(&models.APIKey{}).Count(&totalKeys)
s.DB.Model(&models.APIKey{}).Where("status = ?", "active").Count(&healthyKeys)
s.DB.Model(&models.APIKey{}).Where("status != ?", "active").Count(&disabledKeys)
// TODO: Get request counts from the database
var successCount, failureCount int64
s.DB.Model(&models.RequestLog{}).Where("status_code = ?", http.StatusOK).Count(&successCount)
s.DB.Model(&models.RequestLog{}).Where("status_code != ?", http.StatusOK).Count(&failureCount)
// Add additional system information
var m runtime.MemStats
runtime.ReadMemStats(&m)
response := gin.H{
"keys": gin.H{
"total": totalKeys,
"healthy": healthyKeys,
"disabled": disabledKeys,
},
"requests": gin.H{
"success_count": successCount,
"failure_count": failureCount,
"total_count": successCount + failureCount,
},
"memory": gin.H{
"alloc_mb": bToMb(m.Alloc),
"total_alloc_mb": bToMb(m.TotalAlloc),
"sys_mb": bToMb(m.Sys),
"num_gc": m.NumGC,
"last_gc": time.Unix(0, int64(m.LastGC)).Format("2006-01-02 15:04:05"),
"next_gc_mb": bToMb(m.NextGC),
},
"system": gin.H{
"goroutines": runtime.NumGoroutine(),
"cpu_count": runtime.NumCPU(),
"go_version": runtime.Version(),
},
"timestamp": time.Now().UTC().Format(time.RFC3339),
}
c.JSON(http.StatusOK, response)
}
// MethodNotAllowed handles 405 requests
func (s *Server) MethodNotAllowed(c *gin.Context) {
c.JSON(http.StatusMethodNotAllowed, gin.H{
@@ -169,7 +121,6 @@ func (s *Server) GetConfig(c *gin.Context) {
}
serverConfig := s.config.GetServerConfig()
keysConfig := s.config.GetKeysConfig()
openaiConfig := s.config.GetOpenAIConfig()
authConfig := s.config.GetAuthConfig()
corsConfig := s.config.GetCORSConfig()
@@ -182,12 +133,6 @@ func (s *Server) GetConfig(c *gin.Context) {
"host": serverConfig.Host,
"port": serverConfig.Port,
},
"keys": gin.H{
"file_path": keysConfig.FilePath,
"start_index": keysConfig.StartIndex,
"blacklist_threshold": keysConfig.BlacklistThreshold,
"max_retries": keysConfig.MaxRetries,
},
"openai": gin.H{
"base_url": openaiConfig.BaseURL,
"request_timeout": openaiConfig.RequestTimeout,
@@ -230,8 +175,3 @@ func (s *Server) GetConfig(c *gin.Context) {
c.JSON(http.StatusOK, sanitizedConfig)
}
// Helper function to convert bytes to megabytes
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}