From cb6f263a1d9019dfdfe014361a3588d951dbfff8 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Wed, 25 Mar 2026 15:34:47 +0000 Subject: [PATCH] Add node.log_level config, remove RUST_LOG from service files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add log_level field to NodeConfig (case-insensitive, default: info). The daemon now loads config before initializing tracing so the configured level takes effect. RUST_LOG env var still overrides if set. Remove hardcoded Environment=RUST_LOG=info from systemd units and OpenWrt procd init script — these prevented config-driven log levels from working. --- packaging/debian/fips.service | 3 -- packaging/openwrt-ipk/files/etc/init.d/fips | 1 - packaging/systemd/fips.service | 3 -- src/bin/fips.rs | 53 ++++++++++----------- src/config/node.rs | 17 +++++++ 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/packaging/debian/fips.service b/packaging/debian/fips.service index 6a40b39..4460eaa 100644 --- a/packaging/debian/fips.service +++ b/packaging/debian/fips.service @@ -9,9 +9,6 @@ ExecStart=/usr/bin/fips --config /etc/fips/fips.yaml Restart=on-failure RestartSec=5 -# Logging: RUST_LOG controls verbosity. -Environment=RUST_LOG=info - # Control socket directory (/run/fips/). # Group-accessible so 'fips' group members can use fipsctl/fipstop. RuntimeDirectory=fips diff --git a/packaging/openwrt-ipk/files/etc/init.d/fips b/packaging/openwrt-ipk/files/etc/init.d/fips index f5032d5..a5e3151 100644 --- a/packaging/openwrt-ipk/files/etc/init.d/fips +++ b/packaging/openwrt-ipk/files/etc/init.d/fips @@ -14,7 +14,6 @@ start_service() { procd_open_instance procd_set_param command "$PROG" --config "$CONFIG" - procd_set_param env RUST_LOG=info # Respawn: restart after 5 s, give up after 5 consecutive failures within # a 3600 s window, then reset the failure counter and try again. procd_set_param respawn 3600 5 5 diff --git a/packaging/systemd/fips.service b/packaging/systemd/fips.service index 2c898cb..c58385f 100644 --- a/packaging/systemd/fips.service +++ b/packaging/systemd/fips.service @@ -9,9 +9,6 @@ ExecStart=/usr/local/bin/fips --config /etc/fips/fips.yaml Restart=on-failure RestartSec=5 -# Logging: RUST_LOG controls verbosity. -Environment=RUST_LOG=info - # Control socket directory (/run/fips/). # Group-accessible so 'fips' group members can use fipsctl/fipstop. RuntimeDirectory=fips diff --git a/src/bin/fips.rs b/src/bin/fips.rs index 642ff9f..76d59af 100644 --- a/src/bin/fips.rs +++ b/src/bin/fips.rs @@ -7,7 +7,7 @@ use fips::config::{resolve_identity, IdentitySource}; use fips::version; use fips::{Config, Node}; use std::path::PathBuf; -use tracing::{debug, error, info, warn, Level}; +use tracing::{debug, error, info, warn}; use tracing_subscriber::{fmt, EnvFilter}; /// FIPS mesh network daemon @@ -26,9 +26,32 @@ struct Args { #[tokio::main(flavor = "current_thread")] async fn main() { - // Initialize logging + let args = Args::parse(); + + // Load configuration before initializing logging so we can use + // the config's log_level as the tracing filter default. + let (config, loaded_paths) = if let Some(config_path) = &args.config { + match Config::load_file(config_path) { + Ok(config) => (config, vec![config_path.clone()]), + Err(e) => { + eprintln!("Failed to load configuration from {}: {}", config_path.display(), e); + std::process::exit(1); + } + } + } else { + match Config::load() { + Ok(result) => result, + Err(e) => { + eprintln!("Failed to load configuration: {}", e); + std::process::exit(1); + } + } + }; + + // Initialize logging: RUST_LOG env var overrides config if set + let log_level = config.node.log_level(); let filter = EnvFilter::builder() - .with_default_directive(Level::INFO.into()) + .with_default_directive(log_level.into()) .from_env_lossy(); fmt() @@ -36,32 +59,8 @@ async fn main() { .with_target(true) .init(); - let args = Args::parse(); - info!("FIPS {} starting", version::short_version()); - // Load configuration - debug!("Loading configuration"); - let (config, loaded_paths) = if let Some(config_path) = &args.config { - // Explicit config file specified - load only that file - match Config::load_file(config_path) { - Ok(config) => (config, vec![config_path.clone()]), - Err(e) => { - error!("Failed to load configuration from {}: {}", config_path.display(), e); - std::process::exit(1); - } - } - } else { - // Use default search paths - match Config::load() { - Ok(result) => result, - Err(e) => { - error!("Failed to load configuration: {}", e); - std::process::exit(1); - } - } - }; - if loaded_paths.is_empty() { info!("No config files found, using defaults"); } else { diff --git a/src/config/node.rs b/src/config/node.rs index 07edd12..4367177 100644 --- a/src/config/node.rs +++ b/src/config/node.rs @@ -612,6 +612,11 @@ pub struct NodeConfig { /// Rekey / session rekeying (`node.rekey.*`). #[serde(default)] pub rekey: RekeyConfig, + + /// Log level (`node.log_level`). Case-insensitive. + /// Valid values: trace, debug, info, warn, error. Default: info. + #[serde(default)] + pub log_level: Option, } impl Default for NodeConfig { @@ -637,11 +642,23 @@ impl Default for NodeConfig { session_mmp: SessionMmpConfig::default(), ecn: EcnConfig::default(), rekey: RekeyConfig::default(), + log_level: None, } } } impl NodeConfig { + /// Get the log level as a tracing Level. Default: INFO. + pub fn log_level(&self) -> tracing::Level { + match self.log_level.as_deref().map(|s| s.to_lowercase()).as_deref() { + Some("trace") => tracing::Level::TRACE, + Some("debug") => tracing::Level::DEBUG, + Some("warn") | Some("warning") => tracing::Level::WARN, + Some("error") => tracing::Level::ERROR, + _ => tracing::Level::INFO, + } + } + fn default_tick_interval_secs() -> u64 { 1 } fn default_base_rtt_ms() -> u64 { 100 } fn default_heartbeat_interval_secs() -> u64 { 10 }