minireader/internal/minireader/logger.go
2024-08-10 11:01:50 +07:00

84 lines
1.9 KiB
Go

package minireader
import (
"context"
"errors"
"fmt"
"log/slog"
"net/url"
"os"
"strings"
"time"
"github.com/samber/slog-loki"
"borodyadka.dev/borodyadka/minireader/internal/minireader/config"
)
func parseLoggerOutput(dsn string) (typ string, host string, err error) {
switch dsn {
case "none", "stdout":
return dsn, "", nil
}
u, err := url.Parse(dsn)
if err != nil {
return "", "", err
}
if strings.Contains(u.Scheme, "loki") {
u.Scheme = strings.NewReplacer("loki", "", "+", "").Replace(u.Scheme)
return "loki", u.String(), nil
}
return "", "", errors.New("cannot parse logger dsn")
}
func newLogger(config config.LogConfig) (*slog.Logger, error) {
var level slog.Level
if err := level.UnmarshalText([]byte(config.Level)); err != nil {
return nil, err
}
typ, host, err := parseLoggerOutput(config.Output)
if err != nil {
return nil, err
}
switch typ {
case "none":
return slog.New(discardHandler{}), nil
case "loki":
handler := slogloki.Option{
Level: level,
Endpoint: host,
BatchWait: time.Second,
BatchEntriesNumber: 32,
}.NewLokiHandler()
return slog.New(handler), nil
}
return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: level,
})), nil
}
type discardHandler struct{}
func (discardHandler) Enabled(context.Context, slog.Level) bool { return false }
func (discardHandler) Handle(context.Context, slog.Record) error { return nil }
func (d discardHandler) WithAttrs([]slog.Attr) slog.Handler { return d }
func (d discardHandler) WithGroup(string) slog.Handler { return d }
type gooseWrapper struct {
logger *slog.Logger
}
func (l *gooseWrapper) Printf(msg string, args ...any) {
l.logger.Info(fmt.Sprintf(strings.TrimSpace(msg), args...))
}
func (l *gooseWrapper) Fatalf(msg string, args ...any) {
l.logger.Error(fmt.Sprintf(strings.TrimSpace(msg), args...))
}