feat: 统计表
This commit is contained in:
@@ -104,6 +104,7 @@ func (a *App) Start() error {
|
||||
// 数据库迁移
|
||||
if err := a.db.AutoMigrate(
|
||||
&models.RequestLog{},
|
||||
&models.GroupHourlyStat{},
|
||||
&models.APIKey{},
|
||||
&models.SystemSetting{},
|
||||
&models.Group{},
|
||||
|
@@ -98,3 +98,14 @@ type DashboardStats struct {
|
||||
SuccessRate float64 `json:"success_rate"`
|
||||
GroupStats []GroupRequestStat `json:"group_stats"`
|
||||
}
|
||||
|
||||
// GroupHourlyStat 对应 group_hourly_stats 表,用于存储每个分组每小时的请求统计
|
||||
type GroupHourlyStat struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
Time time.Time `gorm:"type:datetime;not null;uniqueIndex:idx_group_time" json:"time"` // 整点时间
|
||||
GroupID uint `gorm:"not null;uniqueIndex:idx_group_time" json:"group_id"`
|
||||
SuccessCount int64 `gorm:"not null;default:0" json:"success_count"`
|
||||
FailureCount int64 `gorm:"not null;default:0" json:"failure_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -222,6 +223,50 @@ func (s *RequestLogService) writeLogsToDB(logs []*models.RequestLog) error {
|
||||
return fmt.Errorf("failed to batch update api_key stats: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新统计表
|
||||
hourlyStats := make(map[struct {
|
||||
Time time.Time
|
||||
GroupID uint
|
||||
}]struct{ Success, Failure int64 })
|
||||
for _, log := range logs {
|
||||
hourlyTime := log.Timestamp.Truncate(time.Hour)
|
||||
key := struct {
|
||||
Time time.Time
|
||||
GroupID uint
|
||||
}{Time: hourlyTime, GroupID: log.GroupID}
|
||||
|
||||
counts := hourlyStats[key]
|
||||
if log.IsSuccess {
|
||||
counts.Success++
|
||||
} else {
|
||||
counts.Failure++
|
||||
}
|
||||
hourlyStats[key] = counts
|
||||
}
|
||||
|
||||
if len(hourlyStats) > 0 {
|
||||
for key, counts := range hourlyStats {
|
||||
err := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "time"}, {Name: "group_id"}},
|
||||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||||
"success_count": gorm.Expr("success_count + ?", counts.Success),
|
||||
"failure_count": gorm.Expr("failure_count + ?", counts.Failure),
|
||||
"updated_at": time.Now(),
|
||||
}),
|
||||
}).Create(&models.GroupHourlyStat{
|
||||
Time: key.Time,
|
||||
GroupID: key.GroupID,
|
||||
SuccessCount: counts.Success,
|
||||
FailureCount: counts.Failure,
|
||||
}).Error
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to upsert group hourly stat: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user