Skip to content

Commit

Permalink
feat: dashboard timespan
Browse files Browse the repository at this point in the history
  • Loading branch information
zijiren233 committed Dec 31, 2024
1 parent 9e38776 commit 8bfbe9e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 30 deletions.
35 changes: 18 additions & 17 deletions service/aiproxy/controller/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ import (
"github.com/labring/sealos/service/aiproxy/model"
)

func getDashboardStartEndTime(t string) (time.Time, time.Time) {
func getDashboardTime(t string) (time.Time, time.Time, time.Duration) {
end := time.Now()
var start time.Time
var timeSpan time.Duration
switch t {
case "month":
start = end.AddDate(0, 0, -30)
timeSpan = time.Hour * 24
case "two_week":
start = end.AddDate(0, 0, -15)
timeSpan = time.Hour * 12
case "week":
start = end.AddDate(0, 0, -7)
timeSpan = time.Hour * 6
case "day":
fallthrough
default:
start = end.AddDate(0, 0, -1)
timeSpan = time.Hour * 1
}
return start, end
return start, end, timeSpan
}

const (
fillGapsInterval = 3600
)

func fillGaps(data []*model.HourlyChartData) []*model.HourlyChartData {
func fillGaps(data []*model.HourlyChartData, timeSpan time.Duration) []*model.HourlyChartData {
if len(data) <= 1 {
return data
}
Expand All @@ -42,7 +43,7 @@ func fillGaps(data []*model.HourlyChartData) []*model.HourlyChartData {
for i := 1; i < len(data); i++ {
curr := data[i]
prev := data[i-1]
hourDiff := (curr.Timestamp - prev.Timestamp) / fillGapsInterval
hourDiff := (curr.Timestamp - prev.Timestamp) / int64(timeSpan.Seconds())

// If gap is 1 hour or less, continue
if hourDiff <= 1 {
Expand All @@ -54,18 +55,18 @@ func fillGaps(data []*model.HourlyChartData) []*model.HourlyChartData {
if hourDiff > 3 {
// Add point for hour after prev
result = append(result, &model.HourlyChartData{
Timestamp: prev.Timestamp + fillGapsInterval,
Timestamp: prev.Timestamp + int64(timeSpan.Seconds()),
})
// Add point for hour before curr
result = append(result, &model.HourlyChartData{
Timestamp: curr.Timestamp - fillGapsInterval,
Timestamp: curr.Timestamp - int64(timeSpan.Seconds()),
})
result = append(result, curr)
continue
}

// Fill gaps of 2-3 hours with zero points
for j := prev.Timestamp + fillGapsInterval; j < curr.Timestamp; j += fillGapsInterval {
for j := prev.Timestamp + int64(timeSpan.Seconds()); j < curr.Timestamp; j += int64(timeSpan.Seconds()) {
result = append(result, &model.HourlyChartData{
Timestamp: j,
})
Expand All @@ -77,15 +78,15 @@ func fillGaps(data []*model.HourlyChartData) []*model.HourlyChartData {
}

func GetDashboard(c *gin.Context) {
start, end := getDashboardStartEndTime(c.Query("type"))
start, end, timeSpan := getDashboardTime(c.Query("type"))
modelName := c.Query("model")
dashboards, err := model.GetDashboardData(start, end, modelName)
dashboards, err := model.GetDashboardData(start, end, modelName, timeSpan)
if err != nil {
middleware.ErrorResponse(c, http.StatusOK, err.Error())
return
}

dashboards.ChartData = fillGaps(dashboards.ChartData)
dashboards.ChartData = fillGaps(dashboards.ChartData, timeSpan)
middleware.SuccessResponse(c, dashboards)
}

Expand All @@ -96,16 +97,16 @@ func GetGroupDashboard(c *gin.Context) {
return
}

start, end := getDashboardStartEndTime(c.Query("type"))
start, end, timeSpan := getDashboardTime(c.Query("type"))
tokenName := c.Query("token_name")
modelName := c.Query("model")

dashboards, err := model.GetGroupDashboardData(group, start, end, tokenName, modelName)
dashboards, err := model.GetGroupDashboardData(group, start, end, tokenName, modelName, timeSpan)
if err != nil {
middleware.ErrorResponse(c, http.StatusOK, "failed to get statistics")
return
}

dashboards.ChartData = fillGaps(dashboards.ChartData)
dashboards.ChartData = fillGaps(dashboards.ChartData, timeSpan)
middleware.SuccessResponse(c, dashboards)
}
26 changes: 13 additions & 13 deletions service/aiproxy/model/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,29 +627,29 @@ type GroupDashboardResponse struct {
TokenNames []string `json:"token_names"`
}

func getHourTimestamp() string {
func getTimeSpanFormat(timeSpan time.Duration) string {
switch {
case common.UsingMySQL:
return "UNIX_TIMESTAMP(DATE_FORMAT(request_at, '%Y-%m-%d %H:00:00'))"
return fmt.Sprintf("UNIX_TIMESTAMP(DATE_FORMAT(request_at, '%%Y-%%m-%%d %%H:%%i:00')) DIV %d * %d", int64(timeSpan.Seconds()), int64(timeSpan.Seconds()))
case common.UsingPostgreSQL:
return "FLOOR(EXTRACT(EPOCH FROM date_trunc('hour', request_at)))"
return fmt.Sprintf("FLOOR(EXTRACT(EPOCH FROM date_trunc('minute', request_at)) / %d) * %d", int64(timeSpan.Seconds()), int64(timeSpan.Seconds()))
case common.UsingSQLite:
return "STRFTIME('%s', STRFTIME('%Y-%m-%d %H:00:00', request_at))"
return fmt.Sprintf("CAST(STRFTIME('%%s', STRFTIME('%%Y-%%m-%%d %%H:%%M:00', request_at)) AS INTEGER) / %d * %d", int64(timeSpan.Seconds()), int64(timeSpan.Seconds()))
default:
return ""
}
}

func getChartData(group string, start, end time.Time, tokenName, modelName string) ([]*HourlyChartData, error) {
func getChartData(group string, start, end time.Time, tokenName, modelName string, timeSpan time.Duration) ([]*HourlyChartData, error) {
var chartData []*HourlyChartData

hourTimestamp := getHourTimestamp()
if hourTimestamp == "" {
return nil, errors.New("unsupported hour format")
timeSpanFormat := getTimeSpanFormat(timeSpan)
if timeSpanFormat == "" {
return nil, errors.New("unsupported time format")
}

query := LogDB.Table("logs").
Select(hourTimestamp + " as timestamp, count(*) as request_count, sum(used_amount) as used_amount, sum(case when code != 200 then 1 else 0 end) as exception_count").
Select(timeSpanFormat + " as timestamp, count(*) as request_count, sum(used_amount) as used_amount, sum(case when code != 200 then 1 else 0 end) as exception_count").
Group("timestamp").
Order("timestamp ASC")

Expand Down Expand Up @@ -758,14 +758,14 @@ func getTPM(group string, end time.Time, tokenName, modelName string) (int64, er
return tpm, err
}

func GetDashboardData(start, end time.Time, modelName string) (*DashboardResponse, error) {
func GetDashboardData(start, end time.Time, modelName string, timeSpan time.Duration) (*DashboardResponse, error) {
if end.IsZero() {
end = time.Now()
} else if end.Before(start) {
return nil, errors.New("end time is before start time")
}

chartData, err := getChartData("", start, end, "", modelName)
chartData, err := getChartData("", start, end, "", modelName, timeSpan)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -800,7 +800,7 @@ func GetDashboardData(start, end time.Time, modelName string) (*DashboardRespons
}, nil
}

func GetGroupDashboardData(group string, start, end time.Time, tokenName string, modelName string) (*GroupDashboardResponse, error) {
func GetGroupDashboardData(group string, start, end time.Time, tokenName string, modelName string, timeSpan time.Duration) (*GroupDashboardResponse, error) {
if group == "" {
return nil, errors.New("group is required")
}
Expand All @@ -811,7 +811,7 @@ func GetGroupDashboardData(group string, start, end time.Time, tokenName string,
return nil, errors.New("end time is before start time")
}

chartData, err := getChartData(group, start, end, tokenName, modelName)
chartData, err := getChartData(group, start, end, tokenName, modelName, timeSpan)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 8bfbe9e

Please sign in to comment.