zen/core/zlog/zlog.go

142 lines
3.3 KiB
Go

package zlog
import (
"context"
"io"
"log/slog"
"sync"
"github.com/fatih/color"
)
type WriteLocker interface {
io.Writer
sync.Locker
}
func WrapLocker(w io.Writer) WriteLocker {
if wl, ok := w.(WriteLocker); ok {
return wl
}
return &writeLocker{Writer: w}
}
type writeLocker struct {
io.Writer
sync.Mutex
}
type Log struct {
level slog.Level
bufPool *bufferPool
jsonPool *jsonHandlerPool
withAttrs []slog.Attr
withGroup []string
handlerOption *slog.HandlerOptions
pretty bool
color bool
writer WriteLocker
}
// Clone clones the Logger, replacing the output writer with w.
//
// If w is nil, the clone shares the original Logger's output writer.
func (log *Log) Clone(w io.Writer) *Log {
var output WriteLocker
if w == nil {
output = log.writer
} else {
output = WrapLocker(w)
}
withAttrs := make([]slog.Attr, len(log.withAttrs))
copy(withAttrs, log.withAttrs)
withGroup := make([]string, len(log.withGroup))
copy(withGroup, log.withGroup)
return &Log{
level: log.level,
withAttrs: withAttrs,
withGroup: withGroup,
handlerOption: log.handlerOption,
pretty: log.pretty,
bufPool: newBufferPool(),
jsonPool: newJsonHandlerPool(log.handlerOption),
writer: output,
}
}
// Enabled implements the slog.Handler interface.
func (lo *Log) Enabled(ctx context.Context, lvl slog.Level) bool {
return lvl >= lo.level
}
// Handle implements the slog.Handler interface.
func (lo *Log) Handle(ctx context.Context, record slog.Record) error {
if !lo.pretty {
j := lo.jsonPool.Get()
defer j.Put()
return j.Handle(ctx, record)
}
var levelColor *color.Color
switch {
case record.Level >= slog.LevelError:
levelColor = color.New(color.FgRed)
case record.Level >= slog.LevelWarn:
levelColor = color.New(color.FgYellow)
case record.Level >= slog.LevelInfo:
levelColor = color.New(color.FgGreen)
default:
levelColor = color.New(color.FgWhite)
}
_ = levelColor
buf := lo.bufPool.Get()
defer lo.bufPool.Put(buf)
panic("not implemented")
// if record.PC != 0 && pr.opts.AddSource {
// frame := caller.From(record.PC).Frame
// levelColor.Fprint(buf, frame.File)
// levelColor.Fprint(buf, ":")
// levelColor.Fprint(buf, frame.Line)
// levelColor.Fprint(buf, " -- ")
// split := strings.Split(frame.Function, string(os.PathSeparator))
// fnName := split[len(split)-1]
// levelColor.Fprint(buf, fnName)
// buf.WriteByte('\n')
// }
}
// WithAttrs implements the slog.Handler interface.
func (lo *Log) WithAttrs(attrs []slog.Attr) slog.Handler {
l := lo.Clone(nil)
l.withAttrs = append(l.withAttrs, attrs...)
return l
}
// WithGroup implements the slog.Handler interface.
func (lo *Log) WithGroup(name string) slog.Handler {
l := lo.Clone(nil)
l.withGroup = append(l.withGroup, name)
return l
}
type replaceAttrFunc = func([]string, slog.Attr) slog.Attr
// wrapReplaceAttr disables adding Time, Level, Source, Message
// fields when pretty mode is enabled.
func (lo *Log) wrapReplaceAttr(f replaceAttrFunc) replaceAttrFunc {
return func(s []string, a slog.Attr) slog.Attr {
if !lo.pretty {
return f(s, a)
}
switch a.Key {
case slog.TimeKey, slog.LevelKey, slog.SourceKey, slog.MessageKey:
return slog.Attr{}
}
return f(s, a)
}
}