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