diff --git a/internal/server/dashboard.go b/internal/server/dashboard.go index 296771ed..b245477f 100644 --- a/internal/server/dashboard.go +++ b/internal/server/dashboard.go @@ -224,15 +224,19 @@ func (s *Server) handleUsageSummary(c *gin.Context) { // Total stats var totalStats struct { - TotalRequests int `db:"total_requests"` - TotalTokens int `db:"total_tokens"` - TotalCost float64 `db:"total_cost"` - ActiveClients int `db:"active_clients"` + TotalRequests int `db:"total_requests"` + TotalTokens int `db:"total_tokens"` + CacheReadTokens int `db:"total_cache_read_tokens"` + CacheWriteTokens int `db:"total_cache_write_tokens"` + TotalCost float64 `db:"total_cost"` + ActiveClients int `db:"active_clients"` } err := s.database.Get(&totalStats, fmt.Sprintf(` SELECT COUNT(*) as total_requests, COALESCE(SUM(total_tokens), 0) as total_tokens, + COALESCE(SUM(cache_read_tokens), 0) as total_cache_read_tokens, + COALESCE(SUM(cache_write_tokens), 0) as total_cache_write_tokens, COALESCE(SUM(cost), 0.0) as total_cost, COUNT(DISTINCT client_id) as active_clients FROM llm_requests @@ -257,7 +261,6 @@ func (s *Server) handleUsageSummary(c *gin.Context) { WHERE timestamp LIKE ? `, today+"%") if err != nil { - fmt.Printf("[ERROR] Failed to fetch today stats: %v\n", err) todayStats.TodayRequests = 0 todayStats.TodayCost = 0.0 } @@ -279,14 +282,16 @@ func (s *Server) handleUsageSummary(c *gin.Context) { } c.JSON(http.StatusOK, SuccessResponse(gin.H{ - "total_requests": totalStats.TotalRequests, - "total_tokens": totalStats.TotalTokens, - "total_cost": totalStats.TotalCost, - "active_clients": totalStats.ActiveClients, - "today_requests": todayStats.TodayRequests, - "today_cost": todayStats.TodayCost, - "error_rate": miscStats.ErrorRate, - "avg_response_time": miscStats.AvgResponseTime, + "total_requests": totalStats.TotalRequests, + "total_tokens": totalStats.TotalTokens, + "total_cache_read_tokens": totalStats.CacheReadTokens, + "total_cache_write_tokens": totalStats.CacheWriteTokens, + "total_cost": totalStats.TotalCost, + "active_clients": totalStats.ActiveClients, + "today_requests": todayStats.TodayRequests, + "today_cost": todayStats.TodayCost, + "error_rate": miscStats.ErrorRate, + "avg_response_time": miscStats.AvgResponseTime, })) } @@ -307,7 +312,6 @@ func (s *Server) handleTimeSeries(c *gin.Context) { query := fmt.Sprintf(` SELECT COALESCE(SUBSTR(timestamp, 1, 10), 'unknown') as bucket, - COUNT(*) as requests, COALESCE(SUM(total_tokens), 0) as tokens, COALESCE(SUM(cost), 0.0) as cost @@ -357,7 +361,10 @@ func (s *Server) handleProvidersUsage(c *gin.Context) { clause, binds := filter.ToSQL() rows, err := s.database.Queryx(fmt.Sprintf(` - SELECT COALESCE(provider, 'unknown') as provider, COUNT(*) as requests + SELECT + COALESCE(provider, 'unknown') as provider, + COUNT(*) as requests, + COALESCE(SUM(cost), 0.0) as cost FROM llm_requests WHERE 1=1 %s GROUP BY provider @@ -372,8 +379,9 @@ func (s *Server) handleProvidersUsage(c *gin.Context) { for rows.Next() { var provider string var requests int - if err := rows.Scan(&provider, &requests); err == nil { - results = append(results, gin.H{"provider": provider, "requests": requests}) + var cost float64 + if err := rows.Scan(&provider, &requests, &cost); err == nil { + results = append(results, gin.H{"provider": provider, "requests": requests, "cost": cost}) } } @@ -944,6 +952,8 @@ func (s *Server) handleTestProvider(c *gin.Context) { } func (s *Server) handleGetModels(c *gin.Context) { + usedOnly := c.Query("used_only") == "true" + // Merge registry models with DB overrides var dbModels []db.ModelConfig _ = s.database.Select(&dbModels, "SELECT * FROM model_configs") @@ -953,10 +963,30 @@ func (s *Server) handleGetModels(c *gin.Context) { dbMap[m.ID] = m } + // Fetch set of used model IDs if requested + usedModels := make(map[string]bool) + if usedOnly { + rows, err := s.database.Queryx("SELECT DISTINCT model FROM llm_requests") + if err == nil { + for rows.Next() { + var mID string + if err := rows.Scan(&mID); err == nil { + usedModels[mID] = true + } + } + rows.Close() + } + } + var result []gin.H if s.registry != nil { for pID, pInfo := range s.registry.Providers { for mID, mMeta := range pInfo.Models { + // Filter if used_only requested + if usedOnly && !usedModels[mID] { + continue + } + enabled := true promptCost := 0.0 completionCost := 0.0