// Copyright 2023 wanderer // SPDX-License-Identifier: AGPL-3.0-only package slogging import ( "fmt" "os" "golang.org/x/exp/slog" ) type Slogger struct { *slog.Logger } const ( LevelInfo int = iota LevelDebug LevelWarn LevelError ) var ( logger *Slogger opts *slog.HandlerOptions initialised = false ) func Opts() *slog.HandlerOptions { return opts } func Logger() *Slogger { return logger } func Init(jsonHandler bool) *Slogger { opts = &slog.HandlerOptions{ Level: slog.LevelInfo, } if jsonHandler { logger = &Slogger{slog.New(slog.NewJSONHandler(os.Stderr, opts))} } else { logger = &Slogger{slog.New(slog.NewTextHandler(os.Stderr, opts))} } slog.SetDefault(logger.Logger) if initialised { logger.Info("slog logger reinitialised") } else { initialised = true logger.Info("slog logger initialised") } return logger } // SetLevel allows setting log level and returns the pointer to the re-created // logger. func SetLevel(level int) *Slogger { switch level { case LevelInfo: opts.Level = slog.LevelInfo case LevelDebug: opts.Level = slog.LevelDebug case LevelWarn: opts.Level = slog.LevelWarn case LevelError: opts.Level = slog.LevelError default: logger.Infof("unknown level '%d', resetting to level INFO", level) opts.Level = slog.LevelInfo } if _, ok := logger.Handler().(*slog.JSONHandler); ok { logger = &Slogger{slog.New(slog.NewJSONHandler(os.Stderr, opts))} } else { logger = &Slogger{slog.New(slog.NewTextHandler(os.Stderr, opts))} } slog.SetDefault(logger.Logger) return logger } func (l *Slogger) Debugf(msg string, args ...any) { l.Debug(fmt.Sprintf(msg, args...)) } func (l *Slogger) Infof(msg string, args ...any) { l.Info(fmt.Sprintf(msg, args...)) } func (l *Slogger) Warnf(msg string, args ...any) { l.Warn(fmt.Sprintf(msg, args...)) } func (l *Slogger) Errorf(msg string, args ...any) { l.Error(fmt.Sprintf(msg, args...)) }