| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- package model
- import (
- "context"
- "fmt"
- "gorm.io/gorm"
- "one-api/common"
- "strings"
- )
- type Log struct {
- Id int `json:"id" gorm:"index:idx_created_at_id,priority:1"`
- UserId int `json:"user_id" gorm:"index"`
- CreatedAt int64 `json:"created_at" gorm:"bigint;index:idx_created_at_id,priority:2;index:idx_created_at_type"`
- Type int `json:"type" gorm:"index:idx_created_at_type"`
- Content string `json:"content"`
- Username string `json:"username" gorm:"index:index_username_model_name,priority:2;default:''"`
- TokenName string `json:"token_name" gorm:"index;default:''"`
- ModelName string `json:"model_name" gorm:"index;index:index_username_model_name,priority:1;default:''"`
- Quota int `json:"quota" gorm:"default:0"`
- PromptTokens int `json:"prompt_tokens" gorm:"default:0"`
- CompletionTokens int `json:"completion_tokens" gorm:"default:0"`
- UseTime int `json:"use_time" gorm:"default:0"`
- IsStream bool `json:"is_stream" gorm:"default:false"`
- ChannelId int `json:"channel" gorm:"index"`
- TokenId int `json:"token_id" gorm:"default:0;index"`
- Other string `json:"other"`
- }
- const (
- LogTypeUnknown = iota
- LogTypeTopup
- LogTypeConsume
- LogTypeManage
- LogTypeSystem
- )
- func GetLogByKey(key string) (logs []*Log, err error) {
- err = DB.Joins("left join tokens on tokens.id = logs.token_id").Where("tokens.key = ?", strings.TrimPrefix(key, "sk-")).Find(&logs).Error
- return logs, err
- }
- func RecordLog(userId int, logType int, content string) {
- if logType == LogTypeConsume && !common.LogConsumeEnabled {
- return
- }
- username, _ := CacheGetUsername(userId)
- log := &Log{
- UserId: userId,
- Username: username,
- CreatedAt: common.GetTimestamp(),
- Type: logType,
- Content: content,
- }
- err := DB.Create(log).Error
- if err != nil {
- common.SysError("failed to record log: " + err.Error())
- }
- }
- func RecordConsumeLog(ctx context.Context, userId int, channelId int, promptTokens int, completionTokens int, modelName string, tokenName string, quota int, content string, tokenId int, userQuota int, useTimeSeconds int, isStream bool, other map[string]interface{}) {
- common.LogInfo(ctx, fmt.Sprintf("record consume log: userId=%d, 用户调用前余额=%d, channelId=%d, promptTokens=%d, completionTokens=%d, modelName=%s, tokenName=%s, quota=%d, content=%s", userId, userQuota, channelId, promptTokens, completionTokens, modelName, tokenName, quota, content))
- if !common.LogConsumeEnabled {
- return
- }
- username, _ := CacheGetUsername(userId)
- otherStr := common.MapToJsonStr(other)
- log := &Log{
- UserId: userId,
- Username: username,
- CreatedAt: common.GetTimestamp(),
- Type: LogTypeConsume,
- Content: content,
- PromptTokens: promptTokens,
- CompletionTokens: completionTokens,
- TokenName: tokenName,
- ModelName: modelName,
- Quota: quota,
- ChannelId: channelId,
- TokenId: tokenId,
- UseTime: useTimeSeconds,
- IsStream: isStream,
- Other: otherStr,
- }
- err := DB.Create(log).Error
- if err != nil {
- common.LogError(ctx, "failed to record log: "+err.Error())
- }
- if common.DataExportEnabled {
- common.SafeGoroutine(func() {
- LogQuotaData(userId, username, modelName, quota, common.GetTimestamp(), promptTokens+completionTokens)
- })
- }
- }
- func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string, startIdx int, num int, channel int) (logs []*Log, err error) {
- var tx *gorm.DB
- if logType == LogTypeUnknown {
- tx = DB
- } else {
- tx = DB.Where("type = ?", logType)
- }
- if modelName != "" {
- tx = tx.Where("model_name = ?", modelName)
- }
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- if channel != 0 {
- tx = tx.Where("channel_id = ?", channel)
- }
- err = tx.Order("id desc").Limit(num).Offset(startIdx).Find(&logs).Error
- return logs, err
- }
- func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int64, modelName string, tokenName string, startIdx int, num int) (logs []*Log, err error) {
- var tx *gorm.DB
- if logType == LogTypeUnknown {
- tx = DB.Where("user_id = ?", userId)
- } else {
- tx = DB.Where("user_id = ? and type = ?", userId, logType)
- }
- if modelName != "" {
- tx = tx.Where("model_name = ?", modelName)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- err = tx.Order("id desc").Limit(num).Offset(startIdx).Omit("id").Find(&logs).Error
- for i := range logs {
- var otherMap map[string]interface{}
- otherMap = common.StrToMap(logs[i].Other)
- if otherMap != nil {
- // delete admin
- delete(otherMap, "admin_info")
- }
- logs[i].Other = common.MapToJsonStr(otherMap)
- }
- return logs, err
- }
- func SearchAllLogs(keyword string) (logs []*Log, err error) {
- err = DB.Where("type = ? or content LIKE ?", keyword, keyword+"%").Order("id desc").Limit(common.MaxRecentItems).Find(&logs).Error
- return logs, err
- }
- func SearchUserLogs(userId int, keyword string) (logs []*Log, err error) {
- err = DB.Where("user_id = ? and type = ?", userId, keyword).Order("id desc").Limit(common.MaxRecentItems).Omit("id").Find(&logs).Error
- return logs, err
- }
- type Stat struct {
- Quota int `json:"quota"`
- Rpm int `json:"rpm"`
- Tpm int `json:"tpm"`
- }
- func SumUsedQuota(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string, channel int) (stat Stat) {
- tx := DB.Table("logs").Select("sum(quota) quota, count(*) rpm, sum(prompt_tokens) + sum(completion_tokens) tpm")
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- if modelName != "" {
- tx = tx.Where("model_name = ?", modelName)
- }
- if channel != 0 {
- tx = tx.Where("channel_id = ?", channel)
- }
- tx.Where("type = ?", LogTypeConsume).Scan(&stat)
- return stat
- }
- func SumUsedToken(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string) (token int) {
- tx := DB.Table("logs").Select("ifnull(sum(prompt_tokens),0) + ifnull(sum(completion_tokens),0)")
- if username != "" {
- tx = tx.Where("username = ?", username)
- }
- if tokenName != "" {
- tx = tx.Where("token_name = ?", tokenName)
- }
- if startTimestamp != 0 {
- tx = tx.Where("created_at >= ?", startTimestamp)
- }
- if endTimestamp != 0 {
- tx = tx.Where("created_at <= ?", endTimestamp)
- }
- if modelName != "" {
- tx = tx.Where("model_name = ?", modelName)
- }
- tx.Where("type = ?", LogTypeConsume).Scan(&token)
- return token
- }
- func DeleteOldLog(targetTimestamp int64) (int64, error) {
- result := DB.Where("created_at < ?", targetTimestamp).Delete(&Log{})
- return result.RowsAffected, result.Error
- }
|