feat(cli): wire verbosity flags and render typed daemon errors #377

Merged
KofTwentyTwo merged 1 commits from story/obs-9-cli-observability into dev 2026-08-01 00:41:50 +00:00
KofTwentyTwo commented 2026-08-01 00:39:39 +00:00 (Migrated from github.com)

Summary

  • Wires -v/-vv/-vvv to a real stderr tracing subscriber in nuncio-cli (previously parsed but never used). Default is warn; -v=info, -vv=debug, -vvv=trace. NUNCIO_LOG > RUST_LOG > -v count, mirroring nunciod's own precedence. Logs go to stderr only; command output (including --json) stays on stdout.
  • Decodes the WS-A1 ErrorInfo from a failed daemon RPC's grpc-status-details-bin trailer and renders the human message, the gRPC code, and the typed ErrorReason (e.g. ACCOUNT_NOT_FOUND) in both text and --json output, instead of dropping the code or falling back to a raw status.message(). Falls back to code+message when no typed ErrorInfo is present. Migrated ~30 mechanical error-rendering call sites in runner.rs onto a single render_status_error helper plus three sites that were dropping the code entirely (create_rule/preview_rule/update_rule's InvalidArgument arms).
  • docs/RUNNING.md: new "Following & auditing the daemon" section covering log levels, NUNCIO_LOG/RUST_LOG precedence, the rotating log file location (<data_dir>/logs/nunciod.log.<date>), NUNCIO_LOG_FORMAT=json, request_id correlation (grep pattern), and the CLI's -v/-vv/-vvv flags.

Refs #365 (OBS-9). Not a proto change.

Test plan

  • cargo fmt --all -- --check
  • cargo check-all (clippy --all-targets --workspace -D warnings, zero warnings)
  • cargo test-all -- all green, 0 ignored, 0 failed (workspace total incl. nuncio-cli lib 37 tests, cli_system_test 4 tests, nunciod lib 168 tests, plus e2e suites)
  • New tests: logging::tests::verbosity_count_maps_to_expected_level, logging::tests::nuncio_log_beats_rust_log_beats_verbosity_count (pure mapping, no double subscriber init), output::tests::format_json_error_with_info_carries_code_reason_and_metadata, output::tests::format_json_error_with_info_omits_reason_and_metadata_when_absent, runner::tests::typed_error_info_renders_code_reason_and_metadata_in_text_and_json (text + --json against a stub daemon)
  • Grepped the diff for token/password/secret/bearer -- only touches an import name (nuncio_cli::logging), no credential is ever logged
## Summary - Wires `-v/-vv/-vvv` to a real stderr `tracing` subscriber in `nuncio-cli` (previously parsed but never used). Default is `warn`; `-v`=info, `-vv`=debug, `-vvv`=trace. `NUNCIO_LOG` > `RUST_LOG` > `-v` count, mirroring `nunciod`'s own precedence. Logs go to stderr only; command output (including `--json`) stays on stdout. - Decodes the WS-A1 `ErrorInfo` from a failed daemon RPC's `grpc-status-details-bin` trailer and renders the human message, the gRPC code, and the typed `ErrorReason` (e.g. `ACCOUNT_NOT_FOUND`) in both text and `--json` output, instead of dropping the code or falling back to a raw `status.message()`. Falls back to code+message when no typed `ErrorInfo` is present. Migrated ~30 mechanical error-rendering call sites in `runner.rs` onto a single `render_status_error` helper plus three sites that were dropping the code entirely (`create_rule`/`preview_rule`/`update_rule`'s `InvalidArgument` arms). - `docs/RUNNING.md`: new "Following & auditing the daemon" section covering log levels, `NUNCIO_LOG`/`RUST_LOG` precedence, the rotating log file location (`<data_dir>/logs/nunciod.log.<date>`), `NUNCIO_LOG_FORMAT=json`, `request_id` correlation (grep pattern), and the CLI's `-v`/`-vv`/`-vvv` flags. Refs #365 (OBS-9). Not a proto change. ## Test plan - [x] `cargo fmt --all -- --check` - [x] `cargo check-all` (clippy `--all-targets --workspace -D warnings`, zero warnings) - [x] `cargo test-all` -- all green, 0 ignored, 0 failed (workspace total incl. `nuncio-cli` lib 37 tests, `cli_system_test` 4 tests, `nunciod` lib 168 tests, plus e2e suites) - [x] New tests: `logging::tests::verbosity_count_maps_to_expected_level`, `logging::tests::nuncio_log_beats_rust_log_beats_verbosity_count` (pure mapping, no double subscriber init), `output::tests::format_json_error_with_info_carries_code_reason_and_metadata`, `output::tests::format_json_error_with_info_omits_reason_and_metadata_when_absent`, `runner::tests::typed_error_info_renders_code_reason_and_metadata_in_text_and_json` (text + `--json` against a stub daemon) - [x] Grepped the diff for `token`/`password`/`secret`/`bearer` -- only touches an import name (`nuncio_cli::logging`), no credential is ever logged
Sign in to join this conversation.