HUGE refactor. working towards web UI
This commit is contained in:
parent
dd54e8cc49
commit
1f94eecca9
29 changed files with 1669 additions and 162 deletions
189
logger/slog.go
Normal file
189
logger/slog.go
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"arimelody.space/melody-vod-manager/colour"
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
type (
|
||||
Options struct {
|
||||
Handlers []slog.Handler
|
||||
Level slog.Leveler
|
||||
IsTerminal bool
|
||||
}
|
||||
|
||||
SlogHandler struct {
|
||||
attrs []slog.Attr
|
||||
group string
|
||||
mutex *sync.Mutex
|
||||
options Options
|
||||
writer io.Writer
|
||||
}
|
||||
)
|
||||
|
||||
const groupPadding = 11
|
||||
const levelPadding = 5
|
||||
|
||||
func NewSlogHandler(writer io.Writer, options Options) *SlogHandler {
|
||||
writerFile, writerIsFile := writer.(*os.File)
|
||||
if writerIsFile {
|
||||
options.IsTerminal = isatty.IsTerminal(writerFile.Fd())
|
||||
}
|
||||
|
||||
return &SlogHandler{
|
||||
options: options,
|
||||
attrs: []slog.Attr{},
|
||||
group: "OTHER",
|
||||
mutex: &sync.Mutex{},
|
||||
writer: writer,
|
||||
}
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendRecord(buf *strings.Builder, record slog.Record) {
|
||||
log.appendTime(buf, record.Time)
|
||||
log.appendGroup(buf, log.group)
|
||||
log.appendLevel(buf, record.Level)
|
||||
log.appendMessage(buf, record.Message)
|
||||
|
||||
for _, attr := range log.attrs {
|
||||
log.appendAttr(buf, attr)
|
||||
}
|
||||
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
log.appendAttr(buf, attr)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendTime(buf *strings.Builder, t time.Time) {
|
||||
if !t.IsZero() {
|
||||
if log.options.IsTerminal {
|
||||
buf.WriteString(colour.Dim + colour.Gray)
|
||||
}
|
||||
buf.WriteRune('[')
|
||||
buf.WriteString(t.Format(time.UnixDate))
|
||||
buf.WriteRune(']')
|
||||
if log.options.IsTerminal {
|
||||
buf.WriteString(colour.Reset)
|
||||
}
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendGroup(buf *strings.Builder, group string) {
|
||||
if log.options.IsTerminal {
|
||||
buf.WriteString(colour.Dim + colour.Gray)
|
||||
}
|
||||
log.appendPadLeft(buf, groupPadding, group)
|
||||
if log.options.IsTerminal {
|
||||
buf.WriteString(colour.Reset)
|
||||
}
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendPadLeft(buf *strings.Builder, padding int, content string) {
|
||||
padding -= len(content)
|
||||
for i := padding; i > 0; i-- {
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
buf.WriteString(content)
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendPadRight(buf *strings.Builder, padding int, content string) {
|
||||
buf.WriteString(content)
|
||||
padding -= len(content)
|
||||
for i := padding; i > 0; i-- {
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendLevel(buf *strings.Builder, level slog.Level) {
|
||||
if log.options.IsTerminal {
|
||||
levelColour := colour.Reset
|
||||
switch level {
|
||||
case slog.LevelDebug:
|
||||
levelColour = colour.Purple
|
||||
case slog.LevelError:
|
||||
levelColour = colour.Red
|
||||
case slog.LevelWarn:
|
||||
levelColour = colour.Yellow
|
||||
case slog.LevelInfo:
|
||||
levelColour = colour.Cyan
|
||||
}
|
||||
buf.WriteString(levelColour)
|
||||
}
|
||||
log.appendPadRight(buf, levelPadding, level.String())
|
||||
if log.options.IsTerminal {
|
||||
buf.WriteString(colour.Reset)
|
||||
}
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendMessage(buf *strings.Builder, message string) {
|
||||
if message != "" {
|
||||
buf.WriteString(message)
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func (log *SlogHandler) appendAttr(buf *strings.Builder, attr slog.Attr) {
|
||||
buf.WriteString(attr.String())
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
|
||||
func (log *SlogHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
return level >= log.options.Level.Level()
|
||||
}
|
||||
|
||||
func (log *SlogHandler) Handle(ctx context.Context, record slog.Record) error {
|
||||
buf := &strings.Builder{}
|
||||
|
||||
log.appendRecord(buf, record)
|
||||
|
||||
buf.WriteRune('\n')
|
||||
|
||||
log.mutex.Lock()
|
||||
defer log.mutex.Unlock()
|
||||
|
||||
if _, err := log.writer.Write([]byte(buf.String())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, handler := range log.options.Handlers {
|
||||
if err := handler.Handle(ctx, record); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (log *SlogHandler) WithGroup(group string) slog.Handler {
|
||||
log2 := *log
|
||||
log2.group = group
|
||||
log2.options.Handlers = make([]slog.Handler, len(log.options.Handlers))
|
||||
for i, handler := range log.options.Handlers {
|
||||
log.options.Handlers[i] = handler.WithGroup(group)
|
||||
}
|
||||
return &log2
|
||||
}
|
||||
|
||||
func (log *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
log2 := *log
|
||||
log2.attrs = make([]slog.Attr, 0, len(log.attrs)+len(attrs))
|
||||
log2.attrs = append(log2.attrs, log.attrs...)
|
||||
log2.attrs = append(log2.attrs, attrs...)
|
||||
log2.options.Handlers = make([]slog.Handler, len(log.options.Handlers))
|
||||
for i, handler := range log.options.Handlers {
|
||||
log.options.Handlers[i] = handler.WithAttrs(attrs)
|
||||
}
|
||||
return &log2
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue