1
0
forked from x/icebergs
icebergs/logs.go
2022-11-29 11:30:23 +08:00

238 lines
6.3 KiB
Go

package ice
import (
"io"
"runtime"
"strings"
"time"
"unicode"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
)
func (m *Message) join(arg ...Any) (string, []Any) {
list, meta := []string{}, []Any{}
for i := 0; i < len(arg); i += 2 {
switch v := arg[i].(type) {
case logs.Meta:
meta = append(meta, v)
i--
continue
case []string:
list = append(list, v...)
i--
continue
}
key := strings.TrimSpace(kit.Format(arg[i]))
if i == len(arg)-1 {
list = append(list, key)
continue
}
switch v := arg[i+1].(type) {
case logs.Meta:
list = append(list, key)
meta = append(meta, v)
continue
case time.Time:
arg[i+1] = v.Format(MOD_TIME)
case []string:
arg[i+1] = kit.Join(v, " ")
}
list = append(list, key+kit.Select("", DF, !strings.Contains(key, DF)), kit.Format(arg[i+1]))
}
return kit.Join(list, SP), meta
}
func (m *Message) log(level string, str string, arg ...Any) *Message {
_source := logs.FileLineMeta(logs.FileLine(3))
if Info.Log != nil {
Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...))
}
if m.Option(LOG_DISABLE) == TRUE {
return m
}
prefix, suffix := "", ""
if Info.Colors {
switch level {
case LOG_CMDS:
prefix, suffix = "\033[32m", "\033[0m"
case LOG_AUTH, LOG_COST:
prefix, suffix = "\033[33m", "\033[0m"
case LOG_WARN, LOG_ERROR:
prefix, suffix = "\033[31m", "\033[0m"
}
}
switch level {
case LOG_INFO:
if len(str) > 4096 {
str = str[:4096]
}
}
logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...)
return m
}
func (m *Message) Log(level string, str string, arg ...Any) *Message {
return m.log(level, str, arg...)
}
func (m *Message) Logs(level string, arg ...Any) *Message {
str, meta := m.join(arg...)
if unicode.IsUpper([]rune(level)[0]) {
meta = []Any{logs.FileLineMeta("")}
}
return m.log(level, str, meta...)
}
func (m *Message) Auth(arg ...Any) *Message {
str, meta := m.join(arg...)
return m.log(LOG_AUTH, str, meta...)
}
func (m *Message) Cost(arg ...Any) *Message {
str, meta := m.join(arg...)
if str == "" || len(arg) == 0 {
str = kit.Join(m.meta[MSG_DETAIL], SP)
meta = []Any{logs.FileLineMeta(m._fileline())}
}
list := []string{m.FormatCost(), str}
return m.log(LOG_COST, kit.Join(list, SP), meta...)
}
func (m *Message) Info(str string, arg ...Any) *Message {
return m.log(LOG_INFO, str, arg...)
}
func (m *Message) WarnTimeNotValid(time Any, arg ...Any) bool {
return m.Warn(kit.Format(time) < m.Time(), ErrNotValid, kit.Simple(arg), time, m.Time(), logs.FileLineMeta(logs.FileLine(2)))
}
func (m *Message) Warn(err Any, arg ...Any) bool {
switch err := err.(type) {
case error:
if err == io.EOF {
return false
}
arg = append(arg, ERR, err)
case bool:
if !err {
return false
}
case nil:
return false
}
str, meta := m.join(arg...)
m.log(LOG_WARN, str, meta...)
if !m.IsErr() && len(arg) > 0 {
switch m.error(arg...); kit.Format(arg[0]) {
case ErrNotLogin:
m.RenderStatusUnauthorized(str)
case ErrNotRight:
m.RenderStatusForbidden(str)
case ErrNotFound:
m.RenderStatusNotFound(str)
case ErrNotValid:
m.RenderStatusBadRequest(str)
}
}
return true
}
func (m *Message) ErrorNotImplement(arg ...Any) {
m.Error(true, append(kit.List(ErrNotImplement), arg...)...)
}
func (m *Message) Error(err bool, arg ...Any) bool {
if err {
str, meta := m.join(arg...)
m.log(LOG_ERROR, m.FormatChain())
m.log(LOG_ERROR, str, meta)
m.log(LOG_ERROR, m.FormatStack(2, 100))
m.error(arg...)
return true
}
return false
}
func (m *Message) error(arg ...Any) {
if len(arg) > 2 {
str, _ := m.join(arg[2:]...)
m.Resultv(ErrWarn, kit.Simple(arg[0], arg[1], SP+str))
} else {
m.Resultv(ErrWarn, kit.Simple(arg))
}
}
func (m *Message) IsOk() bool { return m.Result() == OK }
func (m *Message) IsErr(arg ...string) bool {
return len(arg) == 0 && m.Result(0) == ErrWarn || len(arg) > 0 && m.Result(1) == arg[0]
}
func (m *Message) IsErrNotFound() bool {
return m.IsErr(ErrNotFound)
}
func (m *Message) Debug(str string, arg ...Any) {
if str == "" {
str = m.FormatMeta()
}
m.log(LOG_DEBUG, str, arg...)
}
func (m *Message) FormatPrefix() string {
return kit.Format("%s %d %s->%s", logs.FmtTime(logs.Now()), m.code, m.source.Name, m.target.Name)
}
func (m *Message) FormatShip() string {
return kit.Format("%s->%s", m.source.Name, m.target.Name)
}
func (m *Message) FormatCost() string {
return kit.FmtDuration(time.Since(m.time))
}
func (m *Message) FormatSize() string {
return kit.Format("%dx%d %v", m.Length(), len(m.meta[MSG_APPEND]), kit.Simple(m.meta[MSG_APPEND]))
}
func (m *Message) FormatMeta() string {
return kit.Format(m.meta)
}
func (m *Message) FormatsMeta() string {
return kit.Formats(m.meta)
}
func (m *Message) FormatChain() string {
ms := []*Message{}
for msg := m; msg != nil; msg = msg.message {
ms = append(ms, msg)
}
meta := append([]string{}, NL)
for i := len(ms) - 1; i >= 0; i-- {
msg := ms[i]
meta = append(meta, kit.Format("%s %s:%d %v %s:%d %v %s:%d %v %s:%d %v %s", msg.FormatPrefix(),
MSG_DETAIL, len(msg.meta[MSG_DETAIL]), msg.meta[MSG_DETAIL],
MSG_OPTION, len(msg.meta[MSG_OPTION]), msg.meta[MSG_OPTION],
MSG_APPEND, len(msg.meta[MSG_APPEND]), msg.meta[MSG_APPEND],
MSG_RESULT, len(msg.meta[MSG_RESULT]), msg.meta[MSG_RESULT],
msg._cmd.GetFileLine(),
))
for _, k := range msg.meta[MSG_OPTION] {
if v, ok := msg.meta[k]; ok {
meta = append(meta, kit.Format("\t%s: %d %v", k, len(v), v))
}
}
for _, k := range msg.meta[MSG_APPEND] {
if v, ok := msg.meta[k]; ok {
meta = append(meta, kit.Format("\t%s: %d %v", k, len(v), v))
}
}
}
return kit.Join(meta, NL)
}
func (m *Message) FormatStack(s, n int) string {
pc := make([]uintptr, n+10)
frames := runtime.CallersFrames(pc[:runtime.Callers(s+1, pc)])
list := []string{}
for {
frame, more := frames.Next()
file := kit.Slice(kit.Split(frame.File, PS, PS), -1)[0]
name := kit.Slice(kit.Split(frame.Function, PS, PS), -1)[0]
switch ls := kit.Split(name, PT, PT); kit.Select("", ls, 0) {
case "reflect", "runtime", "http":
default:
list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name))
}
if len(list) >= n {
break
}
if !more {
break
}
}
return kit.Join(list, NL)
}