diff --git a/cmd/twhelp/app.go b/cmd/twhelp/app.go index c3c9330..edf6aa1 100644 --- a/cmd/twhelp/app.go +++ b/cmd/twhelp/app.go @@ -7,17 +7,23 @@ import ( "github.com/urfave/cli/v2" ) +type appMode string + const ( - appModeProduction = "production" - appModeDevelopment = "development" + appModeProduction appMode = "production" + appModeDevelopment appMode = "development" ) +func (m appMode) String() string { + return string(m) +} + var ( appFlagMode = &cli.GenericFlag{ Name: "mode", Value: &EnumValue{ - Enum: []string{appModeDevelopment, appModeProduction}, - Default: appModeDevelopment, + Enum: []string{appModeDevelopment.String(), appModeProduction.String()}, + Default: appModeDevelopment.String(), }, Usage: fmt.Sprintf("%s or %s", appModeProduction, appModeDevelopment), EnvVars: []string{"APP_MODE"}, @@ -38,12 +44,14 @@ func newApp(name, version string) *appWrapper { app.HelpName = name app.Version = version app.Commands = []*cli.Command{cmdDB, cmdJob} - app.Flags = appFlags + app.Flags = concatSlices(appFlags, logFlags) app.Before = app.handleBefore return app } func (a *appWrapper) handleBefore(c *cli.Context) error { + a.logger = newLoggerFromFlags(c) + c.Context = loggerToCtx(c.Context, a.logger) a.logger.Debug("executing command", slog.Any("args", c.Args().Slice())) diff --git a/cmd/twhelp/logger.go b/cmd/twhelp/logger.go index 873f2a0..1d4efaf 100644 --- a/cmd/twhelp/logger.go +++ b/cmd/twhelp/logger.go @@ -2,9 +2,115 @@ 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 { diff --git a/k8s/base/jobs.yml b/k8s/base/jobs.yml index 75ba4f6..bec9706 100644 --- a/k8s/base/jobs.yml +++ b/k8s/base/jobs.yml @@ -20,6 +20,8 @@ spec: env: - name: APP_MODE value: development + - name: LOG_LEVEL + value: debug - name: DB_CONNECTION_STRING valueFrom: secretKeyRef: @@ -56,6 +58,8 @@ spec: env: - name: APP_MODE value: development + - name: LOG_LEVEL + value: debug - name: DB_CONNECTION_STRING valueFrom: secretKeyRef: