fix: restrict Model Pricing table to used models and fix cost stats
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled

Implemented used_only filter for /api/models. Added missing cache token and cost fields to usage summary and provider usage endpoints.
This commit is contained in:
2026-03-19 13:02:45 -04:00
parent 3f76a544e0
commit f23796f0cc

View File

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