Browse Source

feat: smart parse timestamp (#257)

* feat: smart parse timestamp

* chore: swag

* fix: ci lint
zijiren 6 months ago
parent
commit
ab3720bcb7

+ 5 - 4
core/controller/dashboard.go

@@ -10,6 +10,7 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/labring/aiproxy/core/common/reqlimit"
+	"github.com/labring/aiproxy/core/controller/utils"
 	"github.com/labring/aiproxy/core/middleware"
 	"github.com/labring/aiproxy/core/model"
 	"gorm.io/gorm"
@@ -337,12 +338,12 @@ func GetGroupDashboardModels(c *gin.Context) {
 //	@Param			start_timestamp	query		int64	false	"Start timestamp"
 //	@Param			end_timestamp	query		int64	false	"End timestamp"
 //	@Param			timezone		query		string	false	"Timezone, default is Local"
-//	@Param			timespan		query		string	false	"Time span type (day, hour)"
+//	@Param			timespan		query		string	false	"Time span type (day, hour, minute)"
 //	@Success		200				{object}	middleware.APIResponse{data=[]model.TimeModelData}
 //	@Router			/api/dashboardv2/ [get]
 func GetTimeSeriesModelData(c *gin.Context) {
 	channelID, _ := strconv.Atoi(c.Query("channel"))
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, -1)
 	timezoneLocation, _ := time.LoadLocation(c.DefaultQuery("timezone", "Local"))
 	models, err := model.GetTimeSeriesModelDataMinute(
 		channelID,
@@ -370,7 +371,7 @@ func GetTimeSeriesModelData(c *gin.Context) {
 //	@Param			start_timestamp	query		int64	false	"Start timestamp"
 //	@Param			end_timestamp	query		int64	false	"End timestamp"
 //	@Param			timezone		query		string	false	"Timezone, default is Local"
-//	@Param			timespan		query		string	false	"Time span type (day, hour)"
+//	@Param			timespan		query		string	false	"Time span type (day, hour, minute)"
 //	@Success		200				{object}	middleware.APIResponse{data=[]model.TimeModelData}
 //	@Router			/api/dashboardv2/{group} [get]
 func GetGroupTimeSeriesModelData(c *gin.Context) {
@@ -380,7 +381,7 @@ func GetGroupTimeSeriesModelData(c *gin.Context) {
 		return
 	}
 	tokenName := c.Query("token_name")
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, -1)
 	timezoneLocation, _ := time.LoadLocation(c.DefaultQuery("timezone", "Local"))
 	models, err := model.GetGroupTimeSeriesModelDataMinute(
 		group,

+ 1 - 1
core/controller/group.go

@@ -731,7 +731,7 @@ func UpdateGroupModelConfigs(c *gin.Context) {
 //	@Router			/api/groups/ip_groups [get]
 func GetIPGroupList(c *gin.Context) {
 	threshold, _ := strconv.Atoi(c.Query("threshold"))
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, 0)
 	ipGroupList, err := model.GetIPGroups(threshold, startTime, endTime)
 	if err != nil {
 		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())

+ 4 - 22
core/controller/log.go

@@ -11,24 +11,6 @@ import (
 	"github.com/labring/aiproxy/core/model"
 )
 
-func parseTimeRange(c *gin.Context) (startTime, endTime time.Time) {
-	startTimestamp, _ := strconv.ParseInt(c.Query("start_timestamp"), 10, 64)
-	endTimestamp, _ := strconv.ParseInt(c.Query("end_timestamp"), 10, 64)
-
-	if startTimestamp != 0 {
-		startTime = time.UnixMilli(startTimestamp)
-	}
-	sevenDaysAgo := time.Now().AddDate(0, 0, -7)
-	if startTime.IsZero() || startTime.Before(sevenDaysAgo) {
-		startTime = sevenDaysAgo
-	}
-
-	if endTimestamp != 0 {
-		endTime = time.UnixMilli(endTimestamp)
-	}
-	return
-}
-
 func parseCommonParams(c *gin.Context) (params struct {
 	tokenName string
 	modelName string
@@ -81,7 +63,7 @@ func parseCommonParams(c *gin.Context) (params struct {
 //	@Router			/api/logs/ [get]
 func GetLogs(c *gin.Context) {
 	page, perPage := utils.ParsePageParams(c)
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, 0)
 	params := parseCommonParams(c)
 
 	result, err := model.GetLogs(
@@ -139,7 +121,7 @@ func GetGroupLogs(c *gin.Context) {
 	}
 
 	page, perPage := utils.ParsePageParams(c)
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, 0)
 	params := parseCommonParams(c)
 
 	result, err := model.GetGroupLogs(
@@ -192,7 +174,7 @@ func GetGroupLogs(c *gin.Context) {
 //	@Router			/api/logs/search [get]
 func SearchLogs(c *gin.Context) {
 	page, perPage := utils.ParsePageParams(c)
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, 0)
 	params := parseCommonParams(c)
 
 	keyword := c.Query("keyword")
@@ -254,7 +236,7 @@ func SearchGroupLogs(c *gin.Context) {
 	}
 
 	page, perPage := utils.ParsePageParams(c)
-	startTime, endTime := parseTimeRange(c)
+	startTime, endTime := utils.ParseTimeRange(c, 0)
 	params := parseCommonParams(c)
 	keyword := c.Query("keyword")
 

+ 44 - 0
core/controller/utils/utils.go

@@ -2,6 +2,7 @@ package utils
 
 import (
 	"strconv"
+	"time"
 
 	"github.com/gin-gonic/gin"
 )
@@ -15,3 +16,46 @@ func ParsePageParams(c *gin.Context) (page, perPage int) {
 	perPage, _ = strconv.Atoi(c.Query("per_page"))
 	return
 }
+
+const (
+	defaultMaxSpan = time.Hour * 24 * 7
+)
+
+func ParseTimeRange(c *gin.Context, maxSpan time.Duration) (startTime, endTime time.Time) {
+	if maxSpan == 0 {
+		maxSpan = defaultMaxSpan
+	}
+	startTime, _ = smartParseTimestamp(c.Query("start_timestamp"))
+	endTime, _ = smartParseTimestamp(c.Query("end_timestamp"))
+
+	if endTime.IsZero() {
+		endTime = time.Now()
+	}
+	if maxSpan > 0 {
+		sevenDaysAgo := endTime.Add(maxSpan)
+		if startTime.IsZero() || startTime.Before(sevenDaysAgo) {
+			startTime = sevenDaysAgo
+		}
+	}
+
+	return
+}
+
+func smartParseTimestamp(timestampStr string) (time.Time, error) {
+	timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
+	if err != nil {
+		return time.Time{}, err
+	}
+	digits := len(timestampStr)
+
+	switch {
+	case digits <= 10:
+		return time.Unix(timestamp, 0), nil
+	case digits <= 13:
+		return time.UnixMilli(timestamp), nil
+	case digits <= 16:
+		return time.UnixMicro(timestamp), nil
+	default:
+		return time.Unix(0, timestamp), nil
+	}
+}

+ 2 - 2
core/docs/docs.go

@@ -1169,7 +1169,7 @@ const docTemplate = `{
                     },
                     {
                         "type": "string",
-                        "description": "Time span type (day, hour)",
+                        "description": "Time span type (day, hour, minute)",
                         "name": "timespan",
                         "in": "query"
                     }
@@ -1248,7 +1248,7 @@ const docTemplate = `{
                     },
                     {
                         "type": "string",
-                        "description": "Time span type (day, hour)",
+                        "description": "Time span type (day, hour, minute)",
                         "name": "timespan",
                         "in": "query"
                     }

+ 2 - 2
core/docs/swagger.json

@@ -1160,7 +1160,7 @@
                     },
                     {
                         "type": "string",
-                        "description": "Time span type (day, hour)",
+                        "description": "Time span type (day, hour, minute)",
                         "name": "timespan",
                         "in": "query"
                     }
@@ -1239,7 +1239,7 @@
                     },
                     {
                         "type": "string",
-                        "description": "Time span type (day, hour)",
+                        "description": "Time span type (day, hour, minute)",
                         "name": "timespan",
                         "in": "query"
                     }

+ 2 - 2
core/docs/swagger.yaml

@@ -2712,7 +2712,7 @@ paths:
         in: query
         name: timezone
         type: string
-      - description: Time span type (day, hour)
+      - description: Time span type (day, hour, minute)
         in: query
         name: timespan
         type: string
@@ -2760,7 +2760,7 @@ paths:
         in: query
         name: timezone
         type: string
-      - description: Time span type (day, hour)
+      - description: Time span type (day, hour, minute)
         in: query
         name: timespan
         type: string