2026-04-22 16:01:59 +08:00
|
|
|
|
package service
|
2026-03-15 02:25:10 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
2026-04-22 16:01:59 +08:00
|
|
|
|
"with_you/internal/repository"
|
2026-03-15 02:25:10 +08:00
|
|
|
|
|
|
|
|
|
|
"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 {
|
2026-03-26 18:14:16 +08:00
|
|
|
|
operationRepo repository.OperationLogRepository
|
|
|
|
|
|
loginRepo repository.LoginLogRepository
|
|
|
|
|
|
dataChangeRepo repository.DataChangeLogRepository
|
2026-03-15 02:25:10 +08:00
|
|
|
|
cfg *LogCleanupConfig
|
|
|
|
|
|
logger *zap.Logger
|
|
|
|
|
|
ctx context.Context
|
|
|
|
|
|
cancel context.CancelFunc
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewLogCleanupService 创建日志清理服务
|
|
|
|
|
|
func NewLogCleanupService(
|
2026-03-26 18:14:16 +08:00
|
|
|
|
operationRepo repository.OperationLogRepository,
|
|
|
|
|
|
loginRepo repository.LoginLogRepository,
|
|
|
|
|
|
dataChangeRepo repository.DataChangeLogRepository,
|
2026-03-15 02:25:10 +08:00
|
|
|
|
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 从应用中获取日志清理服务
|
2026-03-30 04:49:35 +08:00
|
|
|
|
func GetLogCleanupServiceFromApp(app any) LogCleanupService {
|
2026-03-15 02:25:10 +08:00
|
|
|
|
// 这里需要根据实际的app结构来获取
|
|
|
|
|
|
// 暂时返回nil,实际使用时需要实现
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|