| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- package model
- import (
- "one-api/common"
- "strconv"
- "time"
- )
- // ChannelStatistics 按渠道统计的数据结构
- type ChannelStatistics struct {
- Time string `json:"time"`
- ChannelId int `json:"channel_id"`
- ChannelName string `json:"channel_name"`
- Quota int `json:"quota"`
- Count int `json:"count"`
- }
- // TokenStatistics 按令牌统计的数据结构
- type TokenStatistics struct {
- Time string `json:"time"`
- TokenName string `json:"token_name"`
- Quota int `json:"quota"`
- Count int `json:"count"`
- }
- // UserStatistics 按用户统计的数据结构
- type UserStatistics struct {
- Time string `json:"time"`
- Username string `json:"username"`
- Quota int `json:"quota"`
- Count int `json:"count"`
- }
- // GetChannelStatistics 获取按渠道统计的数据
- func GetChannelStatistics(startTimestamp, endTimestamp int, username, tokenName, modelName string, channel int, group, defaultTime string) ([]ChannelStatistics, error) {
- var statistics []ChannelStatistics
- // 构建查询条件
- tx := LOG_DB.Table("logs").Select(`
- created_at,
- channel_id,
- COUNT(*) as count,
- SUM(quota) as quota
- `).Where("type = ?", 2) // LogTypeConsume = 2
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if modelName != "" {
- tx = tx.Where("model_name LIKE ?", "%"+modelName+"%")
- }
- if channel != 0 {
- tx = tx.Where("channel_id = ?", channel)
- }
- if group != "" {
- tx = tx.Where("`group` = ?", group)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- // 按时间粒度分组 - 使用数据库无关的函数
- var groupBy string
- switch defaultTime {
- case "hour":
- if common.UsingMySQL {
- groupBy = "channel_id, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d %H:00:00')"
- } else if common.UsingPostgreSQL {
- groupBy = "channel_id, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD HH24:00:00')"
- } else {
- // SQLite
- groupBy = "channel_id, strftime('%Y-%m-%d %H:00:00', datetime(created_at, 'unixepoch'))"
- }
- case "day":
- if common.UsingMySQL {
- groupBy = "channel_id, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "channel_id, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "channel_id, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- case "week":
- if common.UsingMySQL {
- groupBy = "channel_id, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%U')"
- } else if common.UsingPostgreSQL {
- groupBy = "channel_id, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-IW')"
- } else {
- // SQLite
- groupBy = "channel_id, strftime('%Y-%W', datetime(created_at, 'unixepoch'))"
- }
- default:
- if common.UsingMySQL {
- groupBy = "channel_id, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "channel_id, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "channel_id, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- }
- // 按渠道和时间分组
- tx = tx.Group(groupBy).Order("MIN(created_at) ASC")
- // 执行查询
- var results []struct {
- CreatedAt int64 `json:"created_at"`
- ChannelId int `json:"channel_id"`
- Count int `json:"count"`
- Quota int `json:"quota"`
- }
- err := tx.Scan(&results).Error
- if err != nil {
- return nil, err
- }
- // 获取渠道名称映射
- channelIds := make([]int, 0)
- channelMap := make(map[int]string)
- for _, result := range results {
- if result.ChannelId != 0 {
- channelIds = append(channelIds, result.ChannelId)
- }
- }
- if len(channelIds) > 0 {
- var channels []struct {
- Id int `gorm:"column:id"`
- Name string `gorm:"column:name"`
- }
- if err = DB.Table("channels").Select("id, name").Where("id IN ?", channelIds).Find(&channels).Error; err != nil {
- return nil, err
- }
- for _, channel := range channels {
- channelMap[channel.Id] = channel.Name
- }
- }
- // 格式化时间并构建返回结果
- for _, result := range results {
- timeStr := formatTime(result.CreatedAt, defaultTime)
- statistics = append(statistics, ChannelStatistics{
- Time: timeStr,
- ChannelId: result.ChannelId,
- ChannelName: channelMap[result.ChannelId],
- Quota: result.Quota,
- Count: result.Count,
- })
- }
- return statistics, nil
- }
- // GetTokenStatistics 获取按令牌统计的数据
- func GetTokenStatistics(startTimestamp, endTimestamp int, username, tokenName, modelName string, channel int, group, defaultTime string) ([]TokenStatistics, error) {
- var statistics []TokenStatistics
- // 构建查询条件
- tx := LOG_DB.Table("logs").Select(`
- created_at,
- token_name,
- COUNT(*) as count,
- SUM(quota) as quota
- `).Where("type = ?", 2) // LogTypeConsume = 2
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if modelName != "" {
- tx = tx.Where("model_name LIKE ?", "%"+modelName+"%")
- }
- if channel != 0 {
- tx = tx.Where("channel_id = ?", channel)
- }
- if group != "" {
- tx = tx.Where("`group` = ?", group)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- // 按时间粒度分组 - 使用数据库无关的函数
- var groupBy string
- switch defaultTime {
- case "hour":
- if common.UsingMySQL {
- groupBy = "token_name, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d %H:00:00')"
- } else if common.UsingPostgreSQL {
- groupBy = "token_name, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD HH24:00:00')"
- } else {
- // SQLite
- groupBy = "token_name, strftime('%Y-%m-%d %H:00:00', datetime(created_at, 'unixepoch'))"
- }
- case "day":
- if common.UsingMySQL {
- groupBy = "token_name, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "token_name, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "token_name, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- case "week":
- if common.UsingMySQL {
- groupBy = "token_name, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%U')"
- } else if common.UsingPostgreSQL {
- groupBy = "token_name, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-IW')"
- } else {
- // SQLite
- groupBy = "token_name, strftime('%Y-%W', datetime(created_at, 'unixepoch'))"
- }
- default:
- if common.UsingMySQL {
- groupBy = "token_name, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "token_name, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "token_name, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- }
- // 按令牌和时间分组
- tx = tx.Group(groupBy).Order("MIN(created_at) ASC")
- // 执行查询
- var results []struct {
- CreatedAt int64 `json:"created_at"`
- TokenName string `json:"token_name"`
- Count int `json:"count"`
- Quota int `json:"quota"`
- }
- err := tx.Scan(&results).Error
- if err != nil {
- return nil, err
- }
- // 格式化时间并构建返回结果
- for _, result := range results {
- timeStr := formatTime(result.CreatedAt, defaultTime)
- statistics = append(statistics, TokenStatistics{
- Time: timeStr,
- TokenName: result.TokenName,
- Quota: result.Quota,
- Count: result.Count,
- })
- }
- return statistics, nil
- }
- // GetUserStatistics 获取按用户统计的数据
- func GetUserStatistics(startTimestamp, endTimestamp int, username, tokenName, modelName string, channel int, group, defaultTime string) ([]UserStatistics, error) {
- var statistics []UserStatistics
- // 构建查询条件
- tx := LOG_DB.Table("logs").Select(`
- created_at,
- username,
- COUNT(*) as count,
- SUM(quota) as quota
- `).Where("type = ?", 2) // LogTypeConsume = 2
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if modelName != "" {
- tx = tx.Where("model_name LIKE ?", "%"+modelName+"%")
- }
- if channel != 0 {
- tx = tx.Where("channel_id = ?", channel)
- }
- if group != "" {
- tx = tx.Where("`group` = ?", group)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- // 按时间粒度分组 - 使用数据库无关的函数
- var groupBy string
- switch defaultTime {
- case "hour":
- if common.UsingMySQL {
- groupBy = "username, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d %H:00:00')"
- } else if common.UsingPostgreSQL {
- groupBy = "username, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD HH24:00:00')"
- } else {
- // SQLite
- groupBy = "username, strftime('%Y-%m-%d %H:00:00', datetime(created_at, 'unixepoch'))"
- }
- case "day":
- if common.UsingMySQL {
- groupBy = "username, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "username, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "username, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- case "week":
- if common.UsingMySQL {
- groupBy = "username, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%U')"
- } else if common.UsingPostgreSQL {
- groupBy = "username, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-IW')"
- } else {
- // SQLite
- groupBy = "username, strftime('%Y-%W', datetime(created_at, 'unixepoch'))"
- }
- default:
- if common.UsingMySQL {
- groupBy = "username, DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d')"
- } else if common.UsingPostgreSQL {
- groupBy = "username, TO_CHAR(TO_TIMESTAMP(created_at), 'YYYY-MM-DD')"
- } else {
- // SQLite
- groupBy = "username, strftime('%Y-%m-%d', datetime(created_at, 'unixepoch'))"
- }
- }
- // 按用户和时间分组
- tx = tx.Group(groupBy).Order("MIN(created_at) ASC")
- // 执行查询
- var results []struct {
- CreatedAt int64 `json:"created_at"`
- Username string `json:"username"`
- Count int `json:"count"`
- Quota int `json:"quota"`
- }
- err := tx.Scan(&results).Error
- if err != nil {
- return nil, err
- }
- // 格式化时间并构建返回结果
- for _, result := range results {
- timeStr := formatTime(result.CreatedAt, defaultTime)
- statistics = append(statistics, UserStatistics{
- Time: timeStr,
- Username: result.Username,
- Quota: result.Quota,
- Count: result.Count,
- })
- }
- return statistics, nil
- }
- // formatTime 根据时间粒度格式化时间
- func formatTime(timestamp int64, defaultTime string) string {
- t := time.Unix(timestamp, 0)
- switch defaultTime {
- case "hour":
- return t.Format("2006-01-02 15:00")
- case "day":
- return t.Format("2006-01-02")
- case "week":
- _, week := t.ISOWeek()
- return t.Format("2006-01") + "-W" + strconv.Itoa(week)
- default:
- return t.Format("2006-01-02")
- }
- }
|