Files
backend/internal/service/log_cleanup_service.go

206 lines
5.7 KiB
Go
Raw Normal View History

package service
import (
"context"
"time"
"carrot_bbs/internal/repository"
"go.uber.org/zap"
)
// LogCleanupConfig 日志清理配置
type LogCleanupConfig struct {
Enabled bool
OperationLog int // 保留天数
LoginLog int
DataChangeLog int
CleanupTime string // 清理时间,如 "02:00"
}
// LogCleanupService 日志清理服务接口
type LogCleanupService interface {
Start()
Stop()
CleanupOldLogs(ctx context.Context) error
CleanupOperationLogs(ctx context.Context, beforeDate string) error
CleanupLoginLogs(ctx context.Context, beforeDate string) error
CleanupDataChangeLogs(ctx context.Context, beforeDate string) error
}
// logCleanupServiceImpl 日志清理服务实现
type logCleanupServiceImpl struct {
operationRepo repository.OperationLogRepository
loginRepo repository.LoginLogRepository
dataChangeRepo repository.DataChangeLogRepository
cfg *LogCleanupConfig
logger *zap.Logger
ctx context.Context
cancel context.CancelFunc
}
// NewLogCleanupService 创建日志清理服务
func NewLogCleanupService(
operationRepo repository.OperationLogRepository,
loginRepo repository.LoginLogRepository,
dataChangeRepo repository.DataChangeLogRepository,
cfg *LogCleanupConfig,
logger *zap.Logger,
) LogCleanupService {
return &logCleanupServiceImpl{
operationRepo: operationRepo,
loginRepo: loginRepo,
dataChangeRepo: dataChangeRepo,
cfg: cfg,
logger: logger,
}
}
// Start 启动日志清理服务
func (s *logCleanupServiceImpl) Start() {
if !s.cfg.Enabled {
s.logger.Info("log cleanup service disabled")
return
}
s.ctx, s.cancel = context.WithCancel(context.Background())
go s.scheduleCleanup()
s.logger.Info("log cleanup service started",
zap.Int("operation_log_days", s.cfg.OperationLog),
zap.Int("login_log_days", s.cfg.LoginLog),
zap.Int("data_change_log_days", s.cfg.DataChangeLog),
)
}
// Stop 停止日志清理服务
func (s *logCleanupServiceImpl) Stop() {
if s.cancel != nil {
s.cancel()
s.logger.Info("log cleanup service stopped")
}
}
// scheduleCleanup 定时调度清理任务
func (s *logCleanupServiceImpl) scheduleCleanup() {
for {
select {
case <-s.ctx.Done():
return
default:
now := time.Now()
nextCleanup := s.getNextCleanupTime(now)
duration := nextCleanup.Sub(now)
s.logger.Info("next log cleanup scheduled",
zap.Time("time", nextCleanup),
zap.Duration("in", duration),
)
timer := time.NewTimer(duration)
select {
case <-s.ctx.Done():
timer.Stop()
return
case <-timer.C:
if err := s.CleanupOldLogs(s.ctx); err != nil {
s.logger.Error("failed to cleanup old logs", zap.Error(err))
}
}
}
}
}
// getNextCleanupTime 计算下次清理时间
func (s *logCleanupServiceImpl) getNextCleanupTime(now time.Time) time.Time {
cleanupTime, err := time.Parse("15:04", s.cfg.CleanupTime)
if err != nil {
cleanupTime = time.Date(now.Year(), now.Month(), now.Day(), 2, 0, 0, 0, now.Location())
}
nextCleanup := time.Date(now.Year(), now.Month(), now.Day(), cleanupTime.Hour(), cleanupTime.Minute(), 0, 0, now.Location())
if nextCleanup.Before(now) {
nextCleanup = nextCleanup.Add(24 * time.Hour)
}
return nextCleanup
}
// CleanupOldLogs 清理旧日志
func (s *logCleanupServiceImpl) CleanupOldLogs(ctx context.Context) error {
s.logger.Info("starting log cleanup")
// 清理操作日志
if err := s.CleanupOperationLogs(ctx, s.getBeforeDate(s.cfg.OperationLog)); err != nil {
s.logger.Error("failed to cleanup operation logs", zap.Error(err))
}
// 清理登录日志
if err := s.CleanupLoginLogs(ctx, s.getBeforeDate(s.cfg.LoginLog)); err != nil {
s.logger.Error("failed to cleanup login logs", zap.Error(err))
}
// 清理数据变更日志
if err := s.CleanupDataChangeLogs(ctx, s.getBeforeDate(s.cfg.DataChangeLog)); err != nil {
s.logger.Error("failed to cleanup data change logs", zap.Error(err))
}
s.logger.Info("log cleanup completed")
return nil
}
// CleanupOperationLogs 清理操作日志
func (s *logCleanupServiceImpl) CleanupOperationLogs(ctx context.Context, beforeDate string) error {
result := s.operationRepo.DeleteOldLogs(ctx, beforeDate)
s.logger.Info("cleanup operation logs", zap.String("before_date", beforeDate))
return result
}
// CleanupLoginLogs 清理登录日志
func (s *logCleanupServiceImpl) CleanupLoginLogs(ctx context.Context, beforeDate string) error {
result := s.loginRepo.DeleteOldLogs(ctx, beforeDate)
s.logger.Info("cleanup login logs", zap.String("before_date", beforeDate))
return result
}
// CleanupDataChangeLogs 清理数据变更日志
func (s *logCleanupServiceImpl) CleanupDataChangeLogs(ctx context.Context, beforeDate string) error {
result := s.dataChangeRepo.DeleteOldLogs(ctx, beforeDate)
s.logger.Info("cleanup data change logs", zap.String("before_date", beforeDate))
return result
}
// getBeforeDate 计算截止日期
func (s *logCleanupServiceImpl) getBeforeDate(days int) string {
return time.Now().AddDate(0, 0, -days).Format("2006-01-02")
}
// LogService 日志服务组合
type LogService struct {
OperationLog OperationLogService
LoginLog LoginLogService
DataChangeLog DataChangeLogService
}
// NewLogService 创建日志服务组合
func NewLogService(
operationLogService OperationLogService,
loginLogService LoginLogService,
dataChangeLogService DataChangeLogService,
) *LogService {
return &LogService{
OperationLog: operationLogService,
LoginLog: loginLogService,
DataChangeLog: dataChangeLogService,
}
}
// GetLogCleanupServiceFromApp 从应用中获取日志清理服务
func GetLogCleanupServiceFromApp(app any) LogCleanupService {
// 这里需要根据实际的app结构来获取
// 暂时返回nil实际使用时需要实现
return nil
}