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

@@ -10,7 +10,7 @@ Application logging modelled on Laravel's logging config: named channels (consol
`diary` owns the process logger of a SummerCMS application. `config/log.yaml` names a default channel, a global level and a map of channels, the way Laravel's `config/logging.php` does: a console channel that prints styled lines on a terminal, daily files with retention, and a stack that fans a record out to several channels. Code logs through named component loggers (`diary.For`), so every record carries the plugin or module it came from. Every channel is wrapped by `sunscreen.Wrap`, so credentials are redacted whichever channel a record reaches.
The application `main` that `summer build` generates reads the console global options first (`bonfire.PeekGlobals`), calls `diary.Bootstrap` with them, which installs a console channel before configuration is read, and `diary.Setup` right after `compass` loads `config/`. Once the command line is parsed, `diary.ApplyGlobals` re-applies `-v`, `-q` and `--ansi`/`--no-ansi`.
The application `main` that `summer build` generates reads the console global options first (`bonfire.PeekGlobals`), calls `diary.Bootstrap` with them, which installs a console channel before configuration is read, and `diary.Setup` right after `compass` loads `config/`. `diary.FromGlobals` also records the process arguments, and `diary.Bootstrap` and `diary.Setup` start the console at warnings for an invocation that only asks for help (`serve --help`), unless `-v` is given, so the info lines plugins log while they register and boot do not print above the help. Once the command line is parsed, `diary.ApplyGlobals` re-applies `-v`, `-q` and `--ansi`/`--no-ansi`.
## Role in the framework
@@ -34,6 +34,7 @@ Use cases:
- Redaction: every channel leaf is wrapped by `sunscreen.Wrap`.
- Runtime verbosity: `diary.SetVerbosity` lets info (1) or debug (2) through for every component and adds source locations on styled lines (3); quiet raises only the console channels to warn.
- Console global options: `diary.FromGlobals` turns `-v`/`-vv`/`-vvv`, `-q` and `--ansi`/`--no-ansi` into `diary.Options`, and `diary.ApplyGlobals` applies them to the running setup (the generated main registers it with `bonfire.OnGlobals`).
- Quiet boot for help: `diary.FromGlobals` also records the process arguments (`os.Args[1:]`) in `diary.Options`, and `diary.Bootstrap` and `diary.Setup` start the console channels at warnings, as `-q` would, when those arguments only ask for help (`-h` or `--help`) and no `-v` is given. Daily files and stderr channels keep their levels, warnings and errors still print, and an existing generated main gets it from a framework upgrade alone. A `diary.Options` literal without arguments does no check.
- The process default logger (`slog.Default`) and the standard `log` package log through the configured channels without a component.
## Usage
@@ -86,13 +87,13 @@ Tests that set diary up restore the previous process logger with `t.Cleanup(diar
| `diary.Bootstrap` | Installs a console channel on a writer before configuration is read and makes diary the process default logger. |
| `diary.Setup` | Parses `log.*` from a `compass` configuration, builds the channels and installs them; returns configuration errors. |
| `diary.SetVerbosity` | Changes verbosity and quiet at runtime. |
| `diary.FromGlobals` | Returns the `diary.Options` (verbosity, quiet, color mode) of the console global options in a `bonfire.Globals`. |
| `diary.FromGlobals` | Returns the `diary.Options` (verbosity, quiet, color mode) of the console global options in a `bonfire.Globals`, with the process arguments (`os.Args[1:]`) in `Args`. |
| `diary.ApplyGlobals` | Applies parsed `bonfire.Globals` to the running setup: verbosity and quiet, and the console color mode when it changed. |
| `diary.Verbosity` | Returns the current verbosity. |
| `diary.HideOnTTY` | Marks a context so a console channel writing to a terminal skips the records logged with it; files, stderr channels and a console that is not a terminal (also one with forced color, `--ansi` or `FORCE_COLOR`) still write them. Used for facts a command has just printed as a block, such as `serve`'s startup summary. |
| `diary.Reset` | Drops the setup, closes its files and restores the process default logger captured at the first setup. |
| `diary.Close` | Closes the open daily files; later records open them again. |
| `diary.Options` | Setup options: `Verbosity`, `Quiet`, `Color`, `Root`, `Stderr`, `Environ` and `Now`. |
| `diary.Options` | Setup options: `Verbosity`, `Quiet`, `Color`, `Root`, `Stderr`, `Environ`, `Now` and `Args` (the command-line arguments; when set, an invocation that only asks for help boots with the console at warnings). |
| `diary.ParseConfig` | Reads `log.*` over `diary.DefaultConfig`. |
| `diary.DefaultConfig` | The framework defaults. |
| `diary.Config` | Parsed configuration: `Default`, `Level`, `Channels` and `Components`. |
@@ -157,4 +158,4 @@ Environment variables use the `SUMMER_LOG__` prefix with a double underscore bet
go test ./modules/diary/...
```
`TestDiaryTracerSmoke` loads a `config/log.yaml` through `compass`, logs one record from a component logger and checks that it reaches the console and the daily file redacted. `TestConfigEnvSmoke` parses `SUMMER_LOG__` overrides given as strings and checks that every invalid value fails with an error naming its key. `TestDailyDegradesSmoke` points the daily channel at a read-only directory and checks that it warns once and the console keeps logging. The tests write to temporary directories and need no external services.
`TestDiaryTracerSmoke` loads a `config/log.yaml` through `compass`, logs one record from a component logger and checks that it reaches the console and the daily file redacted. `TestConfigEnvSmoke` parses `SUMMER_LOG__` overrides given as strings and checks that every invalid value fails with an error naming its key. `TestDailyDegradesSmoke` points the daily channel at a read-only directory and checks that it warns once and the console keeps logging. `TestBootQuietSmoke` runs the generated main's sequence with a plugin that logs while it registers and boots, and checks that `serve --help` keeps its info lines off the console (but not its warning, nor the daily file) while `serve` prints them. The tests write to temporary directories and need no external services.