1 Star 2 Fork 3

kristas/booting-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
logger.go 5.01 KB
一键复制 编辑 原始数据 按行查看 历史
kristas 提交于 2021-09-17 17:21 . feat: rebuild log
package log
import (
"context"
"fmt"
. "gitee.com/kristas/booting-go/framework/common/util/console"
"gitee.com/kristas/booting-go/framework/common/util/lang"
"path"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
const (
maximumCallerDepth int = 6
DefaultDepth int = 4
)
type LoggerFacade struct {
Ctx context.Context
frame *runtime.Frame
lvl Level
Logger LoggerAdapter
Conf *Configure
depth int
callerInitOnce sync.Once
minimumCallerDepth int
loggerPackage string
}
func New(logger LoggerAdapter, conf *Configure, depth int) (Logger, error) {
l := &LoggerFacade{
Logger: logger,
Conf: conf,
depth: depth,
}
return l, nil
}
func (l *LoggerFacade) Context(ctx context.Context) Logger {
l.Ctx = ctx
return l
}
func (l *LoggerFacade) Trace(format string, a ...interface{}) {
l.lvl = Trace
l.Logger.Trace(l.build(format, a...))
}
func (l *LoggerFacade) Debug(format string, a ...interface{}) {
l.lvl = Debug
l.Logger.Debug(l.build(format, a...))
}
func (l *LoggerFacade) Info(format string, a ...interface{}) {
l.lvl = Info
l.Logger.Info(l.build(format, a...))
}
func (l *LoggerFacade) Warn(format string, a ...interface{}) {
l.lvl = Warn
l.Logger.Warn(l.build(format, a...))
}
func (l *LoggerFacade) Error(format string, a ...interface{}) {
l.lvl = Error
l.Logger.Error(l.build(format, a...))
}
func (l *LoggerFacade) Panic(format string, a ...interface{}) {
l.lvl = Panic
l.Logger.Panic(l.build(format, a...))
}
func (l *LoggerFacade) Fatal(format string, a ...interface{}) {
l.lvl = Fatal
l.Logger.Fatal(l.build(format, a...))
}
type parser func(spec *Spec) string
func (l *LoggerFacade) build(format string, a ...interface{}) string {
l.frame = l.getCaller()
if l.frame == nil {
return ""
}
spec := l.Conf.Style.Spec
s := lang.NewEmptyString()
for _, tmp := range l.Conf.Style.Template {
s = s.Concat(l.styleParser(tmp)(spec[tmp]))
}
message := fmt.Sprintf(format, a...)
return s.Format(message).String()
}
func (l *LoggerFacade) styleParser(template string) parser {
switch template {
case timestamp:
return l.parseTimestamp
case level:
return l.parseLevel
case function:
return l.parseFunction
case location:
return l.parseLocation
case separator:
return l.parseSeparator
case message:
return l.parseMessage
default:
return func(spec *Spec) string {
return ""
}
}
}
func (l *LoggerFacade) parseTimestamp(spec *Spec) string {
now := time.Now()
return Draw(spec.Color, now.Format(spec.Layout))
}
func (l *LoggerFacade) parseLevel(spec *Spec) string {
switch l.lvl {
case Trace:
return Drawf(BlueBold, spec.Layout, l.lvl.String())
case Debug:
return Drawf(CyanBold, spec.Layout, l.lvl.String())
case Info:
return Drawf(GreenBold, spec.Layout, l.lvl.String())
case Warn:
return Drawf(YellowBold, spec.Layout, l.lvl.String())
case Error:
return Drawf(RedBold, spec.Layout, l.lvl.String())
case Fatal:
return Drawf(RedBold, spec.Layout, l.lvl.String())
case Panic:
return Drawf(RedBold, spec.Layout, l.lvl.String())
}
return ""
}
func (l *LoggerFacade) parseFunction(spec *Spec) string {
fc := l.packageParser(l.frame.Function)
return Draw(spec.Color, lang.NewString(spec.Layout).Format(fc).String())
}
func (l *LoggerFacade) parseLocation(spec *Spec) string {
dir, file := path.Split(l.frame.File)
line := strconv.Itoa(l.frame.Line)
return Draw(spec.Color, lang.NewString(spec.Layout).
ReplaceAll("dir", dir).
ReplaceAll("file", file).
ReplaceAll("line", line).String())
}
func (l *LoggerFacade) parseSeparator(spec *Spec) string {
return Draw(spec.Color, spec.Layout)
}
func (l *LoggerFacade) parseMessage(spec *Spec) string {
return Draw(spec.Color, spec.Layout)
}
func (l *LoggerFacade) packageParser(pkg string) string {
split := lang.NewString(pkg).ReplaceAll("/", ".").Split(".")
pkgArr := lang.TransferSliceToSimple(split)
var tmp []string
skipIndex := l.Conf.SkipIndex
for i, s := range pkgArr {
if i < skipIndex {
tmp = append(tmp, s[:1])
} else {
tmp = append(tmp, s)
}
}
return strings.Join(tmp, ".")
}
func (l *LoggerFacade) getCaller() *runtime.Frame {
l.callerInitOnce.Do(func() {
pcs := make([]uintptr, maximumCallerDepth)
_ = runtime.Callers(0, pcs)
for i := 0; i < maximumCallerDepth; i++ {
funcName := runtime.FuncForPC(pcs[i]).Name()
if strings.Contains(funcName, "getCaller") {
l.loggerPackage = getPackageName(funcName)
break
}
}
l.minimumCallerDepth = l.depth
})
pcs := make([]uintptr, maximumCallerDepth)
depth := runtime.Callers(l.minimumCallerDepth, pcs)
frames := runtime.CallersFrames(pcs[:depth])
for f, again := frames.Next(); again; f, again = frames.Next() {
pkg := getPackageName(f.Function)
if pkg != l.loggerPackage {
return &f //nolint:scopelint
}
}
return nil
}
func getPackageName(f string) string {
for {
lastPeriod := strings.LastIndex(f, ".")
lastSlash := strings.LastIndex(f, "/")
if lastPeriod > lastSlash {
f = f[:lastPeriod]
} else {
break
}
}
return f
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/kristas/booting-go.git
git@gitee.com:kristas/booting-go.git
kristas
booting-go
booting-go
v1.3.7

搜索帮助