// package log_buf -- потокобезопасный буфер лога. package log_buf import ( "log" "gitp78su.ipnodns.ru/svi/kern/v4/d0" "gitp78su.ipnodns.ru/svi/kern/v4/d0/defs/def_txt" "gitp78su.ipnodns.ru/svi/kern/v4/d0/defs/table/owner" "gitp78su.ipnodns.ru/svi/kern/v4/d0/helpers" "gitp78su.ipnodns.ru/svi/kern/v4/d1/log_buf/log_msg" ) // ILogBuf -- буферизованный лог для диагностики. // // Буфер для Error -- отдельный. type ILogBuf interface { // Debug -- сообщение отладки Debug(fMsg d0.Txt, args ...any) // LogBus -- возвращает объект публикации в шину // LogBus()ILogBus // Info -- информационные сообщения Info(fMsg d0.Txt, args ...any) // Warn -- предупреждающие сообщения Warn(fMsg d0.Txt, args ...any) // Err -- сообщения об ошибках Err(fMsg *d0.LErr, args ...any) // Get -- возвращает сообщение по номеру (0..99) Get(num d0.Num) log_msg.ILogMsg // GetErr -- возвращает сообщение ошибки по номеру (0..99) GetErr(num d0.Num) log_msg.ILogMsg // Size -- возвращает размер лога Size() d0.Num // IsTerm -- возвращает признак логирования в терминал IsTerm() *d0.MSafeBool } // LogBufParam -- параметры логирующего буфера. type LogBufParam struct { Owner_ *d0.LOwner // Владелец буфера Prefix_ *d0.LTxt // Префикс для сообщений IsTerm_ *d0.MSafeBool // Признак вывода в терминал } // SelfCheck -- проверяет корректность параметров. func (sf *LogBufParam) SelfCheck() { d0.If(sf.IsTerm_ == nil).Hassert("LogBufParam.SelfCheck(): IsTerm_==nil") d0.If(sf.Owner_ == nil).Hassert("LogBufParam.SelfCheck(): Owner_==nil") } // LogBuf -- потокобезопасный буфер лога. type LogBuf struct { *d0.MSafeMutex *LogBufParam owner *owner.LOwner lst []log_msg.ILogMsg lstErr []log_msg.ILogMsg level *d0.LTxt levDebug *d0.LTxt levInfo *d0.LTxt levWarn *d0.LTxt levError *d0.LTxt levEmpty *d0.LTxt } const ( DEBUG = d0.Num(-4) INFO = d0.Num(-3) WARN = d0.Num(-2) ERROR = d0.Num(-1) EMPTY = d0.Num(0) ) // NewLogBuf -- возвращает новый потокобезопасный буфер лога. func NewLogBuf(param *LogBufParam) *LogBuf { d0.If(param == nil).Hassert("NewLogBuf(): param==nil") param.SelfCheck() sf := &LogBuf{ owner: param.Owner_, MSafeMutex: d0.MutSafeMutex(), LogBufParam: param, lst: []log_msg.ILogMsg{}, lstErr: []log_msg.ILogMsg{}, level: d0.LetTxt(param.Owner_, "DEBU"), levDebug: d0.LetTxt(param.Owner_, "DEBU"), levInfo: d0.LetTxt(param.Owner_, "INFO"), levWarn: d0.LetTxt(param.Owner_, "WARN"), levError: d0.LetTxt(param.Owner_, "ERRO"), levEmpty: d0.LetTxt(param.Owner_, "EMPT"), } pref := sf.Prefix_.Get() + d0.Txt(".") sf.Prefix_ = d0.LetTxt(sf.owner, pref) return sf } // IsTerm -- возвращает признак логирования. func (sf *LogBuf) IsTerm() *d0.MSafeBool { return sf.IsTerm_ } // GetErr -- возвращает сообщение ошибки по номеру. func (sf *LogBuf) GetErr(num d0.Num) log_msg.ILogMsg { sf.RLock() defer sf.RUnlock() if len(sf.lstErr) == 0 { msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+"not error msg") return log_msg.NewLogMsg(sf.levDebug, msg) } if num >= d0.Num(len(sf.lstErr)) { return sf.lstErr[len(sf.lstErr)-1] } if num <= 0 { return sf.lstErr[0] } return sf.lstErr[num] } // Get -- возвращает сообщение по номеру. func (sf *LogBuf) Get(num d0.Num) log_msg.ILogMsg { sf.RLock() defer sf.RUnlock() msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+"*no msg*") if len(sf.lst) == 0 { return log_msg.NewLogMsg(sf.levDebug, msg) } if num >= d0.Num(len(sf.lst)) { return log_msg.NewLogMsg(sf.levDebug, msg) } if num <= 0 { return log_msg.NewLogMsg(sf.levDebug, msg) } return sf.lst[num] } // Debug -- сообщение отладки. func (sf *LogBuf) Debug(fTxt d0.Txt, args ...any) { sf.Lock() defer sf.Unlock() strMsg := d0.Sprintf(fTxt, args...) msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+d0.Txt(strMsg)) _msg := log_msg.NewLogMsg(sf.levDebug, msg) sf.lst = append(sf.lst, _msg) sf.checkLen() sf.printTerm(_msg) } // Info -- информационные сообщения. func (sf *LogBuf) Info(fMsg d0.Txt, args ...any) { sf.Lock() defer sf.Unlock() strMsg := d0.Sprintf(fMsg, args...) msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+strMsg) _msg := log_msg.NewLogMsg(sf.levInfo, msg) sf.lst = append(sf.lst, _msg) sf.checkLen() sf.printTerm(_msg) } // Warn -- предупреждающие сообщения. func (sf *LogBuf) Warn(fMsg d0.Txt, args ...any) { sf.Lock() defer sf.Unlock() strMsg := d0.Sprintf(fMsg, args...) msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+strMsg) _msg := log_msg.NewLogMsg(sf.levWarn, msg) sf.lst = append(sf.lst, _msg) sf.checkLen() sf.printTerm(_msg) } // Err -- сообщения об ошибках. func (sf *LogBuf) Err(err *d0.LErr, args ...any) { sf.Lock() defer sf.Unlock() strMsg := d0.Sprintf(err.String(), args...) msg := def_txt.LetTxt(sf.owner, sf.Prefix_.Get()+strMsg) _msg := log_msg.NewLogMsg(sf.levError, msg) sf.lst = append(sf.lst, _msg) sf.lstErr = append(sf.lstErr, _msg) sf.checkLen() sf.checkLenErr() sf.printTerm(_msg) } // Size -- возвращает размер буфера. func (sf *LogBuf) Size() d0.Num { sf.RLock() defer sf.RUnlock() return d0.Num(len(sf.lst)) } // Проверяет длину общую лога. func (sf *LogBuf) checkLen() { for len(sf.lst) > 100 { sf.lst = sf.lst[1:] } } // Проверяет длину лога ошибок. func (sf *LogBuf) checkLenErr() { for len(sf.lstErr) > 100 { sf.lstErr = sf.lstErr[1:] } } // Печатает сообщение в терминал, если разрешено. func (sf *LogBuf) printTerm(msg log_msg.ILogMsg) { if sf.IsTerm_.IsNot() { return } level := msg.Level() if helpers.IsStageProd { switch level.Get() { case "ERRO", "WARN": log.Printf("%v %v\n", level, msg.String()) default: return } } log.Printf("%v\n", msg.String()) } // SetLevel -- проверяет правильность своего состава. func (sf *LogBuf) SetLevel(level d0.Num) { switch level { case EMPTY: sf.level = sf.levEmpty case INFO: sf.level = sf.levInfo case DEBUG: sf.level = sf.levDebug case WARN: sf.level = sf.levWarn case ERROR: sf.level = sf.levError default: d0.If(true).Hassert("logMsg.LogBuf(): NOT SET level(%v)", level) } }