Files
gemini-banlancer/internal/service/log_service.go
2025-11-24 20:47:12 +08:00

165 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"context"
"fmt"
"gemini-balancer/internal/models"
"strconv"
"strings"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
type LogService struct {
db *gorm.DB
logger *logrus.Entry
}
func NewLogService(db *gorm.DB, logger *logrus.Logger) *LogService {
return &LogService{
db: db,
logger: logger.WithField("component", "LogService"),
}
}
func (s *LogService) Record(ctx context.Context, log *models.RequestLog) error {
return s.db.WithContext(ctx).Create(log).Error
}
// LogQueryParams 解耦 Gin使用结构体传参
type LogQueryParams struct {
Page int
PageSize int
ModelName string
IsSuccess *bool // 使用指针区分"未设置"和"false"
StatusCode *int
KeyIDs []string
GroupIDs []string
Q string
ErrorCodes []string
StatusCodes []string
}
func (s *LogService) GetLogs(ctx context.Context, params LogQueryParams) ([]models.RequestLog, int64, error) {
// 参数校验
if params.Page < 1 {
params.Page = 1
}
if params.PageSize < 1 || params.PageSize > 100 {
params.PageSize = 20
}
var logs []models.RequestLog
var total int64
// 构建基础查询
query := s.db.WithContext(ctx).Model(&models.RequestLog{})
query = s.applyFilters(query, params)
if err := query.Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("failed to count logs: %w", err)
}
if total == 0 {
return []models.RequestLog{}, 0, nil
}
offset := (params.Page - 1) * params.PageSize
if err := query.Order("request_time DESC").
Limit(params.PageSize).
Offset(offset).
Find(&logs).Error; err != nil {
return nil, 0, fmt.Errorf("failed to query logs: %w", err)
}
return logs, total, nil
}
func (s *LogService) applyFilters(query *gorm.DB, params LogQueryParams) *gorm.DB {
if params.ModelName != "" {
query = query.Where("model_name = ?", params.ModelName)
}
if params.IsSuccess != nil {
query = query.Where("is_success = ?", *params.IsSuccess)
}
if params.StatusCode != nil {
query = query.Where("status_code = ?", *params.StatusCode)
}
if len(params.KeyIDs) > 0 {
query = query.Where("key_id IN (?)", params.KeyIDs)
}
if len(params.GroupIDs) > 0 {
query = query.Where("group_id IN (?)", params.GroupIDs)
}
if len(params.ErrorCodes) > 0 {
query = query.Where("error_code IN (?)", params.ErrorCodes)
}
if len(params.StatusCodes) > 0 {
query = query.Where("status_code IN (?)", params.StatusCodes)
}
if params.Q != "" {
searchQuery := "%" + params.Q + "%"
query = query.Where(
"model_name LIKE ? OR error_code LIKE ? OR error_message LIKE ? OR CAST(status_code AS CHAR) LIKE ?",
searchQuery, searchQuery, searchQuery, searchQuery,
)
}
return query
}
// ParseLogQueryParams 在 Handler 层调用,解析 Gin 参数
func ParseLogQueryParams(queryParams map[string]string) (LogQueryParams, error) {
params := LogQueryParams{
Page: 1,
PageSize: 20,
}
if pageStr, ok := queryParams["page"]; ok {
if page, err := strconv.Atoi(pageStr); err == nil && page > 0 {
params.Page = page
}
}
if pageSizeStr, ok := queryParams["page_size"]; ok {
if pageSize, err := strconv.Atoi(pageSizeStr); err == nil && pageSize > 0 {
params.PageSize = pageSize
}
}
if modelName, ok := queryParams["model_name"]; ok {
params.ModelName = modelName
}
if isSuccessStr, ok := queryParams["is_success"]; ok {
if isSuccess, err := strconv.ParseBool(isSuccessStr); err == nil {
params.IsSuccess = &isSuccess
} else {
return params, fmt.Errorf("invalid is_success parameter: %s", isSuccessStr)
}
}
if statusCodeStr, ok := queryParams["status_code"]; ok {
if statusCode, err := strconv.Atoi(statusCodeStr); err == nil {
params.StatusCode = &statusCode
} else {
return params, fmt.Errorf("invalid status_code parameter: %s", statusCodeStr)
}
}
if keyIDsStr, ok := queryParams["key_ids"]; ok {
params.KeyIDs = strings.Split(keyIDsStr, ",")
}
if groupIDsStr, ok := queryParams["group_ids"]; ok {
params.GroupIDs = strings.Split(groupIDsStr, ",")
}
if errorCodesStr, ok := queryParams["error_codes"]; ok {
params.ErrorCodes = strings.Split(errorCodesStr, ",")
}
if statusCodesStr, ok := queryParams["status_codes"]; ok {
params.StatusCodes = strings.Split(statusCodesStr, ",")
}
if q, ok := queryParams["q"]; ok {
params.Q = q
}
return params, nil
}