core/cmd/twhelp/logger.go

124 lines
2.4 KiB
Go

package main
import (
"context"
"fmt"
"io"
"log/slog"
"os"
"github.com/urfave/cli/v2"
)
type logLevel string
const (
logLevelDebug logLevel = "debug"
logLevelInfo logLevel = "info"
logLevelWarn logLevel = "warn"
logLevelError logLevel = "error"
)
func (l logLevel) slogLevel() slog.Level {
switch l {
case logLevelDebug:
return slog.LevelDebug
case logLevelInfo:
return slog.LevelInfo
case logLevelWarn:
return slog.LevelWarn
case logLevelError:
return slog.LevelError
default:
panic("unknown log level: " + l)
}
}
func (l logLevel) String() string {
return string(l)
}
type logFormat string
const (
logFormatText logFormat = "text"
logFormatJSON logFormat = "json"
)
func (f logFormat) newHandler(w io.Writer, opts *slog.HandlerOptions) slog.Handler {
switch f {
case logFormatText:
return slog.NewTextHandler(w, opts)
case logFormatJSON:
return slog.NewJSONHandler(w, opts)
default:
panic("unknown log format: " + f)
}
}
func (f logFormat) String() string {
return string(f)
}
var (
logFlagLevel = &cli.GenericFlag{
Name: "log.level",
Value: &EnumValue{
Enum: []string{
logLevelDebug.String(),
logLevelInfo.String(),
logLevelWarn.String(),
logLevelError.String(),
},
Default: logLevelInfo.String(),
},
Usage: fmt.Sprintf("%s, %s, %s or %s", logLevelDebug, logLevelInfo, logLevelWarn, logLevelError),
EnvVars: []string{"LOG_LEVEL"},
}
logFlagFormat = &cli.GenericFlag{
Name: "log.format",
Value: &EnumValue{
Enum: []string{
logFormatJSON.String(),
logFormatText.String(),
},
Default: logFormatText.String(),
},
Usage: fmt.Sprintf("%s or %s", logFormatText, logFormatJSON),
EnvVars: []string{"LOG_FORMAT"},
}
logFlags = []cli.Flag{
logFlagLevel,
logFlagFormat,
}
)
func newLoggerFromFlags(c *cli.Context) *slog.Logger {
return newLogger(loggerConfig{
level: logLevel(c.String(logFlagLevel.Name)),
format: logFormat(c.String(logFlagFormat.Name)),
})
}
type loggerConfig struct {
level logLevel
format logFormat
}
func newLogger(cfg loggerConfig) *slog.Logger {
return slog.New(cfg.format.newHandler(os.Stderr, &slog.HandlerOptions{
Level: cfg.level.slogLevel(),
}))
}
type loggerCtxKey struct{}
func loggerToCtx(ctx context.Context, l *slog.Logger) context.Context {
return context.WithValue(ctx, loggerCtxKey{}, l)
}
func loggerFromCtx(ctx context.Context) *slog.Logger {
logger, _ := ctx.Value(loggerCtxKey{}).(*slog.Logger)
return logger
}