package server import ( "fmt" "net/http" "os" "strings" "time" "log/slog" "github.com/gin-gonic/gin" "gophergate/internal/db" "gophergate/internal/utils" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/load" "github.com/shirou/gopsutil/v3/mem" "github.com/shirou/gopsutil/v3/process" ) func (s *Server) handleSystemHealth(c *gin.Context) { c.JSON(http.StatusOK, SuccessResponse(gin.H{ "status": "ok", "components": gin.H{ "database": "online", "proxy": "online", }, })) } func (s *Server) handleSystemMetrics(c *gin.Context) { v, _ := mem.VirtualMemory() c_usage, _ := cpu.Percent(time.Second, false) d, _ := disk.Usage("/") l, _ := load.Avg() p, _ := process.NewProcess(int32(os.Getpid())) rss, _ := p.MemoryInfo() cpuPercent := 0.0 if len(c_usage) > 0 { cpuPercent = c_usage[0] } c.JSON(http.StatusOK, SuccessResponse(gin.H{ "cpu": gin.H{ "usage_percent": fmt.Sprintf("%.1f", cpuPercent), "load_average": []float64{l.Load1, l.Load5, l.Load15}, }, "memory": gin.H{ "used_mb": v.Used / 1024 / 1024, "total_mb": v.Total / 1024 / 1024, "usage_percent": fmt.Sprintf("%.1f", v.UsedPercent), "process_rss_mb": rss.RSS / 1024 / 1024, }, "disk": gin.H{ "used_gb": float64(d.Used) / 1024 / 1024 / 1024, "total_gb": float64(d.Total) / 1024 / 1024 / 1024, "usage_percent": fmt.Sprintf("%.1f", d.UsedPercent), }, "connections": gin.H{ "db_active": s.database.Stats().OpenConnections, "websocket_listeners": s.hub.GetClientCount(), }, })) } func (s *Server) handleGetSettings(c *gin.Context) { providerCount := 0 modelCount := 0 s.registryMu.RLock() if s.registry != nil { providerCount = len(s.registry.Providers) for _, p := range s.registry.Providers { modelCount += len(p.Models) } } c.JSON(http.StatusOK, SuccessResponse(gin.H{ "server": gin.H{ "version": "1.0.0-go", "auth_tokens": s.cfg.Server.AuthTokens, }, "database": gin.H{ "type": "sqlite", "path": s.cfg.Database.Path, }, "registry": gin.H{ "provider_count": providerCount, "model_count": modelCount, }, })) } func (s *Server) handleCreateBackup(c *gin.Context) { // Simplified backup response c.JSON(http.StatusOK, SuccessResponse(gin.H{ "backup_id": fmt.Sprintf("backup-%d.db", time.Now().Unix()), "status": "created", })) } func (s *Server) handleGetLogs(c *gin.Context) { var logs []db.LLMRequest err := s.database.Select(&logs, "SELECT * FROM llm_requests ORDER BY timestamp DESC LIMIT 100") if err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(err.Error())) return } // Format for UI type UILog struct { Timestamp string `json:"timestamp"` ClientID string `json:"client_id"` Provider string `json:"provider"` Model string `json:"model"` Tokens int `json:"tokens"` Status string `json:"status"` Duration int `json:"duration"` } uiLogs := make([]UILog, len(logs)) for i, l := range logs { clientID := "unknown" if l.ClientID != nil { clientID = *l.ClientID } provider := "unknown" if l.Provider != nil { provider = *l.Provider } model := "unknown" if l.Model != nil { model = *l.Model } tokens := 0 if l.TotalTokens != nil { tokens = *l.TotalTokens } duration := 0 if l.DurationMS != nil { duration = *l.DurationMS } uiLogs[i] = UILog{ Timestamp: l.Timestamp.Format(time.RFC3339), ClientID: clientID, Provider: provider, Model: model, Tokens: tokens, Status: l.Status, Duration: duration, } } c.JSON(http.StatusOK, SuccessResponse(uiLogs)) }