Browse Source

fix: log query field (#235)

zijiren 6 months ago
parent
commit
37fd08e262
8 changed files with 146 additions and 756 deletions
  1. 4 55
      core/controller/dashboard.go
  2. 5 20
      core/controller/log.go
  3. 2 211
      core/docs/docs.go
  4. 2 211
      core/docs/swagger.json
  5. 0 130
      core/docs/swagger.yaml
  6. 18 28
      core/model/log.go
  7. 115 95
      core/model/summary.go
  8. 0 6
      core/router/api.go

+ 4 - 55
core/controller/dashboard.go

@@ -43,10 +43,11 @@ func getDashboardTime(
 		start = time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, timezoneLocation)
 		timeSpan = model.TimeSpanDay
 	case "day":
-		fallthrough
-	default:
 		start = end.AddDate(0, 0, -1)
 		timeSpan = model.TimeSpanHour
+	default:
+		start = end.AddDate(0, 0, -7)
+		timeSpan = model.TimeSpanHour
 	}
 	if startTimestamp != 0 {
 		start = time.Unix(startTimestamp, 0)
@@ -224,7 +225,7 @@ func GetDashboard(c *gin.Context) {
 //	@Router			/api/dashboard/{group} [get]
 func GetGroupDashboard(c *gin.Context) {
 	group := c.Param("group")
-	if group == "" || group == "*" {
+	if group == "" {
 		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
 		return
 	}
@@ -325,58 +326,6 @@ func GetGroupDashboardModels(c *gin.Context) {
 	middleware.SuccessResponse(c, newEnabledModelConfigs)
 }
 
-// GetModelCostRank godoc
-//
-//	@Summary		Get model cost ranking data
-//	@Description	Returns ranking data for models based on cost
-//	@Tags			dashboard
-//	@Produce		json
-//	@Security		ApiKeyAuth
-//	@Param			channel			query		int		false	"Channel ID"
-//	@Param			start_timestamp	query		int64	false	"Start timestamp"
-//	@Param			end_timestamp	query		int64	false	"End timestamp"
-//	@Success		200				{object}	middleware.APIResponse{data=[]model.CostRank}
-//	@Router			/api/model_cost_rank/ [get]
-func GetModelCostRank(c *gin.Context) {
-	channelID, _ := strconv.Atoi(c.Query("channel"))
-	startTime, endTime := parseTimeRange(c)
-	models, err := model.GetModelCostRank("*", "", channelID, startTime, endTime)
-	if err != nil {
-		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
-		return
-	}
-	middleware.SuccessResponse(c, models)
-}
-
-// GetGroupModelCostRank godoc
-//
-//	@Summary		Get model cost ranking data for a specific group
-//	@Description	Returns model cost ranking data specific to the given group
-//	@Tags			dashboard
-//	@Produce		json
-//	@Security		ApiKeyAuth
-//	@Param			group			path		string	true	"Group"
-//	@Param			token_name		query		string	false	"Token name"
-//	@Param			start_timestamp	query		int64	false	"Start timestamp"
-//	@Param			end_timestamp	query		int64	false	"End timestamp"
-//	@Success		200				{object}	middleware.APIResponse{data=[]model.CostRank}
-//	@Router			/api/model_cost_rank/{group} [get]
-func GetGroupModelCostRank(c *gin.Context) {
-	group := c.Param("group")
-	if group == "" || group == "*" {
-		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
-		return
-	}
-	tokenName := c.Query("token_name")
-	startTime, endTime := parseTimeRange(c)
-	models, err := model.GetModelCostRank(group, tokenName, 0, startTime, endTime)
-	if err != nil {
-		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
-		return
-	}
-	middleware.SuccessResponse(c, models)
-}
-
 // GetTimeSeriesModelData godoc
 //
 //	@Summary		Get model usage data for a specific channel

+ 5 - 20
core/controller/log.go

@@ -64,15 +64,12 @@ func parseCommonParams(c *gin.Context) (params struct {
 //	@Tags			logs
 //	@Produce		json
 //	@Security		ApiKeyAuth
-//	@Param			group			query		string	false	"Group or *"
 //	@Param			page			query		int		false	"Page number"
 //	@Param			per_page		query		int		false	"Items per page"
 //	@Param			start_timestamp	query		int		false	"Start timestamp (milliseconds)"
 //	@Param			end_timestamp	query		int		false	"End timestamp (milliseconds)"
-//	@Param			token_name		query		string	false	"Token name"
 //	@Param			model_name		query		string	false	"Model name"
 //	@Param			channel			query		int		false	"Channel ID"
-//	@Param			token_id		query		int		false	"Token ID"
 //	@Param			order			query		string	false	"Order"
 //	@Param			request_id		query		string	false	"Request ID"
 //	@Param			code_type		query		string	false	"Status code type"
@@ -86,16 +83,12 @@ func GetLogs(c *gin.Context) {
 	page, perPage := utils.ParsePageParams(c)
 	startTime, endTime := parseTimeRange(c)
 	params := parseCommonParams(c)
-	group := c.Query("group")
 
 	result, err := model.GetLogs(
-		group,
 		startTime,
 		endTime,
 		params.modelName,
 		params.requestID,
-		params.tokenID,
-		params.tokenName,
 		params.channelID,
 		params.order,
 		model.CodeType(params.codeType),
@@ -140,7 +133,7 @@ func GetLogs(c *gin.Context) {
 //	@Router			/api/log/{group} [get]
 func GetGroupLogs(c *gin.Context) {
 	group := c.Param("group")
-	if group == "" || group == "*" {
+	if group == "" {
 		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
 		return
 	}
@@ -157,7 +150,6 @@ func GetGroupLogs(c *gin.Context) {
 		params.requestID,
 		params.tokenID,
 		params.tokenName,
-		params.channelID,
 		params.order,
 		model.CodeType(params.codeType),
 		params.code,
@@ -181,13 +173,11 @@ func GetGroupLogs(c *gin.Context) {
 //	@Tags			logs
 //	@Produce		json
 //	@Security		ApiKeyAuth
-//	@Param			group			query		string	false	"Group or *"
-//	@Param			keyword			query		string	true	"Keyword"
+//	@Param			keyword			query		string	false	"Keyword"
 //	@Param			page			query		int		false	"Page number"
 //	@Param			per_page		query		int		false	"Items per page"
 //	@Param			start_timestamp	query		int		false	"Start timestamp (milliseconds)"
 //	@Param			end_timestamp	query		int		false	"End timestamp (milliseconds)"
-//	@Param			token_name		query		string	false	"Filter by token name"
 //	@Param			model_name		query		string	false	"Filter by model name"
 //	@Param			channel			query		int		false	"Filter by channel"
 //	@Param			token_id		query		int		false	"Filter by token id"
@@ -206,14 +196,11 @@ func SearchLogs(c *gin.Context) {
 	params := parseCommonParams(c)
 
 	keyword := c.Query("keyword")
-	group := c.Query("group")
 
 	result, err := model.SearchLogs(
-		group,
 		keyword,
 		params.requestID,
 		params.tokenID,
-		params.tokenName,
 		params.modelName,
 		startTime,
 		endTime,
@@ -242,14 +229,13 @@ func SearchLogs(c *gin.Context) {
 //	@Produce		json
 //	@Security		ApiKeyAuth
 //	@Param			group			path		string	true	"Group name"
-//	@Param			keyword			query		string	true	"Keyword"
+//	@Param			keyword			query		string	false	"Keyword"
 //	@Param			page			query		int		false	"Page number"
 //	@Param			per_page		query		int		false	"Items per page"
 //	@Param			start_timestamp	query		int		false	"Start timestamp (milliseconds)"
 //	@Param			end_timestamp	query		int		false	"End timestamp (milliseconds)"
 //	@Param			token_name		query		string	false	"Filter by token name"
 //	@Param			model_name		query		string	false	"Filter by model name"
-//	@Param			channel			query		int		false	"Filter by channel"
 //	@Param			token_id		query		int		false	"Filter by token id"
 //	@Param			order			query		string	false	"Order"
 //	@Param			request_id		query		string	false	"Request ID"
@@ -262,7 +248,7 @@ func SearchLogs(c *gin.Context) {
 //	@Router			/api/log/{group}/search [get]
 func SearchGroupLogs(c *gin.Context) {
 	group := c.Param("group")
-	if group == "" || group == "*" {
+	if group == "" {
 		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
 		return
 	}
@@ -281,7 +267,6 @@ func SearchGroupLogs(c *gin.Context) {
 		params.modelName,
 		startTime,
 		endTime,
-		params.channelID,
 		params.order,
 		model.CodeType(params.codeType),
 		params.code,
@@ -331,7 +316,7 @@ func GetLogDetail(c *gin.Context) {
 //	@Router			/api/log/{group}/detail/{log_id} [get]
 func GetGroupLogDetail(c *gin.Context) {
 	group := c.Param("group")
-	if group == "" || group == "*" {
+	if group == "" {
 		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
 		return
 	}

+ 2 - 211
core/docs/docs.go

@@ -2564,8 +2564,7 @@ const docTemplate = `{
                         "type": "string",
                         "description": "Keyword",
                         "name": "keyword",
-                        "in": "query",
-                        "required": true
+                        "in": "query"
                     },
                     {
                         "type": "integer",
@@ -2603,12 +2602,6 @@ const docTemplate = `{
                         "name": "model_name",
                         "in": "query"
                     },
-                    {
-                        "type": "integer",
-                        "description": "Filter by channel",
-                        "name": "channel",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Filter by token id",
@@ -2696,12 +2689,6 @@ const docTemplate = `{
                 ],
                 "summary": "Get all logs",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Page number",
@@ -2726,12 +2713,6 @@ const docTemplate = `{
                         "name": "end_timestamp",
                         "in": "query"
                     },
-                    {
-                        "type": "string",
-                        "description": "Token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Model name",
@@ -2744,12 +2725,6 @@ const docTemplate = `{
                         "name": "channel",
                         "in": "query"
                     },
-                    {
-                        "type": "integer",
-                        "description": "Token ID",
-                        "name": "token_id",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Order",
@@ -3051,18 +3026,11 @@ const docTemplate = `{
                 ],
                 "summary": "Search logs",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Keyword",
                         "name": "keyword",
-                        "in": "query",
-                        "required": true
+                        "in": "query"
                     },
                     {
                         "type": "integer",
@@ -3088,12 +3056,6 @@ const docTemplate = `{
                         "name": "end_timestamp",
                         "in": "query"
                     },
-                    {
-                        "type": "string",
-                        "description": "Filter by token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Filter by model name",
@@ -4454,133 +4416,6 @@ const docTemplate = `{
                 }
             }
         },
-        "/api/model_cost_rank/": {
-            "get": {
-                "security": [
-                    {
-                        "ApiKeyAuth": []
-                    }
-                ],
-                "description": "Returns ranking data for models based on cost",
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "dashboard"
-                ],
-                "summary": "Get model cost ranking data",
-                "parameters": [
-                    {
-                        "type": "integer",
-                        "description": "Channel ID",
-                        "name": "channel",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Start timestamp",
-                        "name": "start_timestamp",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "End timestamp",
-                        "name": "end_timestamp",
-                        "in": "query"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "allOf": [
-                                {
-                                    "$ref": "#/definitions/middleware.APIResponse"
-                                },
-                                {
-                                    "type": "object",
-                                    "properties": {
-                                        "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/model.CostRank"
-                                            }
-                                        }
-                                    }
-                                }
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "/api/model_cost_rank/{group}": {
-            "get": {
-                "security": [
-                    {
-                        "ApiKeyAuth": []
-                    }
-                ],
-                "description": "Returns model cost ranking data specific to the given group",
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "dashboard"
-                ],
-                "summary": "Get model cost ranking data for a specific group",
-                "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group",
-                        "name": "group",
-                        "in": "path",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Start timestamp",
-                        "name": "start_timestamp",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "End timestamp",
-                        "name": "end_timestamp",
-                        "in": "query"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "allOf": [
-                                {
-                                    "$ref": "#/definitions/middleware.APIResponse"
-                                },
-                                {
-                                    "type": "object",
-                                    "properties": {
-                                        "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/model.CostRank"
-                                            }
-                                        }
-                                    }
-                                }
-                            ]
-                        }
-                    }
-                }
-            }
-        },
         "/api/models/builtin": {
             "get": {
                 "security": [
@@ -9288,50 +9123,6 @@ const docTemplate = `{
                 }
             }
         },
-        "model.CostRank": {
-            "type": "object",
-            "properties": {
-                "cache_creation_tokens": {
-                    "type": "integer"
-                },
-                "cached_tokens": {
-                    "type": "integer"
-                },
-                "input_tokens": {
-                    "type": "integer"
-                },
-                "max_rpm": {
-                    "type": "integer"
-                },
-                "max_rps": {
-                    "type": "integer"
-                },
-                "max_tpm": {
-                    "type": "integer"
-                },
-                "max_tps": {
-                    "type": "integer"
-                },
-                "model": {
-                    "type": "string"
-                },
-                "output_tokens": {
-                    "type": "integer"
-                },
-                "request_count": {
-                    "type": "integer"
-                },
-                "total_tokens": {
-                    "type": "integer"
-                },
-                "used_amount": {
-                    "type": "number"
-                },
-                "web_search_count": {
-                    "type": "integer"
-                }
-            }
-        },
         "model.DashboardResponse": {
             "type": "object",
             "properties": {

+ 2 - 211
core/docs/swagger.json

@@ -2555,8 +2555,7 @@
                         "type": "string",
                         "description": "Keyword",
                         "name": "keyword",
-                        "in": "query",
-                        "required": true
+                        "in": "query"
                     },
                     {
                         "type": "integer",
@@ -2594,12 +2593,6 @@
                         "name": "model_name",
                         "in": "query"
                     },
-                    {
-                        "type": "integer",
-                        "description": "Filter by channel",
-                        "name": "channel",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Filter by token id",
@@ -2687,12 +2680,6 @@
                 ],
                 "summary": "Get all logs",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Page number",
@@ -2717,12 +2704,6 @@
                         "name": "end_timestamp",
                         "in": "query"
                     },
-                    {
-                        "type": "string",
-                        "description": "Token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Model name",
@@ -2735,12 +2716,6 @@
                         "name": "channel",
                         "in": "query"
                     },
-                    {
-                        "type": "integer",
-                        "description": "Token ID",
-                        "name": "token_id",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Order",
@@ -3042,18 +3017,11 @@
                 ],
                 "summary": "Search logs",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Keyword",
                         "name": "keyword",
-                        "in": "query",
-                        "required": true
+                        "in": "query"
                     },
                     {
                         "type": "integer",
@@ -3079,12 +3047,6 @@
                         "name": "end_timestamp",
                         "in": "query"
                     },
-                    {
-                        "type": "string",
-                        "description": "Filter by token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
                     {
                         "type": "string",
                         "description": "Filter by model name",
@@ -4445,133 +4407,6 @@
                 }
             }
         },
-        "/api/model_cost_rank/": {
-            "get": {
-                "security": [
-                    {
-                        "ApiKeyAuth": []
-                    }
-                ],
-                "description": "Returns ranking data for models based on cost",
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "dashboard"
-                ],
-                "summary": "Get model cost ranking data",
-                "parameters": [
-                    {
-                        "type": "integer",
-                        "description": "Channel ID",
-                        "name": "channel",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Start timestamp",
-                        "name": "start_timestamp",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "End timestamp",
-                        "name": "end_timestamp",
-                        "in": "query"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "allOf": [
-                                {
-                                    "$ref": "#/definitions/middleware.APIResponse"
-                                },
-                                {
-                                    "type": "object",
-                                    "properties": {
-                                        "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/model.CostRank"
-                                            }
-                                        }
-                                    }
-                                }
-                            ]
-                        }
-                    }
-                }
-            }
-        },
-        "/api/model_cost_rank/{group}": {
-            "get": {
-                "security": [
-                    {
-                        "ApiKeyAuth": []
-                    }
-                ],
-                "description": "Returns model cost ranking data specific to the given group",
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "dashboard"
-                ],
-                "summary": "Get model cost ranking data for a specific group",
-                "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group",
-                        "name": "group",
-                        "in": "path",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Token name",
-                        "name": "token_name",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Start timestamp",
-                        "name": "start_timestamp",
-                        "in": "query"
-                    },
-                    {
-                        "type": "integer",
-                        "description": "End timestamp",
-                        "name": "end_timestamp",
-                        "in": "query"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "allOf": [
-                                {
-                                    "$ref": "#/definitions/middleware.APIResponse"
-                                },
-                                {
-                                    "type": "object",
-                                    "properties": {
-                                        "data": {
-                                            "type": "array",
-                                            "items": {
-                                                "$ref": "#/definitions/model.CostRank"
-                                            }
-                                        }
-                                    }
-                                }
-                            ]
-                        }
-                    }
-                }
-            }
-        },
         "/api/models/builtin": {
             "get": {
                 "security": [
@@ -9279,50 +9114,6 @@
                 }
             }
         },
-        "model.CostRank": {
-            "type": "object",
-            "properties": {
-                "cache_creation_tokens": {
-                    "type": "integer"
-                },
-                "cached_tokens": {
-                    "type": "integer"
-                },
-                "input_tokens": {
-                    "type": "integer"
-                },
-                "max_rpm": {
-                    "type": "integer"
-                },
-                "max_rps": {
-                    "type": "integer"
-                },
-                "max_tpm": {
-                    "type": "integer"
-                },
-                "max_tps": {
-                    "type": "integer"
-                },
-                "model": {
-                    "type": "string"
-                },
-                "output_tokens": {
-                    "type": "integer"
-                },
-                "request_count": {
-                    "type": "integer"
-                },
-                "total_tokens": {
-                    "type": "integer"
-                },
-                "used_amount": {
-                    "type": "number"
-                },
-                "web_search_count": {
-                    "type": "integer"
-                }
-            }
-        },
         "model.DashboardResponse": {
             "type": "object",
             "properties": {

+ 0 - 130
core/docs/swagger.yaml

@@ -808,35 +808,6 @@ definitions:
       rejected_prediction_tokens:
         type: integer
     type: object
-  model.CostRank:
-    properties:
-      cache_creation_tokens:
-        type: integer
-      cached_tokens:
-        type: integer
-      input_tokens:
-        type: integer
-      max_rpm:
-        type: integer
-      max_rps:
-        type: integer
-      max_tpm:
-        type: integer
-      max_tps:
-        type: integer
-      model:
-        type: string
-      output_tokens:
-        type: integer
-      request_count:
-        type: integer
-      total_tokens:
-        type: integer
-      used_amount:
-        type: number
-      web_search_count:
-        type: integer
-    type: object
   model.DashboardResponse:
     properties:
       cache_creation_tokens:
@@ -3496,7 +3467,6 @@ paths:
       - description: Keyword
         in: query
         name: keyword
-        required: true
         type: string
       - description: Page number
         in: query
@@ -3522,10 +3492,6 @@ paths:
         in: query
         name: model_name
         type: string
-      - description: Filter by channel
-        in: query
-        name: channel
-        type: integer
       - description: Filter by token id
         in: query
         name: token_id
@@ -3604,10 +3570,6 @@ paths:
     get:
       description: Returns a paginated list of all logs with optional filters
       parameters:
-      - description: Group or *
-        in: query
-        name: group
-        type: string
       - description: Page number
         in: query
         name: page
@@ -3624,10 +3586,6 @@ paths:
         in: query
         name: end_timestamp
         type: integer
-      - description: Token name
-        in: query
-        name: token_name
-        type: string
       - description: Model name
         in: query
         name: model_name
@@ -3636,10 +3594,6 @@ paths:
         in: query
         name: channel
         type: integer
-      - description: Token ID
-        in: query
-        name: token_id
-        type: integer
       - description: Order
         in: query
         name: order
@@ -3795,14 +3749,9 @@ paths:
     get:
       description: Search logs with various filters
       parameters:
-      - description: Group or *
-        in: query
-        name: group
-        type: string
       - description: Keyword
         in: query
         name: keyword
-        required: true
         type: string
       - description: Page number
         in: query
@@ -3820,10 +3769,6 @@ paths:
         in: query
         name: end_timestamp
         type: integer
-      - description: Filter by token name
-        in: query
-        name: token_name
-        type: string
       - description: Filter by model name
         in: query
         name: model_name
@@ -4641,81 +4586,6 @@ paths:
       summary: Search model configs
       tags:
       - modelconfig
-  /api/model_cost_rank/:
-    get:
-      description: Returns ranking data for models based on cost
-      parameters:
-      - description: Channel ID
-        in: query
-        name: channel
-        type: integer
-      - description: Start timestamp
-        in: query
-        name: start_timestamp
-        type: integer
-      - description: End timestamp
-        in: query
-        name: end_timestamp
-        type: integer
-      produces:
-      - application/json
-      responses:
-        "200":
-          description: OK
-          schema:
-            allOf:
-            - $ref: '#/definitions/middleware.APIResponse'
-            - properties:
-                data:
-                  items:
-                    $ref: '#/definitions/model.CostRank'
-                  type: array
-              type: object
-      security:
-      - ApiKeyAuth: []
-      summary: Get model cost ranking data
-      tags:
-      - dashboard
-  /api/model_cost_rank/{group}:
-    get:
-      description: Returns model cost ranking data specific to the given group
-      parameters:
-      - description: Group
-        in: path
-        name: group
-        required: true
-        type: string
-      - description: Token name
-        in: query
-        name: token_name
-        type: string
-      - description: Start timestamp
-        in: query
-        name: start_timestamp
-        type: integer
-      - description: End timestamp
-        in: query
-        name: end_timestamp
-        type: integer
-      produces:
-      - application/json
-      responses:
-        "200":
-          description: OK
-          schema:
-            allOf:
-            - $ref: '#/definitions/middleware.APIResponse'
-            - properties:
-                data:
-                  items:
-                    $ref: '#/definitions/model.CostRank'
-                  type: array
-              type: object
-      security:
-      - ApiKeyAuth: []
-      summary: Get model cost ranking data for a specific group
-      tags:
-      - dashboard
   /api/models/builtin:
     get:
       description: Returns a list of builtin models

+ 18 - 28
core/model/log.go

@@ -252,7 +252,7 @@ func GetLogDetail(logID int) (*RequestDetail, error) {
 }
 
 func GetGroupLogDetail(logID int, group string) (*RequestDetail, error) {
-	if group == "" || group == "*" {
+	if group == "" {
 		return nil, errors.New("invalid group parameter")
 	}
 	var detail RequestDetail
@@ -497,9 +497,7 @@ func buildGetLogsQuery(
 		tx = tx.Where("ip = ?", ip)
 	}
 
-	if group == "" {
-		tx = tx.Where("group_id = ''")
-	} else if group != "*" {
+	if group != "" {
 		tx = tx.Where("group_id = ?", group)
 	}
 	if modelName != "" {
@@ -622,13 +620,10 @@ func getLogs(
 }
 
 func GetLogs(
-	group string,
 	startTimestamp time.Time,
 	endTimestamp time.Time,
 	modelName string,
 	requestID string,
-	tokenID int,
-	tokenName string,
 	channelID int,
 	order string,
 	codeType CodeType,
@@ -647,20 +642,20 @@ func GetLogs(
 
 	g.Go(func() error {
 		var err error
-		channels, err = GetUsedChannels(group, startTimestamp, endTimestamp)
+		channels, err = GetUsedChannels(startTimestamp, endTimestamp)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
 		total, logs, err = getLogs(
-			group,
+			"",
 			startTimestamp,
 			endTimestamp,
 			modelName,
 			requestID,
-			tokenID,
-			tokenName,
+			0,
+			"",
 			channelID,
 			order,
 			codeType,
@@ -695,7 +690,6 @@ func GetGroupLogs(
 	requestID string,
 	tokenID int,
 	tokenName string,
-	channelID int,
 	order string,
 	codeType CodeType,
 	code int,
@@ -720,14 +714,15 @@ func GetGroupLogs(
 
 	g.Go(func() error {
 		var err error
-		total, logs, err = getLogs(group,
+		total, logs, err = getLogs(
+			group,
 			startTimestamp,
 			endTimestamp,
 			modelName,
 			requestID,
 			tokenID,
 			tokenName,
-			channelID,
+			0,
 			order,
 			codeType,
 			code,
@@ -742,13 +737,13 @@ func GetGroupLogs(
 
 	g.Go(func() error {
 		var err error
-		tokenNames, err = GetUsedTokenNames(group, startTimestamp, endTimestamp)
+		tokenNames, err = GetGroupUsedTokenNames(group, startTimestamp, endTimestamp)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
-		models, err = GetUsedModels(group, tokenName, startTimestamp, endTimestamp)
+		models, err = GetGroupUsedModels(group, tokenName, startTimestamp, endTimestamp)
 		return err
 	})
 
@@ -790,9 +785,7 @@ func buildSearchLogsQuery(
 		tx = tx.Where("ip = ?", ip)
 	}
 
-	if group == "" {
-		tx = tx.Where("group_id = ''")
-	} else if group != "*" {
+	if group != "" {
 		tx = tx.Where("group_id = ?", group)
 	}
 	if modelName != "" {
@@ -966,11 +959,9 @@ func searchLogs(
 }
 
 func SearchLogs(
-	group string,
 	keyword string,
 	requestID string,
 	tokenID int,
-	tokenName string,
 	modelName string,
 	startTimestamp time.Time,
 	endTimestamp time.Time,
@@ -993,11 +984,11 @@ func SearchLogs(
 	g.Go(func() error {
 		var err error
 		total, logs, err = searchLogs(
-			group,
+			"",
 			keyword,
 			requestID,
 			tokenID,
-			tokenName,
+			"",
 			modelName,
 			startTimestamp,
 			endTimestamp,
@@ -1016,7 +1007,7 @@ func SearchLogs(
 
 	g.Go(func() error {
 		var err error
-		channels, err = GetUsedChannels(group, startTimestamp, endTimestamp)
+		channels, err = GetUsedChannels(startTimestamp, endTimestamp)
 		return err
 	})
 
@@ -1042,7 +1033,6 @@ func SearchGroupLogs(
 	modelName string,
 	startTimestamp time.Time,
 	endTimestamp time.Time,
-	channelID int,
 	order string,
 	codeType CodeType,
 	code int,
@@ -1075,7 +1065,7 @@ func SearchGroupLogs(
 			modelName,
 			startTimestamp,
 			endTimestamp,
-			channelID,
+			0,
 			order,
 			codeType,
 			code,
@@ -1090,13 +1080,13 @@ func SearchGroupLogs(
 
 	g.Go(func() error {
 		var err error
-		tokenNames, err = GetUsedTokenNames(group, startTimestamp, endTimestamp)
+		tokenNames, err = GetGroupUsedTokenNames(group, startTimestamp, endTimestamp)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
-		models, err = GetUsedModels(group, tokenName, startTimestamp, endTimestamp)
+		models, err = GetGroupUsedModels(group, tokenName, startTimestamp, endTimestamp)
 		return err
 	})
 

+ 115 - 95
core/model/summary.go

@@ -234,26 +234,16 @@ func createSummary(unique SummaryUnique, data SummaryData) error {
 }
 
 func getChartData(
-	group string,
 	start, end time.Time,
-	tokenName, modelName string,
 	channelID int,
+	modelName string,
 	timeSpan TimeSpanType,
 	timezone *time.Location,
 ) ([]*ChartData, error) {
-	var query *gorm.DB
+	query := LogDB.Model(&Summary{})
 
-	if group == "*" || channelID != 0 {
-		query = LogDB.Model(&Summary{})
-		if channelID != 0 {
-			query = query.Where("channel_id = ?", channelID)
-		}
-	} else {
-		query = LogDB.Model(&GroupSummary{}).
-			Where("group_id = ?", group)
-		if tokenName != "" {
-			query = query.Where("token_name = ?", tokenName)
-		}
+	if channelID != 0 {
+		query = query.Where("channel_id = ?", channelID)
 	}
 
 	if modelName != "" {
@@ -276,7 +266,7 @@ func getChartData(
 		"sum(total_tokens) as total_tokens, sum(web_search_count) as web_search_count"
 
 	// Only include max metrics when querying for a specific channel and model
-	if (channelID != 0 && modelName != "") || (group != "*" && tokenName != "" && modelName != "") {
+	if channelID != 0 && modelName != "" {
 		selectFields += ", max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tpm, max(max_tps) as max_tps"
 	} else {
 		// Set max metrics to 0 when not querying for specific channel and model
@@ -302,23 +292,85 @@ func getChartData(
 	return chartData, nil
 }
 
-func GetUsedChannels(group string, start, end time.Time) ([]int, error) {
-	if group != "*" {
-		return []int{}, nil
+func getGroupChartData(
+	group string,
+	start, end time.Time,
+	tokenName, modelName string,
+	timeSpan TimeSpanType,
+	timezone *time.Location,
+) ([]*ChartData, error) {
+	query := LogDB.Model(&GroupSummary{})
+	if group != "" {
+		query = query.Where("group_id = ?", group)
+	}
+	if tokenName != "" {
+		query = query.Where("token_name = ?", tokenName)
+	}
+
+	if modelName != "" {
+		query = query.Where("model = ?", modelName)
+	}
+
+	switch {
+	case !start.IsZero() && !end.IsZero():
+		query = query.Where("hour_timestamp BETWEEN ? AND ?", start.Unix(), end.Unix())
+	case !start.IsZero():
+		query = query.Where("hour_timestamp >= ?", start.Unix())
+	case !end.IsZero():
+		query = query.Where("hour_timestamp <= ?", end.Unix())
+	}
+
+	// Only include max metrics when we have specific channel and model
+	selectFields := "hour_timestamp as timestamp, sum(request_count) as request_count, sum(used_amount) as used_amount, " +
+		"sum(exception_count) as exception_count, sum(input_tokens) as input_tokens, sum(output_tokens) as output_tokens, " +
+		"sum(cached_tokens) as cached_tokens, sum(cache_creation_tokens) as cache_creation_tokens, " +
+		"sum(total_tokens) as total_tokens, sum(web_search_count) as web_search_count"
+
+	// Only include max metrics when querying for a specific channel and model
+	if group != "" && tokenName != "" && modelName != "" {
+		selectFields += ", max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tpm, max(max_tps) as max_tps"
+	} else {
+		// Set max metrics to 0 when not querying for specific channel and model
+		selectFields += ", 0 as max_rpm, 0 as max_rps, 0 as max_tpm, 0 as max_tps"
+	}
+
+	query = query.
+		Select(selectFields).
+		Group("timestamp").
+		Order("timestamp ASC")
+
+	var chartData []*ChartData
+	err := query.Scan(&chartData).Error
+	if err != nil {
+		return nil, err
 	}
-	return getLogGroupByValues[int]("channel_id", group, "", start, end)
+
+	// If timeSpan is day, aggregate hour data into day data
+	if timeSpan == TimeSpanDay && len(chartData) > 0 {
+		return aggregateHourDataToDay(chartData, timezone), nil
+	}
+
+	return chartData, nil
+}
+
+func GetUsedChannels(start, end time.Time) ([]int, error) {
+	return getLogGroupByValues[int]("channel_id", start, end)
+}
+
+func GetUsedModels(start, end time.Time) ([]string, error) {
+	return getLogGroupByValues[string]("model", start, end)
 }
 
-func GetUsedModels(group, tokenName string, start, end time.Time) ([]string, error) {
-	return getLogGroupByValues[string]("model", group, tokenName, start, end)
+func GetGroupUsedModels(group, tokenName string, start, end time.Time) ([]string, error) {
+	return getGroupLogGroupByValues[string]("model", group, tokenName, start, end)
 }
 
-func GetUsedTokenNames(group string, start, end time.Time) ([]string, error) {
-	return getLogGroupByValues[string]("token_name", group, "", start, end)
+func GetGroupUsedTokenNames(group string, start, end time.Time) ([]string, error) {
+	return getGroupLogGroupByValues[string]("token_name", group, "", start, end)
 }
 
 func getLogGroupByValues[T cmp.Ordered](
-	field, group, tokenName string,
+	field string,
 	start, end time.Time,
 ) ([]T, error) {
 	type Result struct {
@@ -330,17 +382,8 @@ func getLogGroupByValues[T cmp.Ordered](
 
 	var query *gorm.DB
 
-	if group == "*" {
-		query = LogDB.
-			Model(&Summary{})
-	} else {
-		query = LogDB.
-			Model(&GroupSummary{}).
-			Where("group_id = ?", group)
-		if tokenName != "" {
-			query = query.Where("token_name = ?", tokenName)
-		}
-	}
+	query = LogDB.
+		Model(&Summary{})
 
 	switch {
 	case !start.IsZero() && !end.IsZero():
@@ -379,42 +422,24 @@ func getLogGroupByValues[T cmp.Ordered](
 	return values, nil
 }
 
-type CostRank struct {
-	Model               string  `json:"model"`
-	UsedAmount          float64 `json:"used_amount"`
-	InputTokens         int64   `json:"input_tokens"`
-	OutputTokens        int64   `json:"output_tokens"`
-	CachedTokens        int64   `json:"cached_tokens"`
-	CacheCreationTokens int64   `json:"cache_creation_tokens"`
-	TotalTokens         int64   `json:"total_tokens"`
-	RequestCount        int64   `json:"request_count"`
-	WebSearchCount      int64   `json:"web_search_count"`
-
-	MaxRPM int64 `json:"max_rpm,omitempty"`
-	MaxRPS int64 `json:"max_rps,omitempty"`
-	MaxTPM int64 `json:"max_tpm,omitempty"`
-	MaxTPS int64 `json:"max_tps,omitempty"`
-}
-
-func GetModelCostRank(
-	group, tokenName string,
-	channelID int,
+func getGroupLogGroupByValues[T cmp.Ordered](
+	field, group, tokenName string,
 	start, end time.Time,
-) ([]*CostRank, error) {
-	var ranks []*CostRank
+) ([]T, error) {
+	type Result struct {
+		Value        T
+		UsedAmount   float64
+		RequestCount int64
+	}
+	var results []Result
 
-	var query *gorm.DB
-	if group == "*" || channelID != 0 {
-		query = LogDB.Model(&Summary{})
-		if channelID != 0 {
-			query = query.Where("channel_id = ?", channelID)
-		}
-	} else {
-		query = LogDB.Model(&GroupSummary{}).
-			Where("group_id = ?", group)
-		if tokenName != "" {
-			query = query.Where("token_name = ?", tokenName)
-		}
+	query := LogDB.
+		Model(&GroupSummary{})
+	if group != "" {
+		query = query.Where("group_id = ?", group)
+	}
+	if tokenName != "" {
+		query = query.Where("token_name = ?", tokenName)
 	}
 
 	switch {
@@ -426,36 +451,32 @@ func GetModelCostRank(
 		query = query.Where("hour_timestamp <= ?", end.Unix())
 	}
 
-	selectFields := "model, SUM(used_amount) as used_amount, SUM(request_count) as request_count, SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens, SUM(cached_tokens) as cached_tokens, SUM(cache_creation_tokens) as cache_creation_tokens, SUM(total_tokens) as total_tokens"
-	if (channelID != 0) || (group != "*" && tokenName != "") {
-		selectFields += ", max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tps, max(max_tps) as max_tps"
-	} else {
-		selectFields += ", 0 as max_rpm, 0 as max_rps, 0 as max_tpm, 0 as max_tps"
-	}
-
-	query = query.
-		Select(selectFields).
-		Group("model")
-
-	err := query.Scan(&ranks).Error
+	err := query.
+		Select(
+			field + " as value, SUM(request_count) as request_count, SUM(used_amount) as used_amount",
+		).
+		Group(field).
+		Scan(&results).Error
 	if err != nil {
 		return nil, err
 	}
 
-	slices.SortFunc(ranks, func(a, b *CostRank) int {
+	slices.SortFunc(results, func(a, b Result) int {
 		if a.UsedAmount != b.UsedAmount {
 			return cmp.Compare(b.UsedAmount, a.UsedAmount)
 		}
-		if a.TotalTokens != b.TotalTokens {
-			return cmp.Compare(b.TotalTokens, a.TotalTokens)
-		}
 		if a.RequestCount != b.RequestCount {
 			return cmp.Compare(b.RequestCount, a.RequestCount)
 		}
-		return cmp.Compare(a.Model, b.Model)
+		return cmp.Compare(a.Value, b.Value)
 	})
 
-	return ranks, nil
+	values := make([]T, len(results))
+	for i, result := range results {
+		values[i] = result.Value
+	}
+
+	return values, nil
 }
 
 type ChartData struct {
@@ -631,19 +652,19 @@ func GetDashboardData(
 
 	g.Go(func() error {
 		var err error
-		chartData, err = getChartData("*", start, end, "", modelName, channelID, timeSpan, timezone)
+		chartData, err = getChartData(start, end, channelID, modelName, timeSpan, timezone)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
-		channels, err = GetUsedChannels("*", start, end)
+		channels, err = GetUsedChannels(start, end)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
-		models, err = GetUsedModels("*", "", start, end)
+		models, err = GetUsedModels(start, end)
 		return err
 	})
 
@@ -666,7 +687,7 @@ func GetGroupDashboardData(
 	timeSpan TimeSpanType,
 	timezone *time.Location,
 ) (*GroupDashboardResponse, error) {
-	if group == "" || group == "*" {
+	if group == "" {
 		return nil, errors.New("group is required")
 	}
 
@@ -686,13 +707,12 @@ func GetGroupDashboardData(
 
 	g.Go(func() error {
 		var err error
-		chartData, err = getChartData(
+		chartData, err = getGroupChartData(
 			group,
 			start,
 			end,
 			tokenName,
 			modelName,
-			0,
 			timeSpan,
 			timezone,
 		)
@@ -701,13 +721,13 @@ func GetGroupDashboardData(
 
 	g.Go(func() error {
 		var err error
-		tokenNames, err = GetUsedTokenNames(group, start, end)
+		tokenNames, err = GetGroupUsedTokenNames(group, start, end)
 		return err
 	})
 
 	g.Go(func() error {
 		var err error
-		models, err = GetUsedModels(group, tokenName, start, end)
+		models, err = GetGroupUsedModels(group, tokenName, start, end)
 		return err
 	})
 

+ 0 - 6
core/router/api.go

@@ -41,12 +41,6 @@ func SetAPIRouter(router *gin.Engine) {
 			dashboardRoute.GET("/:group/models", controller.GetGroupDashboardModels)
 		}
 
-		modelCostRankRoute := apiRouter.Group("/model_cost_rank")
-		{
-			modelCostRankRoute.GET("/", controller.GetModelCostRank)
-			modelCostRankRoute.GET("/:group", controller.GetGroupModelCostRank)
-		}
-
 		dashboardV2Route := apiRouter.Group("/dashboardv2")
 		{
 			dashboardV2Route.GET("/", controller.GetTimeSeriesModelData)