package utils import ( "fmt" "log" "os" "sync" "time" ) type DailyFileWriter struct { currentFile *os.File mu sync.Mutex logDir string frequency string currentDate string currentSlot int logger *log.Logger nodeID string } func NewDailyFileWriter(logDir, frequency string, logger *log.Logger, nodeID string) *DailyFileWriter { return &DailyFileWriter{ logDir: logDir, frequency: frequency, logger: logger, nodeID: nodeID, } } func (w *DailyFileWriter) Write(p []byte) (n int, err error) { w.mu.Lock() defer w.mu.Unlock() now := time.Now() if w.needRotate(now) { if err := w.rotateFile(now); err != nil { w.logger.Printf("❌❌ 日志文件切换失败: %v", err) return 0, err } } if w.currentFile == nil { if err := w.rotateFile(now); err != nil { return 0, err } } return w.currentFile.Write(p) } func (w *DailyFileWriter) needRotate(now time.Time) bool { currentDate := now.Format("2006-01-02") if w.frequency == "daily" { return w.currentDate != currentDate } else if w.frequency == "10min" { currentSlot := (now.Hour()*60 + now.Minute()) / 10 return w.currentDate != currentDate || w.currentSlot != currentSlot } return false } func (w *DailyFileWriter) rotateFile(now time.Time) error { if w.currentFile != nil { w.currentFile.Close() } dateStr := now.Format("2006-01-02") var slotStr string if w.frequency == "10min" { slot := (now.Hour()*60 + now.Minute()) / 10 slotStr = fmt.Sprintf("%03d", slot) } else { slotStr = "000" } if err := os.MkdirAll(w.logDir, 0755); err != nil { return fmt.Errorf("创建日志目录失败: %w", err) } filename := fmt.Sprintf("%s/xk-websocket-%s-%s.log", w.logDir, dateStr, slotStr) file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { return fmt.Errorf("打开日志文件失败: %w", err) } w.currentFile = file w.currentDate = dateStr if w.frequency == "10min" { w.currentSlot = (now.Hour()*60 + now.Minute()) / 10 } return nil }