errs/errs.go

171 lines
2.7 KiB
Go

// 0.1.2
package errs
import (
"fmt"
"os"
"runtime"
"git.leolab.info/lib/replacer"
)
type ErrCode string
var Silent = false
var StrFmt = "[ERROR] %date% %time% [%code%] %error% at %file%:%line% %func%"
var Trace = false
const (
ErrError ErrCode = "ErrError"
ErrNoError ErrCode = "ErrNoError"
ErrDSError ErrCode = "ErrDSError"
)
type src struct {
File string
Line int
Func string
}
//Структура ошибки
// 0.1.0
type Err struct {
dsId int64
Code ErrCode
Msg string
src src
Prev *Err
}
//Реализация интерфейса error
// 0.1.0
func (e *Err) Error() string {
if e == nil {
panic("NIL Error")
}
return e.Msg
}
//Получить "карту" ошибки
// 0.1.4
func (e *Err) Map() map[string]interface{} {
if e == nil {
panic("NIL Error")
}
ret := map[string]interface{}{
"DSId": e.dsId,
"Code": e.Code,
"Msg": e.Msg,
"Src": map[string]interface{}{
"File": e.src.File,
"Line": e.src.Line,
"Func": e.src.Func,
},
}
if e.Prev != nil {
ret["Prev"] = e.Error()
}
return ret
}
//Создать ошибку
// 0.1.4
func RaiseError(eCode ErrCode, msg string, prev ...*Err) *Err {
e := &Err{
Code: eCode,
Msg: msg,
src: getSrc(2),
Prev: nil,
}
if len(prev) > 0 {
e.Prev = prev[0]
}
e = storeDS(e)
logError(e)
return e
}
//Передать ошибку выше
// 0.1.4
func UpError(err *Err, args ...any) *Err {
e := &Err{
Code: err.Code,
Msg: err.Msg,
src: getSrc(2),
Prev: err,
}
if len(args) > 1 {
for _, a := range args {
switch v := a.(type) {
case string:
e.Msg = v
case ErrCode:
e.Code = v
default:
//Unknown
}
}
}
e = storeDS(e)
if Trace {
logError(e)
}
return e
}
//Преобразовать ошибку
// 0.1.0
func Error(e error) *Err {
err := &Err{
Code: ErrError,
Msg: e.Error(),
src: getSrc(2),
Prev: nil,
}
err = storeDS(err)
logError(err)
return err
}
//Получить источник
// 0.1.0
func getSrc(lvl int) (s src) {
pc, file, line, ok := runtime.Caller(lvl)
if !ok {
return src{File: "undefined", Line: 0, Func: "undefined()"}
}
f := runtime.CallersFrames([]uintptr{pc})
ff, _ := f.Next()
s = src{
File: file,
Line: line,
Func: ff.Function,
}
return s
}
//Получить строку по формату
// 0.1.0
func (e *Err) getString() string {
if e == nil {
panic("Err is NIL")
}
r := replacer.New()
r.Add("code", string(e.Code))
r.Add("file", e.src.File)
r.Add("line", fmt.Sprintf("%v", e.src.Line))
r.Add("func", e.src.Func)
r.Add("error", e.Msg)
return r.ReplaceC(StrFmt)
}
//Вывести ошибку
// 0.1.0
func logError(e *Err) {
storeFS(e)
if Silent {
return
}
fmt.Fprintln(os.Stderr, e.getString())
}