112 lines
2.2 KiB
Go
112 lines
2.2 KiB
Go
package logger
|
||
|
||
import (
|
||
"fmt"
|
||
"path/filepath"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
type RotatingLogger struct {
|
||
dataLogger *DataLogger
|
||
currentHour int
|
||
baseDir string
|
||
mu sync.Mutex
|
||
eventLogger *EventLogger
|
||
checkInterval time.Duration
|
||
}
|
||
|
||
func NewRotatingLogger(eventLogger *EventLogger, checkInterval time.Duration) (*RotatingLogger, error) {
|
||
// Получаем директорию для бинарных данных
|
||
dataDir, err := GetDataLogsDir()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Интервал проверки по умолчанию
|
||
if checkInterval == 0 {
|
||
checkInterval = 1 * time.Minute
|
||
}
|
||
|
||
r := &RotatingLogger{
|
||
baseDir: dataDir,
|
||
eventLogger: eventLogger,
|
||
checkInterval: checkInterval,
|
||
}
|
||
|
||
if err := r.rotate(); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
go r.rotationLoop()
|
||
return r, nil
|
||
}
|
||
|
||
func (r *RotatingLogger) getFilename() string {
|
||
now := time.Now()
|
||
return filepath.Join(r.baseDir, fmt.Sprintf("gpio-%04d-%02d-%02d-%02d.bin",
|
||
now.Year(), now.Month(), now.Day(), now.Hour()))
|
||
}
|
||
|
||
func (r *RotatingLogger) rotate() error {
|
||
r.mu.Lock()
|
||
defer r.mu.Unlock()
|
||
|
||
now := time.Now()
|
||
newHour := now.Hour()
|
||
|
||
// Если уже правильный час и логгер существует - ок
|
||
if r.dataLogger != nil && r.currentHour == newHour {
|
||
return nil
|
||
}
|
||
|
||
// Закрываем старый
|
||
if r.dataLogger != nil {
|
||
r.dataLogger.Close()
|
||
}
|
||
|
||
// Открываем новый
|
||
filename := r.getFilename()
|
||
dataLogger, err := NewDataLogger(filename)
|
||
if err != nil {
|
||
if r.eventLogger != nil {
|
||
r.eventLogger.Event("ПЛАНОВАЯ_РОТАЦИЯ_НЕУДАЧНА")
|
||
}
|
||
return err
|
||
}
|
||
|
||
r.dataLogger = dataLogger
|
||
r.currentHour = newHour
|
||
if r.eventLogger != nil {
|
||
r.eventLogger.Event("ПЛАНОВАЯ_РОТАЦИЯ")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (r *RotatingLogger) Write(s Sample) {
|
||
r.mu.Lock()
|
||
logger := r.dataLogger
|
||
r.mu.Unlock()
|
||
|
||
if logger != nil {
|
||
logger.Write(s)
|
||
}
|
||
}
|
||
|
||
func (r *RotatingLogger) rotationLoop() {
|
||
ticker := time.NewTicker(r.checkInterval)
|
||
defer ticker.Stop()
|
||
|
||
for range ticker.C {
|
||
r.rotate()
|
||
}
|
||
}
|
||
|
||
func (r *RotatingLogger) Close() error {
|
||
r.mu.Lock()
|
||
defer r.mu.Unlock()
|
||
if r.dataLogger != nil {
|
||
return r.dataLogger.Close()
|
||
}
|
||
return nil
|
||
} |