chatai/internal/log/logger.go
2024-12-25 17:18:23 +00:00

168 lines
3.1 KiB
Go

package log
import (
"fmt"
"io"
"os"
"strings"
"time"
)
const (
CRed = LogColor("\033[01;31m")
CGreen = LogColor("\033[01;32m")
CYellow = LogColor("\033[01;33m")
CBlue = LogColor("\033[01;34m")
CMagenta = LogColor("\033[01;35m")
CCyan = LogColor("\033[01;36m")
CWhite = LogColor("\033[01;37m")
CReset = LogColor("\033[0m")
LDbg = LogLevel(0x00)
LInf = LogLevel(0x01)
LWrn = LogLevel(0x02)
LErr = LogLevel(0x03)
)
var (
LevelNameMap = map[LogLevel]string{
LDbg: "DBG",
LInf: "INF",
LWrn: "WRN",
LErr: "ERR",
}
LevelColorMap = map[LogLevel]LogColor{
LDbg: CBlue,
LInf: CGreen,
LWrn: CYellow,
LErr: CRed,
}
)
type Logger struct {
Writer io.Writer
TimeFormat string
TagColor map[string]LogColor
MinLevel LogLevel
}
type Tag struct {
Name string
Color LogColor
Logger *Logger
}
type LogColor string
type LogLevel uint8
func New(w io.Writer) *Logger {
return &Logger{
Writer: w,
TimeFormat: time.RFC3339,
}
}
func NewStdout() *Logger {
l := New(os.Stdout)
l.MinLevel = LInf
return l
}
func (l *Logger) AddTagColor(prefix string, color LogColor) *Logger {
l.TagColor[prefix] = color
return l
}
func (l *Logger) SetTagColor(m map[string]LogColor) *Logger {
l.TagColor = m
return l
}
func (l *Logger) SetTimeFormat(format string) *Logger {
l.TimeFormat = format
return l
}
func (l *Logger) GetFormatedTime() string {
return time.Now().Local().Format(l.TimeFormat)
}
func (l *Logger) Logf(tag string, level LogLevel, format string, a ...any) {
l.Tag(tag).Logf(level, format, a...)
}
func (l *Logger) Tag(tag string) *Tag {
color := CReset
for prefix, c := range l.TagColor {
if strings.HasPrefix(tag, prefix) {
color = c
}
}
return &Tag{Name: tag, Color: color, Logger: l}
}
func (tag *Tag) ColoredName() string {
return fmt.Sprintf("%s%s%s", tag.Color, tag.Name, CReset)
}
func (tag *Tag) Logf(level LogLevel, format string, a ...any) {
if level < tag.Logger.MinLevel {
return
}
lines := strings.Split(fmt.Sprintf(format, a...), "\n")
for _, line := range lines {
c := fmt.Sprintf("%s %s - [%s] %s\n",
tag.Logger.GetFormatedTime(),
level.Colored(),
tag.ColoredName(),
line,
)
//nolint:errcheck
tag.Logger.Writer.Write([]byte(c))
}
}
func (tag *Tag) LogWriter(level LogLevel) io.Writer {
r, w := io.Pipe()
go func() {
defer w.Close()
buf2 := []byte{}
buf1 := make([]byte, 1)
for {
_, err := r.Read(buf1)
if err != nil {
tag.Logger.Tag("log").Errf("LogWriter read error: %v", err)
break
}
if buf1[0] == '\n' {
tag.Logf(level, "%s", buf2)
buf2 = []byte{}
} else {
buf2 = append(buf2, buf1[0])
}
}
}()
return w
}
func (tag *Tag) Dbgf(format string, a ...any) {
tag.Logf(LDbg, format, a...)
}
func (tag *Tag) Inff(format string, a ...any) {
tag.Logf(LInf, format, a...)
}
func (tag *Tag) Wrnf(format string, a ...any) {
tag.Logf(LWrn, format, a...)
}
func (tag *Tag) Errf(format string, a ...any) {
tag.Logf(LErr, format, a...)
}
func (ll *LogLevel) Colored() string {
return fmt.Sprintf("%s%s%s", LevelColorMap[*ll], LevelNameMap[*ll], CReset)
}