// logger.go - система логирования для fush shell // Записывает события четырех уровней: DEBUG, INFO, WARN, ERROR // Использует атомарные операции для потокобезопасности // Обеспечивает принудительную запись на диск после каждого сообщения package logger import ( "fmt" "os" "sync/atomic" "time" ) // LogLevel определяет уровень логирования type LogLevel int const ( LevelDebug LogLevel = iota LevelInfo LevelWarn LevelError ) // Logger представляет структуру логгера type Logger struct { file *os.File level LogLevel closed atomic.Bool } // New создает новый логгер func New(logPath string) (*Logger, error) { // Открываем файл для добавления записей file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, err } return &Logger{ file: file, level: LevelInfo, }, nil } // Close закрывает логгер func (l *Logger) Close() error { if l.closed.Load() { return nil } l.closed.Store(true) return l.file.Close() } // log записывает сообщение в лог func (l *Logger) log(level LogLevel, format string, args ...interface{}) { if l.closed.Load() { return } if level < l.level { return } levelStr := map[LogLevel]string{ LevelDebug: "DEBUG", LevelInfo: "INFO", LevelWarn: "WARN", LevelError: "ERROR", }[level] timestamp := time.Now().Format("2006-01-02 15:04:05.000") message := fmt.Sprintf(format, args...) logLine := fmt.Sprintf("[%s] [%s] %s\n", timestamp, levelStr, message) // Атомарная запись в файл _, err := l.file.WriteString(logLine) if err != nil { fmt.Fprintf(os.Stderr, "Ошибка записи лога: %v\n", err) } // Принудительная запись на диск l.file.Sync() } // Debug записывает отладочное сообщение func (l *Logger) Debug(format string, args ...interface{}) { l.log(LevelDebug, format, args...) } // Info записывает информационное сообщение func (l *Logger) Info(format string, args ...interface{}) { l.log(LevelInfo, format, args...) } // Warn записывает предупреждение func (l *Logger) Warn(format string, args ...interface{}) { l.log(LevelWarn, format, args...) } // Error записывает ошибку func (l *Logger) Error(format string, args ...interface{}) { l.log(LevelError, format, args...) } // SetLevel устанавливает уровень логирования func (l *Logger) SetLevel(level LogLevel) { l.level = level }