package service import ( "context" "fmt" "gemini-balancer/internal/models" "strconv" "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 KeyID *uint64 GroupID *uint64 } 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 params.KeyID != nil { query = query.Where("key_id = ?", *params.KeyID) } if params.GroupID != nil { query = query.Where("group_id = ?", *params.GroupID) } 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 keyIDStr, ok := queryParams["key_id"]; ok { if keyID, err := strconv.ParseUint(keyIDStr, 10, 64); err == nil { params.KeyID = &keyID } else { return params, fmt.Errorf("invalid key_id parameter: %s", keyIDStr) } } if groupIDStr, ok := queryParams["group_id"]; ok { if groupID, err := strconv.ParseUint(groupIDStr, 10, 64); err == nil { params.GroupID = &groupID } else { return params, fmt.Errorf("invalid group_id parameter: %s", groupIDStr) } } return params, nil }