diff --git a/go/cmd/entrypoint/daemon.go b/go/cmd/entrypoint/daemon.go index ef8d475..c8b8c04 100644 --- a/go/cmd/entrypoint/daemon.go +++ b/go/cmd/entrypoint/daemon.go @@ -7,8 +7,6 @@ import ( "isle/daemon" "isle/daemon/daecommon" - - "dev.mediocregopher.com/mediocre-go-lib.git/mlog" ) // TODO it would be good to have an `isle daemon config-check` kind of command, @@ -30,11 +28,6 @@ var subCmdDaemon = subCmd{ "Write the default configuration file to stdout and exit.", ) - logLevelStr := ctx.flags.StringP( - "log-level", "l", "info", - `Maximum log level which should be output. Values can be "debug", "info", "warn", "error", "fatal". Does not apply to sub-processes`, - ) - ctx, err := ctx.withParsedFlags() if err != nil { return fmt.Errorf("parsing flags: %w", err) @@ -44,12 +37,8 @@ var subCmdDaemon = subCmd{ return daecommon.CopyDefaultConfig(os.Stdout) } - logLevel := mlog.LevelFromString(*logLevelStr) - if logLevel == nil { - return fmt.Errorf("couldn't parse log level %q", *logLevelStr) - } - - logger := ctx.logger.WithMaxLevel(logLevel.Int()) + logger := ctx.logger() + defer logger.Close() // TODO check that daemon is either running as root, or that the // required linux capabilities are set. diff --git a/go/cmd/entrypoint/flags.go b/go/cmd/entrypoint/flags.go index fcd8732..e1bc372 100644 --- a/go/cmd/entrypoint/flags.go +++ b/go/cmd/entrypoint/flags.go @@ -2,9 +2,13 @@ package main import ( "encoding" + "errors" "fmt" "isle/nebula" + "isle/toolkit" "net/netip" + + "dev.mediocregopher.com/mediocre-go-lib.git/mlog" ) type textUnmarshaler[T any] interface { @@ -37,3 +41,24 @@ type ( ipNetFlag = textUnmarshalerFlag[nebula.IPNet, *nebula.IPNet] ipFlag = textUnmarshalerFlag[netip.Addr, *netip.Addr] ) + +type logLevelFlag struct { + mlog.Level +} + +func (f *logLevelFlag) Set(v string) error { + f.Level = toolkit.LogLevelFromString(v) + if f.Level == nil { + return errors.New("not a valid log level") + } + return nil +} + +func (f *logLevelFlag) String() string { + if f.Level == nil { + return "UNKNOWN" + } + return f.Level.String() +} + +func (f *logLevelFlag) Type() string { return "string" } diff --git a/go/cmd/entrypoint/logger.go b/go/cmd/entrypoint/logger.go deleted file mode 100644 index a9a9510..0000000 --- a/go/cmd/entrypoint/logger.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path" - "sync" - - "dev.mediocregopher.com/mediocre-go-lib.git/mctx" - "dev.mediocregopher.com/mediocre-go-lib.git/mlog" -) - -type logMsgHandler struct { - stderr *os.File - l sync.Mutex -} - -func newLogMsgHandler() mlog.MessageHandler { - return &logMsgHandler{ - stderr: os.Stderr, - } -} - -func (h *logMsgHandler) Sync() error { - return h.stderr.Sync() -} - -func (h *logMsgHandler) Handle(msg mlog.FullMessage) error { - h.l.Lock() - defer h.l.Unlock() - - var namespaceStr string - - if len(msg.Namespace) > 0 { - namespaceStr = "[" + path.Join(msg.Namespace...) + "] " - } - - var annotationsStr string - - if m := mctx.EvaluateAnnotations(msg.Context, nil).StringMap(); len(m) > 0 { - - for k, v := range m { - annotationsStr += fmt.Sprintf(" %q=%q", k, v) - } - } - - fmt.Fprintf( - h.stderr, "%s %s%s%s\n", - msg.Level.String(), - namespaceStr, - msg.Description, - annotationsStr, - ) - - return nil -} diff --git a/go/cmd/entrypoint/main.go b/go/cmd/entrypoint/main.go index 1a2a35a..ca33e0c 100644 --- a/go/cmd/entrypoint/main.go +++ b/go/cmd/entrypoint/main.go @@ -29,11 +29,7 @@ func binPath(name string) string { } func main() { - - logger := mlog.NewLogger(&mlog.LoggerOpts{ - MessageHandler: newLogMsgHandler(), - MaxLevel: mlog.LevelInfo.Int(), // TODO make this configurable - }) + logger := mlog.NewLogger(nil) defer logger.Close() ctx, cancel := context.WithCancel(context.Background()) @@ -56,7 +52,6 @@ func main() { err := subCmdCtx{ Context: ctx, - logger: logger, args: os.Args[1:], }.doSubCmd( subCmdDaemon, diff --git a/go/cmd/entrypoint/sub_cmd.go b/go/cmd/entrypoint/sub_cmd.go index c8f50db..1e23dfd 100644 --- a/go/cmd/entrypoint/sub_cmd.go +++ b/go/cmd/entrypoint/sub_cmd.go @@ -14,7 +14,8 @@ import ( type flagSet struct { *pflag.FlagSet - network string + network string + logLevel logLevelFlag } type subCmd struct { @@ -38,18 +39,16 @@ type subCmd struct { // subCmdCtx contains all information available to a subCmd's do method. type subCmdCtx struct { context.Context - logger *mlog.Logger subCmd subCmd // the subCmd itself args []string // command-line arguments, excluding the subCmd itself. subCmdNames []string // names of subCmds so far, including this one - flags flagSet + flags *flagSet } func newSubCmdCtx( ctx context.Context, - logger *mlog.Logger, subCmd subCmd, args []string, subCmdNames []string, @@ -72,17 +71,25 @@ func newSubCmdCtx( os.Exit(2) } - fs := flagSet{FlagSet: flags} + fs := &flagSet{ + FlagSet: flags, + logLevel: logLevelFlag{mlog.LevelInfo}, + } if !subCmd.noNetwork { fs.FlagSet.StringVar( - &fs.network, "network", "", "Which network to perform the command against, if more than one is joined. Can be ID, name, or domain", + &fs.network, "network", "", "Which network to perform the command against, if more than one is joined. Can be an ID, name, or domain.", ) } + fs.FlagSet.VarP( + &fs.logLevel, + "log-level", "l", + "Maximum log level to output. Can be DEBUG, CHILD, INFO, WARN, ERROR, or FATAL.", + ) + return subCmdCtx{ Context: ctx, - logger: logger, subCmd: subCmd, args: args, subCmdNames: subCmdNames, @@ -99,6 +106,12 @@ func usagePrefix(subCmdNames []string) string { return fmt.Sprintf("\nUSAGE: %s %s", os.Args[0], subCmdNamesStr) } +func (ctx subCmdCtx) logger() *mlog.Logger { + return mlog.NewLogger(&mlog.LoggerOpts{ + MaxLevel: ctx.flags.logLevel.Int(), + }) +} + func (ctx subCmdCtx) withParsedFlags() (subCmdCtx, error) { ctx.flags.VisitAll(func(f *pflag.Flag) { if f.Shorthand == "h" { @@ -167,7 +180,6 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error { nextSubCmdCtx := newSubCmdCtx( ctx.Context, - ctx.logger, subCmd, args, append(ctx.subCmdNames, subCmdName),