Skip to content

fix(cli): install the tracing subscriber before flag validation - #671

Open
emlautarom1-agent[bot] wants to merge 5 commits into
mainfrom
worktree-tracing-init
Open

fix(cli): install the tracing subscriber before flag validation#671
emlautarom1-agent[bot] wants to merge 5 commits into
mainfrom
worktree-tracing-init

Conversation

@emlautarom1-agent

@emlautarom1-agent emlautarom1-agent Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Closes #604

Summary

pluto_tracing::init was called from five places, each of them after the command had already converted and validated its own arguments, so anything raised during that conversion went to a subscriber that did not exist yet. --p2p-relays=http://… produced no insecure-relay warning at all on run, unsafe run, dkg or relay, and enr/version installed no subscriber whatsoever.

The log and Loki flags now live in one TracingArgs, flattened onto the root command as clap globals. main builds a single TracingConfig from it and calls pluto_tracing::init once, before dispatching to any command. Since the flags no longer belong to the subcommand, no command can run its conversion ahead of init: the ordering is structural rather than a convention.

init also spawns the Loki background task and returns a LokiWorker, so the drain is owned in one place under a single flush budget. Centralizing both removes the per-command flag copies, their duplicated spawn and drain blocks, and the config fields that carried a TracingConfig no crate ever read.

Differences from Charon

  1. The log and Loki flags are global. Charon binds --log-* to run, relay and dkg, and --loki-* to run and relay. Here all six attach to every subcommand, which is what lets main read them off the root before any subcommand exists. Scoping them per-command would put a match arm per command back into main — the coupling this removes. Consequence: dkg gains the Loki flags, and enr, version, create * and alpha test * gain all six.
  2. --log-color=auto keys off NO_COLOR rather than TTY detection. Charon uses term.IsTerminal(os.Stderr.Fd()). The behaviour itself is unchanged here; it is called out because the flag now applies to every command.

emlautarom1-agent Bot and others added 3 commits August 26, 2026 13:41
Consolidate the per-command log and Loki flags into a single `TracingArgs`
flattened onto the root command as global args, and initialize tracing once
in `main` from those flags, before any command builds its config. Warnings
raised while validating flags — notably the insecure-relay warning — reach
the subscriber on every command, and `enr`/`version` get a subscriber too.

Console output goes to stderr so a command's stdout stays pipeable, and
`--log-level` accepts only the levels Charon documents, so a typo cannot
parse as an env-filter target directive and silently disable logging.

`pluto_tracing::init` spawns the Loki background task and returns the
worker, so the drain lifetime is owned in one place.

Closes #604
Charon resolves the level through `zapcore.ParseLevel` and lowercases the
color before matching, so both accept `INFO` and `FORCE` as readily as
`info` and `force` — a common shape for values supplied through
`CHARON_LOG_LEVEL` in unit files and compose manifests.

Values that name no level at all stay rejected, so a typo cannot parse as
an env-filter target directive and silently disable logging.
`main` reports a tracing-init failure and a clap parse failure directly on
stderr, since neither has a subscriber to report through, so nothing
converts either error into a `CliError`. Removing the variants also removes
the `From` impls that made them look reachable.

@emlautarom1-agent emlautarom1-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline notes on the parts that carry a decision rather than a mechanical edit.

Comment on lines +67 to +128
#[arg(
long = "log-format",
env = "CHARON_LOG_FORMAT",
default_value = "console",
global = true,
display_order = 1000,
help = "Log format; console, logfmt or json"
)]
pub log_format: String,

#[arg(
long = "log-level",
env = "CHARON_LOG_LEVEL",
default_value = "info",
global = true,
ignore_case = true,
display_order = 1001,
help = "Log level; debug, info, warn or error"
)]
pub log_level: LogLevel,

#[arg(
long = "log-color",
env = "CHARON_LOG_COLOR",
default_value = "auto",
global = true,
ignore_case = true,
display_order = 1002,
help = "Log color; auto, force, disable."
)]
pub log_color: ConsoleColor,

#[arg(
long = "log-output-path",
env = "CHARON_LOG_OUTPUT_PATH",
global = true,
display_order = 1003,
help = "Path in which to write on-disk logs."
)]
pub log_output_path: Option<PathBuf>,

#[arg(
long = "loki-addresses",
env = "CHARON_LOKI_ADDRESSES",
value_delimiter = ',',
global = true,
display_order = 1004,
help = "Enables sending of logfmt structured logs to these Loki log aggregation server addresses. This is in addition to normal stderr logs."
)]
pub loki_addresses: Vec<String>,

#[arg(
long = "loki-service",
env = "CHARON_LOKI_SERVICE",
default_value = "pluto",
global = true,
display_order = 1005,
help = "Service label sent with logs to Loki."
)]
pub loki_service: String,
}

@emlautarom1-agent emlautarom1-agent Bot Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Differs from Charon. All six flags are global, so they attach to every subcommand; Charon binds --log-* to run/relay/dkg and --loki-* to run/relay only.

With this, main can read the flags off the root before any subcommand exists, so no command can push in a conversion ahead of init. Scoping them per-command would put a match arm per command back into main, which is the coupling being removed.

Comment thread crates/cli/src/main.rs
Err(err) => {
eprintln!("{err}");
return ExitCode::FAILURE;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why eprintln! survives here. These two early returns are the only paths with no subscriber to report through — the arg-match failure, and init itself failing. Every other error goes through error! so it also reaches Loki before the drain below.

@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
@NethermindEth NethermindEth deleted a comment from emlautarom1-agent Bot Aug 26, 2026
emlautarom1-agent Bot and others added 2 commits August 26, 2026 14:39
`--log-format` and `--log-output-path` are accepted and never applied, and
only the first `--loki-addresses` entry reaches a layer. A runtime warning
covered one of the three and fired on every command that set it, including
the ones that never read the flag.

Note the gap on each field instead, so it is visible where the flag is
declared and stays next to the work needed to close it.
@emlautarom1
emlautarom1 marked this pull request as ready for review August 26, 2026 17:53

@emlautarom1 emlautarom1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required quite a bit of steering; final code is shorter due to the removal of duplication. Main changes are:

  • Tracing flags are global and processed as soon as possible, so further parsing can signal using the tracing module.
  • Replaced free standing strings with closed enums (ex. log levels)
  • Made flags case insensitive to match Charon
  • Logs go to stderr
  • Removed some warnings due to unused flags; prefer to use TODOs instead.

// no subscriber is installed yet (init happens later inside
// `commands::relay::run`), so write directly to stderr.
eprintln!(
"warning: {extra} additional --loki-addresses ignored; only the first is used",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep this warning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stop losing pre-init tracing events

2 participants