// package slog_file -- бекенд для вывода в файл package slog_file import ( "fmt" // "log" "os" "sync" "time" "wartank/pkg/components/safe_bool" "wartank/pkg/cons" "wartank/pkg/types" ) const ( threadName = "slog_file" ) // SlogFile -- бэкенд для вывода в файл type SlogFile struct { kern types.IKernel file *os.File fileName string isWork *safe_bool.БезопБул chMsg chan []byte // канал входящих сообщений block sync.Mutex } // NewSlogFile -- возвращает новый бэкенд логгера для вывода в файл func NewSlogFile(kern types.IKernel, build string) (*SlogFile, error) { { // Предусловия if kern == nil { return nil, fmt.Errorf("NewSlogFile(): IKernel is nil") } if build == "" { return nil, fmt.Errorf("NewSlogFile(): strBuild is empty") } } сам := &SlogFile{ kern: kern, fileName: cons.СамИмя + "_" + build + time.Now().UTC().Format("_2006-01-02 15:04:05.000") + ".log", isWork: safe_bool.НовБезопБул(), chMsg: make(chan []byte, 10), } сам.isWork.Уст() _ = os.MkdirAll("./log", 0700) сам.fileName = "./log/" + сам.fileName if err := сам.open(); err != nil { return nil, fmt.Errorf("NewSlogFile(): in open log-file, err=%w", err) } сам.kern.Wg().Add(threadName) go сам.run() return сам, nil } // Открывает файл на запись func (сам *SlogFile) open() error { file, err := os.OpenFile(сам.fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { сам.kern.CancelApp() return fmt.Errorf("NewSlogFile.open(): in open %q, err=%w", сам.fileName, err) } сам.file = file return nil } // Запускает работу в отдельном потоке func (сам *SlogFile) run() { defer func() { сам.isWork.Сброс() сам.block.Lock() defer сам.block.Unlock() _ = сам.file.Close() close(сам.chMsg) сам.kern.Wg().Done(threadName) // log._rintf("SlogFile.run(): end work\n") сам.kern.CancelApp() }() for { select { case <-сам.kern.Done(): // Ожидание отмены контекста приложения return case msg := <-сам.chMsg: if err := сам.write(msg); err != nil { сам.kern.Slog().Errorf("SlogFile.run(): in write msg, err=\n\t%v", err) return } } } } // Внцтренни вызов записи func (сам *SlogFile) write(msg []byte) error { _, err := сам.file.Write(msg) if err != nil { return fmt.Errorf("SlogFile.run(): in write file %q, err=\n\t%w", сам.fileName, err) } return nil } // Write -- записывает данные в файл func (сам *SlogFile) Write(msg string) { if !сам.isWork.Получ() { return } сам.block.Lock() defer сам.block.Unlock() сам.chMsg <- []byte(msg) }