| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // 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"
- )
- // СлогФайл -- бэкенд для вывода в файл
- type СлогФайл struct {
- kern types.ИЯдро
- file *os.File
- fileName string
- isWork *safe_bool.БезопБул
- chMsg chan []byte // канал входящих сообщений
- block sync.Mutex
- }
- // НовСлогФайл -- возвращает новый бэкенд логгера для вывода в файл
- func НовСлогФайл(kern types.ИЯдро, build string) (*СлогФайл, error) {
- { // Предусловия
- if kern == nil {
- return nil, fmt.Errorf("НовСлогФайл(): ИЯдро is nil")
- }
- if build == "" {
- return nil, fmt.Errorf("НовСлогФайл(): strBuild is empty")
- }
- }
- сам := &СлогФайл{
- 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("НовСлогФайл(): in open log-file, err=%w", err)
- }
- ош := сам.kern.Wg().Add(threadName)
- if ош != nil {
- return nil, fmt.Errorf("НовСлогФайл(): in Add %q, err=%w", threadName, ош)
- }
- go сам.run()
- return сам, nil
- }
- // Открывает файл на запись
- func (сам *СлогФайл) open() error {
- file, err := os.OpenFile(сам.fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
- if err != nil {
- сам.kern.Отменить()
- return fmt.Errorf("СлогФайл.open(): in open %q, err=%w", сам.fileName, err)
- }
- сам.file = file
- return nil
- }
- // Запускает работу в отдельном потоке
- func (сам *СлогФайл) run() {
- defer func() {
- сам.isWork.Сброс()
- сам.block.Lock()
- defer сам.block.Unlock()
- _ = сам.file.Close()
- close(сам.chMsg)
- ош := сам.kern.Wg().Done(threadName)
- if ош != nil {
- log.Printf("СлогФайл.run(): при удалении группы ожидания, ош=\n\t%v", ош)
- }
- // log._rintf("SlogFile.run(): end work\n")
- сам.kern.Отменить()
- }()
- for {
- select {
- case <-сам.kern.Done(): // Ожидание отмены контекста приложения
- return
- case msg := <-сам.chMsg:
- if err := сам.write(msg); err != nil {
- сам.kern.Слог().Ошибка("СлогФайл.run(): in write msg, err=\n\t%v", err)
- return
- }
- }
- }
- }
- // Внцтренни вызов записи
- func (сам *СлогФайл) write(msg []byte) error {
- _, err := сам.file.Write(msg)
- if err != nil {
- return fmt.Errorf("СлогФайл.run(): in write file %q, err=\n\t%w", сам.fileName, err)
- }
- return nil
- }
- // Write -- записывает данные в файл
- func (сам *СлогФайл) Write(msg string) {
- if !сам.isWork.Получ() {
- return
- }
- сам.block.Lock()
- defer сам.block.Unlock()
- сам.chMsg <- []byte(msg)
- }
|