mirror of
https://github.com/linux-do/new-api.git
synced 2025-09-18 00:16:37 +08:00
203 lines
6.5 KiB
Go
203 lines
6.5 KiB
Go
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"`
|
||
ChannelId int `json:"channel" gorm:"index"`
|
||
TokenId int `json:"token_id" gorm:"default:0;index"`
|
||
}
|
||
|
||
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.Split(key, "-")[1]).Find(&logs).Error
|
||
return logs, err
|
||
}
|
||
|
||
func RecordLog(userId int, logType int, content string) {
|
||
if logType == LogTypeConsume && !common.LogConsumeEnabled {
|
||
return
|
||
}
|
||
log := &Log{
|
||
UserId: userId,
|
||
Username: GetUsernameById(userId),
|
||
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) {
|
||
common.LogInfo(ctx, fmt.Sprintf("record consume log: userId=%d, 用户调用å‰<C3A5>ä½™é¢<C3A9>=%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 := GetUsernameById(userId)
|
||
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,
|
||
}
|
||
err := DB.Create(log).Error
|
||
if err != nil {
|
||
common.LogError(ctx, "failed to record log: "+err.Error())
|
||
}
|
||
if common.DataExportEnabled {
|
||
go LogQuotaData(userId, username, modelName, quota, common.GetTimestamp())
|
||
}
|
||
}
|
||
|
||
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
|
||
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
|
||
}
|