fix: log resolved model name instead of group name in Recent Activity
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled

When using model groups (e.g. 'deepseek-auto'), the dashboard logged the
group name instead of the concrete resolved model (e.g. 'deepseek-reasoner').

Now:
- logRequest passes the resolved modelID (concrete) + modelGroup (group name)
- RequestLog struct has a new ModelGroup field (omitempty)
- Dashboard displays resolved model (via group) when a group was used

Files changed:
  internal/server/logging.go  - add ModelGroup field
  internal/server/server.go   - pass resolved modelID, capture modelGroup
  static/js/websocket.js      - show group annotation in Recent Activity
  static/js/pages/overview.js - show group annotation in overview table
  static/js/pages/monitoring.js - show group annotation in stream
This commit is contained in:
2026-05-07 11:16:36 -04:00
parent 14de7e9ebf
commit 3021e4b2b4
5 changed files with 23 additions and 19 deletions
+17 -14
View File
@@ -362,7 +362,7 @@ func (s *Server) handleResponses(c *gin.Context) {
if stream {
ch, err := provider.ResponsesStream(c.Request.Context(), &req)
if err != nil {
s.logRequest(startTime, clientID, providerName, req.Model, nil, err, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", nil, err, false)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
@@ -377,9 +377,9 @@ func (s *Server) handleResponses(c *gin.Context) {
if !ok {
fmt.Fprintf(w, "data: [DONE]\n\n")
if lastUsage != nil {
s.logRequest(startTime, clientID, providerName, req.Model, lastUsage.ToUsage(), nil, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", lastUsage.ToUsage(), nil, false)
} else {
s.logRequest(startTime, clientID, providerName, req.Model, nil, nil, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", nil, nil, false)
}
return false
}
@@ -399,15 +399,15 @@ func (s *Server) handleResponses(c *gin.Context) {
resp, err := provider.Responses(c.Request.Context(), &req)
if err != nil {
s.logRequest(startTime, clientID, providerName, req.Model, nil, err, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", nil, err, false)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if resp.Usage != nil {
s.logRequest(startTime, clientID, providerName, req.Model, resp.Usage.ToUsage(), nil, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", resp.Usage.ToUsage(), nil, false)
} else {
s.logRequest(startTime, clientID, providerName, req.Model, nil, nil, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", nil, nil, false)
}
c.JSON(http.StatusOK, resp)
}
@@ -528,7 +528,9 @@ func (s *Server) handleChatCompletions(c *gin.Context) {
}
// Check if model is a group and route to a concrete model
modelGroup := ""
if s.modelRouter != nil && s.modelRouter.IsGroup(modelID) {
modelGroup = modelID
userMessage := extractUserMessage(req.Messages)
decision, err := s.modelRouter.Route(c.Request.Context(), modelID, userMessage)
if err != nil {
@@ -536,7 +538,7 @@ func (s *Server) handleChatCompletions(c *gin.Context) {
return
}
modelID = decision.SelectedModel
log.Printf("[ROUTER] %s -> %s (%s: %s)", req.Model, modelID, decision.Strategy, decision.Reason)
log.Printf("[ROUTER] %s -> %s (%s: %s)", modelGroup, modelID, decision.Strategy, decision.Reason)
}
// Convert ChatCompletionRequest to UnifiedRequest
@@ -657,7 +659,7 @@ if unifiedReq.MaxTokens == nil {
if unifiedReq.Stream {
ch, err := provider.ChatCompletionStream(c.Request.Context(), unifiedReq)
if err != nil {
s.logRequest(startTime, clientID, providerName, req.Model, nil, err, unifiedReq.HasImages)
s.logRequest(startTime, clientID, providerName, modelID, modelGroup, nil, err, unifiedReq.HasImages)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
@@ -671,7 +673,7 @@ if unifiedReq.MaxTokens == nil {
chunk, ok := <-ch
if !ok {
fmt.Fprintf(w, "data: [DONE]\n\n")
s.logRequest(startTime, clientID, providerName, req.Model, lastUsage, nil, unifiedReq.HasImages)
s.logRequest(startTime, clientID, providerName, modelID, modelGroup, lastUsage, nil, unifiedReq.HasImages)
return false
}
if chunk.Usage != nil {
@@ -689,12 +691,12 @@ if unifiedReq.MaxTokens == nil {
resp, err := provider.ChatCompletion(c.Request.Context(), unifiedReq)
if err != nil {
s.logRequest(startTime, clientID, providerName, req.Model, nil, err, unifiedReq.HasImages)
s.logRequest(startTime, clientID, providerName, modelID, modelGroup, nil, err, unifiedReq.HasImages)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
s.logRequest(startTime, clientID, providerName, req.Model, resp.Usage, nil, unifiedReq.HasImages)
s.logRequest(startTime, clientID, providerName, modelID, modelGroup, resp.Usage, nil, unifiedReq.HasImages)
c.JSON(http.StatusOK, resp)
}
@@ -763,7 +765,7 @@ func (s *Server) handleImageGenerations(c *gin.Context) {
resp, err := provider.ImageGeneration(c.Request.Context(), &req)
if err != nil {
s.logRequest(startTime, clientID, providerName, req.Model, nil, err, false)
s.logRequest(startTime, clientID, providerName, req.Model, "", nil, err, false)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
@@ -777,7 +779,7 @@ func (s *Server) handleImageGenerations(c *gin.Context) {
// Calculate per-image cost (not per-token like chat)
cost := imageGenCost(providerName, req.Model, req.Size, uint32(len(resp.Data)))
s.logRequest(startTime, clientID, providerName, req.Model, &models.Usage{
s.logRequest(startTime, clientID, providerName, req.Model, "", &models.Usage{
PromptTokens: promptTokens,
CompletionTokens: uint32(len(resp.Data)),
TotalTokens: promptTokens + uint32(len(resp.Data)),
@@ -819,12 +821,13 @@ func imageGenCost(provider, model string, size *string, n uint32) float64 {
return perImage * float64(n)
}
func (s *Server) logRequest(start time.Time, clientID, provider, model string, usage *models.Usage, err error, hasImages bool) {
func (s *Server) logRequest(start time.Time, clientID, provider, model, modelGroup string, usage *models.Usage, err error, hasImages bool) {
entry := RequestLog{
Timestamp: start,
ClientID: clientID,
Provider: provider,
Model: model,
ModelGroup: modelGroup,
Status: "success",
DurationMS: time.Since(start).Milliseconds(),
HasImages: hasImages,