feat: 添加日志管理和敏感词过滤功能
- 新增日志管理模块:操作日志、登录日志、数据变更日志 - 新增敏感词过滤器 (sanitizer) - 新增日志异步写入管理器 - 新增日志定时清理服务 - 优化帖子相关服务和上传服务
This commit is contained in:
205
internal/service/log_cleanup_service.go
Normal file
205
internal/service/log_cleanup_service.go
Normal file
@@ -0,0 +1,205 @@
|
||||
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 interface{}) LogCleanupService {
|
||||
// 这里需要根据实际的app结构来获取
|
||||
// 暂时返回nil,实际使用时需要实现
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user