package main import ( "fmt" "log/slog" "slices" "github.com/urfave/cli/v2" "go.uber.org/automaxprocs/maxprocs" ) type appMode string const ( 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.String(), appModeProduction.String()}, Default: appModeDevelopment.String(), }, Usage: fmt.Sprintf("%s or %s", appModeProduction, appModeDevelopment), EnvVars: []string{"APP_MODE"}, } appFlagAutoMaxProcs = &cli.BoolFlag{ Name: "autoMaxProcs", Usage: "whether to set GOMAXPROCS automatically to match Linux container CPU quota" + " (https://github.com/uber-go/automaxprocs)", Value: false, EnvVars: []string{"AUTO_MAX_PROCS"}, } appFlags = []cli.Flag{ appFlagMode, appFlagAutoMaxProcs, } ) type appWrapper struct { *cli.App logger *slog.Logger } func newApp(name, version string) *appWrapper { app := &appWrapper{App: cli.NewApp(), logger: slog.Default()} app.Name = name app.HelpName = name app.Version = version app.Commands = []*cli.Command{cmdDB, cmdJob, cmdConsumer, cmdServe} app.DefaultCommand = cmdServe.Name app.Flags = slices.Concat(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) if c.Bool(appFlagAutoMaxProcs.Name) { _, _ = maxprocs.Set(maxprocs.Logger(func(s string, v ...any) { a.logger.Info(fmt.Sprintf(s, v...)) })) } a.logger.Debug("executing command", slog.Any("args", c.Args().Slice())) return nil }