feat(diary): boot --help invocations with the console at warn (quick-261028-rqc)

- Options.Args holds the command-line arguments; FromGlobals fills it
  from os.Args[1:], so the generated main needs no change
- Bootstrap and Setup install the setup with Quiet when Args only ask
  for help (-h, --help) and no -v is given; files keep their levels
- TestBootQuietSmoke runs the generated main's sequence with a plugin
  that logs from Register and Boot
This commit is contained in:
Jakub Zych
2026-10-28 21:43:36 +01:00
parent 653d95a5b9
commit 6b9becd994
5 changed files with 277 additions and 11 deletions

View File

@@ -31,6 +31,8 @@ type Options struct {
// to debug; 3 or more also adds source locations on the console.
Verbosity int
// Quiet raises the console channels to warn; files keep their levels.
// Bootstrap and Setup also set it for arguments that only ask for help
// (see Args).
Quiet bool
// Color decides on styled console output (bonfire.ColorAuto by default).
Color consolekit.ColorMode
@@ -43,6 +45,14 @@ type Options struct {
Environ []string
// Now is the clock of the daily writers; nil means time.Now.
Now func() time.Time
// Args are the command-line arguments without the program name. When
// non-nil, Bootstrap and Setup check whether they only ask for help
// and, at verbosity 0, install the setup with Quiet, so the records
// plugins log while they register and boot stay off the console.
// FromGlobals sets them to a copy of os.Args[1:]; nil (an Options
// literal) means no check. A caller that dispatches on other arguments
// sets Args itself.
Args []string
}
func (o Options) normalize() Options {
@@ -116,13 +126,15 @@ func For(component string) *slog.Logger {
// Bootstrap installs a console channel on w, before configuration is read,
// and makes diary the process default logger. The generated main calls it
// first; Setup replaces it once config/log.yaml is loaded.
// first; Setup replaces it once config/log.yaml is loaded. Like Setup, it
// starts the console at warn when opts.Args only ask for help and no -v is
// given.
func Bootstrap(w io.Writer, opts Options) {
if w == nil {
w = os.Stderr
}
opts.Stderr = w
opts = opts.normalize()
opts = bootQuiet(opts.normalize())
cfg := DefaultConfig()
cfg.Default = "console"
cfg.Channels = map[string]ChannelConfig{"console": {Driver: DriverConsole, Format: FormatAuto}}
@@ -138,13 +150,14 @@ func Bootstrap(w io.Writer, opts Options) {
// Setup parses log.* from cfg (ParseConfig), builds the channels and makes
// them the target of every diary logger and of the process default logger.
// A configuration error is returned and leaves the previous setup in place;
// a daily file that cannot be opened never fails Setup.
// a daily file that cannot be opened never fails Setup. When opts.Args only
// ask for help and no -v is given, the console channels start at warn.
func Setup(cfg *compass.Config, opts Options) error {
conf, err := ParseConfig(cfg)
if err != nil {
return err
}
opts = opts.normalize()
opts = bootQuiet(opts.normalize())
ch, err := buildChannels(conf, opts)
if err != nil {
return err
@@ -215,9 +228,15 @@ func setVerbosityLocked(v int, quiet bool) {
// FromGlobals returns the Options for the console global options: their
// verbosity, quiet switch and color mode. The generated main passes it to
// Bootstrap and Setup. g is a bonfire.Globals: bonfire and diary share the
// type through internal/consolekit, so diary does not link bonfire.
// type through internal/consolekit, so diary does not link bonfire. It also
// sets Args to a copy of os.Args[1:] (empty, not nil, without arguments), so
// an invocation that only asks for help boots with the console at warn.
func FromGlobals(g consolekit.Globals) Options {
return Options{Verbosity: g.Verbosity, Quiet: g.Quiet, Color: g.Color}
args := []string{}
if len(os.Args) > 1 {
args = append(args, os.Args[1:]...)
}
return Options{Verbosity: g.Verbosity, Quiet: g.Quiet, Color: g.Color, Args: args}
}
// ApplyGlobals applies the parsed global options to the installed setup: