SuperCoder/internal/logging/logger.go

142 lines
2.7 KiB
Go
Raw Normal View History

2025-03-21 18:20:28 +01:00
package logging
import (
"context"
"io"
"log/slog"
"slices"
"github.com/kujtimiihoxha/termai/internal/pubsub"
"golang.org/x/exp/maps"
)
const DefaultLevel = "info"
2025-04-09 19:07:39 +02:00
const (
persistKeyArg = "$persist"
PersistTimeArg = "$persist_time"
)
2025-03-21 18:20:28 +01:00
var levels = map[string]slog.Level{
"debug": slog.LevelDebug,
DefaultLevel: slog.LevelInfo,
"warn": slog.LevelWarn,
"error": slog.LevelError,
}
func ValidLevels() []string {
keys := maps.Keys(levels)
slices.SortFunc(keys, func(a, b string) int {
if a == DefaultLevel {
return -1
}
if b == DefaultLevel {
return 1
}
if a < b {
return -1
}
return 1
})
return keys
}
2025-04-09 19:07:39 +02:00
func NewLogger(opts Options) Interface {
2025-03-21 18:20:28 +01:00
logger := &Logger{}
2025-04-09 19:07:39 +02:00
broker := pubsub.NewBroker[LogMessage]()
2025-03-21 18:20:28 +01:00
writer := &writer{
2025-04-09 19:07:39 +02:00
messages: []LogMessage{},
2025-03-21 18:20:28 +01:00
Broker: broker,
}
handler := slog.NewTextHandler(
2025-04-09 19:07:39 +02:00
io.MultiWriter(writer),
2025-03-21 18:20:28 +01:00
&slog.HandlerOptions{
Level: slog.Level(levels[opts.Level]),
},
)
logger.logger = slog.New(handler)
logger.writer = writer
return logger
}
type Options struct {
2025-04-09 19:07:39 +02:00
Level string
2025-03-21 18:20:28 +01:00
}
type Logger struct {
logger *slog.Logger
writer *writer
}
2025-04-09 19:07:39 +02:00
func (l *Logger) SetLevel(level string) {
if _, ok := levels[level]; !ok {
level = DefaultLevel
}
handler := slog.NewTextHandler(
io.MultiWriter(l.writer),
&slog.HandlerOptions{
Level: levels[level],
},
)
l.logger = slog.New(handler)
}
// PersistDebug implements Interface.
func (l *Logger) PersistDebug(msg string, args ...any) {
args = append(args, persistKeyArg, true)
l.Debug(msg, args...)
}
// PersistError implements Interface.
func (l *Logger) PersistError(msg string, args ...any) {
args = append(args, persistKeyArg, true)
l.Error(msg, args...)
}
// PersistInfo implements Interface.
func (l *Logger) PersistInfo(msg string, args ...any) {
args = append(args, persistKeyArg, true)
l.Info(msg, args...)
}
// PersistWarn implements Interface.
func (l *Logger) PersistWarn(msg string, args ...any) {
args = append(args, persistKeyArg, true)
l.Warn(msg, args...)
}
2025-03-21 18:20:28 +01:00
func (l *Logger) Debug(msg string, args ...any) {
l.logger.Debug(msg, args...)
}
func (l *Logger) Info(msg string, args ...any) {
l.logger.Info(msg, args...)
}
func (l *Logger) Warn(msg string, args ...any) {
l.logger.Warn(msg, args...)
}
func (l *Logger) Error(msg string, args ...any) {
l.logger.Error(msg, args...)
}
2025-04-09 19:07:39 +02:00
func (l *Logger) List() []LogMessage {
2025-03-21 18:20:28 +01:00
return l.writer.messages
}
2025-04-09 19:07:39 +02:00
func (l *Logger) Get(id string) (LogMessage, error) {
2025-03-21 18:20:28 +01:00
for _, msg := range l.writer.messages {
if msg.ID == id {
return msg, nil
}
}
2025-04-09 19:07:39 +02:00
return LogMessage{}, io.EOF
2025-03-21 18:20:28 +01:00
}
2025-04-09 19:07:39 +02:00
func (l *Logger) Subscribe(ctx context.Context) <-chan pubsub.Event[LogMessage] {
2025-03-21 18:20:28 +01:00
return l.writer.Subscribe(ctx)
}