package slog import ( "fmt" "os" "strings" "sync" "time" "wartank/pkg/components/kernel/slog/slog_file" "wartank/pkg/components/kernel/slog/slog_term" "wartank/pkg/components/safebool" "wartank/pkg/cons" "wartank/pkg/types" ) /* Попытка сделать логирование в файл и консоль */ const ( strSlog = "ISlog" LevelDebug = iota LevelInfo LevelWarn LevelError ) // Slog -- лог событий для записи type Slog struct { kern types.IKernel buf strings.Builder block sync.RWMutex lf *slog_file.SlogFile lt *slog_term.SlogTerm isWork *safebool.SafeBool level int // Уровень логирования } // NewSlog -- возвращает объект логирования func NewSlog(kern types.IKernel) (*Slog, error) { if kern == nil { return nil, fmt.Errorf("NewSlog(): IKernel is nil") } os.Setenv("BUILD", "test_BUILD") build := os.Getenv("BUILD") if build == "" { return nil, fmt.Errorf("NewSlog(): strBuild is empty") } sf := &Slog{ kern: kern, buf: strings.Builder{}, lt: slog_term.NewSlogTerm(), isWork: safebool.NewSafeBool(), } lf, err := slog_file.NewSlogFile(kern, build) if err != nil { return nil, fmt.Errorf("NewSlog(): in create SlogFile, err=\n\t%w", err) } sf.lf = lf go sf.close() sf.isWork.Set() sf.kern.Wg().Add(strSlog) sf.Infof("NewSlog()\n") return sf, nil } // Debugf -- выводит в лог отладочную инфу func (sf *Slog) Debugf(str string, lstVal ...interface{}) { sf.block.Lock() defer sf.block.Unlock() if !sf.isWork.Get() { return } sf.printf("DEBUG", str, lstVal...) } // Infof -- выводит в лог дежурную инфу func (sf *Slog) Infof(str string, lstVal ...interface{}) { sf.block.Lock() defer sf.block.Unlock() if !sf.isWork.Get() { return } sf.printf("INFO", str, lstVal...) } // Warnf -- выводит в лог предупредительную инфу func (sf *Slog) Warnf(str string, lstVal ...interface{}) { sf.block.Lock() defer sf.block.Unlock() if !sf.isWork.Get() { return } sf.printf("WARN", str, lstVal...) } // Errorf -- выводит в лог инфу об ошибках func (sf *Slog) Errorf(str string, lstVal ...interface{}) { sf.block.Lock() defer sf.block.Unlock() if !sf.isWork.Get() { return } sf.printf("ERROR", str, lstVal...) } // Внутренний вызов без блокировки func (sf *Slog) printf(pref, str string, lstVal ...interface{}) { style := "" switch pref { case "DEBUG": // Режим отладки style = "\033[2;37;40m" // case "PRINT": // Режим печати // style = "\033[0;34;40m" case "INFO": // Режим информирования style = "\033[0;37;40m" case "WARN": // Режим предупреждения style = "\033[1;31;40m" case "ERROR": // Режим ошибки style = "\033[1;37;41m" } strTime := time.Now().Local().Format("2006-01-02 15:04:05.000\t") sf.buf.WriteString(strTime + "\t") sf.buf.WriteString(pref + "\t") sf.buf.WriteString(cons.SelfName + "\n\t") sf.buf.WriteString(fmt.Sprintf(str, lstVal...)) sf.lf.Write(sf.buf.String()) sf.lt.Write(style + sf.buf.String() + "\033[00m") sf.buf.Reset() } // Ожидает закрытия приложения func (sf *Slog) close() { <-sf.kern.Done() sf.block.Lock() if !sf.isWork.Get() { return } sf.isWork.Reset() sf.kern.Wg().Done(strSlog) sf.block.Unlock() }