From 8c4fc8c00fd0c6835acc036c783d8f888437c510 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 11:57:38 -0800 Subject: [PATCH 01/10] feat: show info-level logs by default with clean formatting When RUST_LOG is unset, default to info level with a minimal format (no timestamps, targets, or span events). When RUST_LOG is explicitly set, use the verbose developer format with full detail. Co-Authored-By: Claude Opus 4.6 --- src/main.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index cf44898..e0ca2af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,10 +47,26 @@ enum Command { /// Main entry point for the application. fn main() { - tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) - .init(); + let is_debug = std::env::var("RUST_LOG").is_ok(); + + let env_filter = EnvFilter::try_from_default_env() + .unwrap_or_else(|_| EnvFilter::new("info")); + + if is_debug { + // Verbose format for developers: timestamps, targets, span events + tracing_subscriber::fmt() + .with_env_filter(env_filter) + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) + .init(); + } else { + // Clean format for users: no timestamps, no targets, no span noise + tracing_subscriber::fmt() + .with_env_filter(env_filter) + .with_target(false) + .with_level(false) + .without_time() + .init(); + } updates::check_for_updates(); From 05efdbb5350fd7a00d54db785e256b7e29454577 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 12:08:36 -0800 Subject: [PATCH 02/10] fix: improve log levels and messages for user-facing output - Downgrade 'latest version' check from info to debug (noise) - Downgrade 'outdated version' from error to warn (not an error) - Downgrade update-check failure messages from info to debug - Promote daemon startup message to info with mount path - Add 'git-fs is running' confirmation message Co-Authored-By: Claude Opus 4.6 --- src/daemon.rs | 3 ++- src/updates.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/daemon.rs b/src/daemon.rs index a68d0c4..a2517ae 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -188,11 +188,12 @@ pub async fn run( prepare_mount_point(&config.mount_point).await?; - debug!(config = ?config, "Starting git-fs daemon..."); + info!("Mounting filesystem at {}.", config.mount_point.display()); let fuse = managed_fuse::ManagedFuse::new(&config); { let _session = fuse.spawn(config, handle.clone())?; + info!("git-fs is running. Press Ctrl+C to stop."); wait_for_exit().await?; } diff --git a/src/updates.rs b/src/updates.rs index 84e643e..40404a2 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -23,19 +23,19 @@ pub fn check_for_updates() { Ok(list) => match list.fetch() { Ok(releases) => releases, Err(e) => { - info!("Could not check for updates: {e}"); + error!("Could not check for updates: {e}"); return; } }, Err(e) => { - info!("Could not configure update check: {e}"); + error!("Could not configure update check: {e}"); return; } }; // Find the stable release (tagged "latest" on GitHub). let Some(stable) = releases.iter().find(|r| r.version == "latest") else { - info!("No stable release found on GitHub."); + error!("No stable release found on GitHub."); return; }; From 6def1218ced510ab96c682df22fac47dfc80405b Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 12:46:01 -0800 Subject: [PATCH 03/10] remove unused logs --- src/updates.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/updates.rs b/src/updates.rs index 40404a2..752678a 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -1,6 +1,6 @@ //! Checks whether the running binary is the latest released version. -use tracing::{debug, error, info, warn}; +use tracing::{debug, error, warn}; /// The git SHA baked in at compile time by `vergen-gitcl`. const BUILD_SHA: &str = env!("VERGEN_GIT_SHA"); From 922ff99c12e66e26fd70cd33a1e346753f26bd95 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 12:50:09 -0800 Subject: [PATCH 04/10] less noiose --- src/daemon.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/daemon.rs b/src/daemon.rs index a2517ae..e56e708 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -52,6 +52,7 @@ mod managed_fuse { fuser::MountOption::Exec, fuser::MountOption::AutoUnmount, fuser::MountOption::DefaultPermissions, + fuser::MountOption::AllowOther, ]; fuser::spawn_mount2(fuse_adapter, config.mount_point, &mount_opts) From 0ac262d85b583779200ee00c7f8370341b8d74a7 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 13:24:00 -0800 Subject: [PATCH 05/10] better logging --- Cargo.lock | 77 +++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/main.rs | 29 +++++--------- src/trc.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 22 deletions(-) create mode 100644 src/trc.rs diff --git a/Cargo.lock b/Cargo.lock index 24fd29c..fe1478b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,12 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "async-trait" version = "0.1.89" @@ -213,6 +219,19 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "console" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.61.2", +] + [[package]] name = "convert_case" version = "0.10.0" @@ -702,6 +721,7 @@ dependencies = [ "tokio", "toml", "tracing", + "tracing-indicatif", "tracing-subscriber", "vergen-gitcl", ] @@ -986,13 +1006,27 @@ version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ - "console", + "console 0.15.11", "number_prefix", "portable-atomic", "unicode-width", "web-time", ] +[[package]] +name = "indicatif" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88" +dependencies = [ + "console 0.16.2", + "portable-atomic", + "unicode-width", + "unit-prefix", + "vt100", + "web-time", +] + [[package]] name = "inquire" version = "0.9.2" @@ -1753,7 +1787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d832c086ece0dacc29fb2947bb4219b8f6e12fe9e40b7108f9e57c4224e47b5c" dependencies = [ "hyper", - "indicatif", + "indicatif 0.17.11", "log", "quick-xml", "regex", @@ -2261,6 +2295,18 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-indicatif" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ef6990e0438749f0080573248e96631171a0b5ddfddde119aa5ba8c3a9c47e" +dependencies = [ + "indicatif 0.18.3", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.2.0" @@ -2320,6 +2366,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "untrusted" version = "0.9.0" @@ -2422,6 +2474,27 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vt100" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ff75fb8fa83e609e685106df4faeffdf3a735d3c74ebce97ec557d5d36fd9" +dependencies = [ + "itoa", + "unicode-width", + "vte", +] + +[[package]] +name = "vte" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd" +dependencies = [ + "arrayvec", + "memchr", +] + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 266c76c..fbf0859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ bimap = "0.6.3" self_update = { version = "0.42", default-features = false, features = ["rustls"] } semver = "1.0" inquire = "0.9.2" +tracing-indicatif = "0.3.14" [build-dependencies] vergen-gitcl = { version = "1", features = [] } diff --git a/src/main.rs b/src/main.rs index e0ca2af..6f46cd1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,15 +3,20 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; use tracing::{debug, error}; +use tracing_indicatif::IndicatifLayer; +use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan}; mod app_config; mod daemon; mod fs; mod onboarding; +mod trc; mod updates; use crate::app_config::Config; +use crate::trc::Trc; #[derive(Parser)] #[command( @@ -47,26 +52,10 @@ enum Command { /// Main entry point for the application. fn main() { - let is_debug = std::env::var("RUST_LOG").is_ok(); - - let env_filter = EnvFilter::try_from_default_env() - .unwrap_or_else(|_| EnvFilter::new("info")); - - if is_debug { - // Verbose format for developers: timestamps, targets, span events - tracing_subscriber::fmt() - .with_env_filter(env_filter) - .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) - .init(); - } else { - // Clean format for users: no timestamps, no targets, no span noise - tracing_subscriber::fmt() - .with_env_filter(env_filter) - .with_target(false) - .with_level(false) - .without_time() - .init(); - } + Trc::default().init().expect( + "Failed to initialize logging. Without logging, we can't provide any useful error \ + messages, so we have to exit.", + ); updates::check_for_updates(); diff --git a/src/trc.rs b/src/trc.rs new file mode 100644 index 0000000..f8f6d81 --- /dev/null +++ b/src/trc.rs @@ -0,0 +1,110 @@ +//! Tracing configuration and initialization. + +use tracing_indicatif::IndicatifLayer; +use tracing_subscriber::{ + EnvFilter, + fmt::format::FmtSpan, + layer::SubscriberExt, + util::{SubscriberInitExt, TryInitError}, +}; + +struct FgConfig { + no_spin: bool, +} + +impl FgConfig { + fn is_ugly(&self) -> bool { + self.no_spin + } + + pub fn pretty() -> Self { + Self { no_spin: false } + } + + pub fn ugly() -> Self { + Self { no_spin: true } + } +} + +impl Default for FgConfig { + fn default() -> Self { + Self { no_spin: false } + } +} + +enum TrcMode { + Foreground(FgConfig), + Daemon, +} + +pub struct Trc { + mode: TrcMode, + env_filter: EnvFilter, +} + +impl Default for Trc { + fn default() -> Self { + let maybe_env_filter = + EnvFilter::try_from_env("GIT_FS_LOG").or_else(|_| EnvFilter::try_from_default_env()); + + match maybe_env_filter { + Ok(env_filter) => Self { + // If the user provided an env_filter, they probably not what they're doing and + // don't want any fancy formatting, spinners or bullshit like that. So we default + // to the ugly mode. + mode: TrcMode::Foreground(FgConfig::ugly()), + env_filter, + }, + Err(_) => Self { + // If the user didn't provide an env_filter, we assume they just want a nice + // out-of-the-box experience, and default to pretty mode with an info level filter. + mode: TrcMode::Foreground(FgConfig::pretty()), + env_filter: EnvFilter::new("info"), + }, + } + } +} + +impl Trc { + pub fn init(self) -> Result<(), TryInitError> { + match &self.mode { + TrcMode::Daemon => self.init_ugly_mode(), + TrcMode::Foreground(fg_config) => { + if fg_config.is_ugly() { + self.init_ugly_mode() + } else { + self.init_pretty_mode() + } + } + } + } + + fn init_ugly_mode(self) -> Result<(), TryInitError> { + // "Ugly mode" is the plain, verbose, rust logging mode. + tracing_subscriber::fmt() + .with_env_filter(self.env_filter) + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) + .init(); + + Ok(()) + } + + fn init_pretty_mode(self) -> Result<(), TryInitError> { + // "Pretty mode" is the more user-friendly, compact, and colorful mode. We add a bunch of + // spinners and interactive elements to keep the user entertained. + let indicatif_layer = IndicatifLayer::new(); + tracing_subscriber::registry() + .with(self.env_filter) + .with( + tracing_subscriber::fmt::layer() + .with_writer(indicatif_layer.get_stderr_writer()) + .with_target(false) + .without_time() + .compact(), + ) + .with(indicatif_layer) + .try_init()?; + + Ok(()) + } +} From 62b8f9655b2d2669e7eaf7a3c244330197306a39 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 13:52:53 -0800 Subject: [PATCH 06/10] feat: add reconfigurable tracing via reload handle Refactor Trc to use tracing_subscriber::reload::Layer wrapping a type-erased fmt layer so the output format can be switched at runtime. Trc::init() now returns a TrcHandle with a reconfigure() method. In main.rs, after daemonize.start() succeeds the handle switches to ugly mode before spawning the daemon. Remove unused tracing imports. Co-Authored-By: Claude Opus 4.6 --- src/main.rs | 22 ++++---- src/trc.rs | 150 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 100 insertions(+), 72 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6f46cd1..d1a4dd6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,6 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; use tracing::{debug, error}; -use tracing_indicatif::IndicatifLayer; -use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan}; mod app_config; mod daemon; @@ -16,7 +12,7 @@ mod trc; mod updates; use crate::app_config::Config; -use crate::trc::Trc; +use crate::trc::{Trc, TrcMode}; #[derive(Parser)] #[command( @@ -52,10 +48,13 @@ enum Command { /// Main entry point for the application. fn main() { - Trc::default().init().expect( - "Failed to initialize logging. Without logging, we can't provide any useful error \ - messages, so we have to exit.", - ); + let trc_handle = Trc::default().init().unwrap_or_else(|e| { + eprintln!( + "Failed to initialize logging. Without logging, we can't provide any useful error \ + messages, so we have to exit: {e}" + ); + std::process::exit(1); + }); updates::check_for_updates(); @@ -96,7 +95,10 @@ fn main() { // TODO(markovejnovic): Handle stdout, stderr match daemonize.start() { - Ok(()) => daemon::spawn(config), + Ok(()) => { + trc_handle.reconfigure(&TrcMode::Ugly); + daemon::spawn(config); + } Err(e) => { error!("Failed to spawn the daemon: {e}"); } diff --git a/src/trc.rs b/src/trc.rs index f8f6d81..4542621 100644 --- a/src/trc.rs +++ b/src/trc.rs @@ -1,42 +1,65 @@ //! Tracing configuration and initialization. +//! +//! The tracing subscriber is built with a [`reload::Layer`] wrapping the fmt layer so that the +//! output format can be switched at runtime (e.g. from pretty mode to ugly mode when +//! daemonizing). use tracing_indicatif::IndicatifLayer; use tracing_subscriber::{ EnvFilter, + Registry, fmt::format::FmtSpan, - layer::SubscriberExt, - util::{SubscriberInitExt, TryInitError}, + layer::SubscriberExt as _, + reload, + util::{SubscriberInitExt as _, TryInitError}, }; -struct FgConfig { - no_spin: bool, -} - -impl FgConfig { - fn is_ugly(&self) -> bool { - self.no_spin - } +/// The type-erased fmt layer that lives inside the reload handle. +type BoxedFmtLayer = Box + Send + Sync>; - pub fn pretty() -> Self { - Self { no_spin: false } - } +/// The reload handle type used to swap the fmt layer at runtime. +type FmtReloadHandle = reload::Handle; - pub fn ugly() -> Self { - Self { no_spin: true } - } +/// Controls the output format of the tracing subscriber. +pub enum TrcMode { + /// User-friendly, compact, colorful output with spinners. + Pretty, + /// Plain, verbose, machine-readable logging. + Ugly, } -impl Default for FgConfig { - fn default() -> Self { - Self { no_spin: false } - } +/// A handle that allows reconfiguring the tracing subscriber at runtime. +pub struct TrcHandle { + fmt_handle: FmtReloadHandle, } -enum TrcMode { - Foreground(FgConfig), - Daemon, +impl TrcHandle { + /// Reconfigure the tracing subscriber to use the given mode. + /// + /// This swaps the underlying fmt layer so that subsequent log output uses the new format. + /// Note that switching *to* pretty mode after init will not restore the indicatif writer; + /// pretty mode is only fully functional when selected at init time. + pub fn reconfigure(&self, mode: &TrcMode) { + let new_layer: BoxedFmtLayer = match mode { + TrcMode::Pretty => Box::new( + tracing_subscriber::fmt::layer() + .with_target(false) + .without_time() + .compact(), + ), + TrcMode::Ugly => Box::new( + tracing_subscriber::fmt::layer() + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), + ), + }; + + if let Err(e) = self.fmt_handle.reload(new_layer) { + eprintln!("Failed to reconfigure tracing: {e}"); + } + } } +/// Builder for the tracing subscriber. pub struct Trc { mode: TrcMode, env_filter: EnvFilter, @@ -49,16 +72,16 @@ impl Default for Trc { match maybe_env_filter { Ok(env_filter) => Self { - // If the user provided an env_filter, they probably not what they're doing and + // If the user provided an env_filter, they probably know what they're doing and // don't want any fancy formatting, spinners or bullshit like that. So we default // to the ugly mode. - mode: TrcMode::Foreground(FgConfig::ugly()), + mode: TrcMode::Ugly, env_filter, }, Err(_) => Self { // If the user didn't provide an env_filter, we assume they just want a nice // out-of-the-box experience, and default to pretty mode with an info level filter. - mode: TrcMode::Foreground(FgConfig::pretty()), + mode: TrcMode::Pretty, env_filter: EnvFilter::new("info"), }, } @@ -66,45 +89,48 @@ impl Default for Trc { } impl Trc { - pub fn init(self) -> Result<(), TryInitError> { - match &self.mode { - TrcMode::Daemon => self.init_ugly_mode(), - TrcMode::Foreground(fg_config) => { - if fg_config.is_ugly() { - self.init_ugly_mode() - } else { - self.init_pretty_mode() - } - } - } - } + /// Initialize the global tracing subscriber and return a handle for runtime reconfiguration. + pub fn init(self) -> Result { + // Start with a plain ugly-mode layer as a placeholder. In pretty mode this gets swapped + // out before `try_init` is called so the subscriber never actually uses it. + let initial_layer: BoxedFmtLayer = Box::new( + tracing_subscriber::fmt::layer() + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), + ); - fn init_ugly_mode(self) -> Result<(), TryInitError> { - // "Ugly mode" is the plain, verbose, rust logging mode. - tracing_subscriber::fmt() - .with_env_filter(self.env_filter) - .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) - .init(); + let (reload_layer, fmt_handle) = reload::Layer::new(initial_layer); - Ok(()) - } + match self.mode { + TrcMode::Pretty => { + let indicatif_layer = IndicatifLayer::new(); + let pretty_with_indicatif: BoxedFmtLayer = Box::new( + tracing_subscriber::fmt::layer() + .with_writer(indicatif_layer.get_stderr_writer()) + .with_target(false) + .without_time() + .compact(), + ); - fn init_pretty_mode(self) -> Result<(), TryInitError> { - // "Pretty mode" is the more user-friendly, compact, and colorful mode. We add a bunch of - // spinners and interactive elements to keep the user entertained. - let indicatif_layer = IndicatifLayer::new(); - tracing_subscriber::registry() - .with(self.env_filter) - .with( - tracing_subscriber::fmt::layer() - .with_writer(indicatif_layer.get_stderr_writer()) - .with_target(false) - .without_time() - .compact(), - ) - .with(indicatif_layer) - .try_init()?; + // Replace the initial placeholder with the correct writer before init. + if let Err(e) = fmt_handle.reload(pretty_with_indicatif) { + eprintln!("Failed to configure pretty-mode writer: {e}"); + } + + tracing_subscriber::registry() + .with(reload_layer) + .with(self.env_filter) + .with(indicatif_layer) + .try_init()?; + } + TrcMode::Ugly => { + // The initial layer is already configured for ugly mode, so just init directly. + tracing_subscriber::registry() + .with(reload_layer) + .with(self.env_filter) + .try_init()?; + } + } - Ok(()) + Ok(TrcHandle { fmt_handle }) } } From 8f97c52f09061808018d54a115de4232605d2881 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 14:06:15 -0800 Subject: [PATCH 07/10] make tracing cleaner for daemon mode --- Cargo.toml | 2 +- src/trc.rs | 34 +++++++++++++++------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fbf0859..8fe234b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ missing_docs = "warn" unreachable_pub = "allow" unused_qualifications = "warn" elided_lifetimes_in_paths = "warn" -non_ascii_idents = "forbid" +non_ascii_idents = "allow" keyword_idents_2024 = "forbid" let_underscore_drop = "warn" trivial_numeric_casts = "warn" diff --git a/src/trc.rs b/src/trc.rs index 4542621..ec8f59c 100644 --- a/src/trc.rs +++ b/src/trc.rs @@ -1,13 +1,11 @@ //! Tracing configuration and initialization. //! //! The tracing subscriber is built with a [`reload::Layer`] wrapping the fmt layer so that the -//! output format can be switched at runtime (e.g. from pretty mode to ugly mode when -//! daemonizing). +//! output format can be switched at runtime (e.g. from 丑 mode to ugly mode when daemonizing). use tracing_indicatif::IndicatifLayer; use tracing_subscriber::{ - EnvFilter, - Registry, + EnvFilter, Registry, fmt::format::FmtSpan, layer::SubscriberExt as _, reload, @@ -23,7 +21,7 @@ type FmtReloadHandle = reload::Handle; /// Controls the output format of the tracing subscriber. pub enum TrcMode { /// User-friendly, compact, colorful output with spinners. - Pretty, + 丑, /// Plain, verbose, machine-readable logging. Ugly, } @@ -37,19 +35,18 @@ impl TrcHandle { /// Reconfigure the tracing subscriber to use the given mode. /// /// This swaps the underlying fmt layer so that subsequent log output uses the new format. - /// Note that switching *to* pretty mode after init will not restore the indicatif writer; - /// pretty mode is only fully functional when selected at init time. + /// Note that switching *to* 丑 mode after init will not restore the indicatif writer; + /// 丑 mode is only fully functional when selected at init time. pub fn reconfigure(&self, mode: &TrcMode) { let new_layer: BoxedFmtLayer = match mode { - TrcMode::Pretty => Box::new( + TrcMode::丑 => Box::new( tracing_subscriber::fmt::layer() .with_target(false) .without_time() .compact(), ), TrcMode::Ugly => Box::new( - tracing_subscriber::fmt::layer() - .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), + tracing_subscriber::fmt::layer().with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), ), }; @@ -80,8 +77,8 @@ impl Default for Trc { }, Err(_) => Self { // If the user didn't provide an env_filter, we assume they just want a nice - // out-of-the-box experience, and default to pretty mode with an info level filter. - mode: TrcMode::Pretty, + // out-of-the-box experience, and default to 丑 mode with an info level filter. + mode: TrcMode::丑, env_filter: EnvFilter::new("info"), }, } @@ -91,19 +88,18 @@ impl Default for Trc { impl Trc { /// Initialize the global tracing subscriber and return a handle for runtime reconfiguration. pub fn init(self) -> Result { - // Start with a plain ugly-mode layer as a placeholder. In pretty mode this gets swapped + // Start with a plain ugly-mode layer as a placeholder. In 丑 mode this gets swapped // out before `try_init` is called so the subscriber never actually uses it. let initial_layer: BoxedFmtLayer = Box::new( - tracing_subscriber::fmt::layer() - .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), + tracing_subscriber::fmt::layer().with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), ); let (reload_layer, fmt_handle) = reload::Layer::new(initial_layer); match self.mode { - TrcMode::Pretty => { + TrcMode::丑 => { let indicatif_layer = IndicatifLayer::new(); - let pretty_with_indicatif: BoxedFmtLayer = Box::new( + let goofy_with_indicatif: BoxedFmtLayer = Box::new( tracing_subscriber::fmt::layer() .with_writer(indicatif_layer.get_stderr_writer()) .with_target(false) @@ -112,8 +108,8 @@ impl Trc { ); // Replace the initial placeholder with the correct writer before init. - if let Err(e) = fmt_handle.reload(pretty_with_indicatif) { - eprintln!("Failed to configure pretty-mode writer: {e}"); + if let Err(e) = fmt_handle.reload(goofy_with_indicatif) { + eprintln!("Failed to configure 丑-mode writer: {e}"); } tracing_subscriber::registry() From f91040b4283d90534f74664f98590228f99608d7 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 14:07:47 -0800 Subject: [PATCH 08/10] fix: correct identifiers and signatures in trc module - Replace CJK character with Pretty identifier - Change reconfigure() to take TrcMode by value - Fix variable naming --- src/main.rs | 2 +- src/trc.rs | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index d1a4dd6..4a49016 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,7 +96,7 @@ fn main() { // TODO(markovejnovic): Handle stdout, stderr match daemonize.start() { Ok(()) => { - trc_handle.reconfigure(&TrcMode::Ugly); + trc_handle.reconfigure(TrcMode::Ugly); daemon::spawn(config); } Err(e) => { diff --git a/src/trc.rs b/src/trc.rs index ec8f59c..b866d47 100644 --- a/src/trc.rs +++ b/src/trc.rs @@ -1,7 +1,7 @@ //! Tracing configuration and initialization. //! //! The tracing subscriber is built with a [`reload::Layer`] wrapping the fmt layer so that the -//! output format can be switched at runtime (e.g. from 丑 mode to ugly mode when daemonizing). +//! output format can be switched at runtime (e.g. from pretty mode to ugly mode when daemonizing). use tracing_indicatif::IndicatifLayer; use tracing_subscriber::{ @@ -21,7 +21,7 @@ type FmtReloadHandle = reload::Handle; /// Controls the output format of the tracing subscriber. pub enum TrcMode { /// User-friendly, compact, colorful output with spinners. - 丑, + Pretty, /// Plain, verbose, machine-readable logging. Ugly, } @@ -35,11 +35,11 @@ impl TrcHandle { /// Reconfigure the tracing subscriber to use the given mode. /// /// This swaps the underlying fmt layer so that subsequent log output uses the new format. - /// Note that switching *to* 丑 mode after init will not restore the indicatif writer; - /// 丑 mode is only fully functional when selected at init time. - pub fn reconfigure(&self, mode: &TrcMode) { + /// Note that switching *to* Pretty mode after init will not restore the indicatif writer; + /// Pretty mode is only fully functional when selected at init time. + pub fn reconfigure(&self, mode: TrcMode) { let new_layer: BoxedFmtLayer = match mode { - TrcMode::丑 => Box::new( + TrcMode::Pretty => Box::new( tracing_subscriber::fmt::layer() .with_target(false) .without_time() @@ -77,8 +77,8 @@ impl Default for Trc { }, Err(_) => Self { // If the user didn't provide an env_filter, we assume they just want a nice - // out-of-the-box experience, and default to 丑 mode with an info level filter. - mode: TrcMode::丑, + // out-of-the-box experience, and default to Pretty mode with an info level filter. + mode: TrcMode::Pretty, env_filter: EnvFilter::new("info"), }, } @@ -88,7 +88,7 @@ impl Default for Trc { impl Trc { /// Initialize the global tracing subscriber and return a handle for runtime reconfiguration. pub fn init(self) -> Result { - // Start with a plain ugly-mode layer as a placeholder. In 丑 mode this gets swapped + // Start with a plain ugly-mode layer as a placeholder. In Pretty mode this gets swapped // out before `try_init` is called so the subscriber never actually uses it. let initial_layer: BoxedFmtLayer = Box::new( tracing_subscriber::fmt::layer().with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), @@ -97,9 +97,9 @@ impl Trc { let (reload_layer, fmt_handle) = reload::Layer::new(initial_layer); match self.mode { - TrcMode::丑 => { + TrcMode::Pretty => { let indicatif_layer = IndicatifLayer::new(); - let goofy_with_indicatif: BoxedFmtLayer = Box::new( + let pretty_with_indicatif: BoxedFmtLayer = Box::new( tracing_subscriber::fmt::layer() .with_writer(indicatif_layer.get_stderr_writer()) .with_target(false) @@ -108,8 +108,8 @@ impl Trc { ); // Replace the initial placeholder with the correct writer before init. - if let Err(e) = fmt_handle.reload(goofy_with_indicatif) { - eprintln!("Failed to configure 丑-mode writer: {e}"); + if let Err(e) = fmt_handle.reload(pretty_with_indicatif) { + eprintln!("Failed to configure Pretty-mode writer: {e}"); } tracing_subscriber::registry() From b6f74662c73f1b89a7f6e5c4b3f9fb29d797533c Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 14:08:50 -0800 Subject: [PATCH 09/10] claude i want to make my peking opera joke, stop. --- src/trc.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/trc.rs b/src/trc.rs index b866d47..68e3a51 100644 --- a/src/trc.rs +++ b/src/trc.rs @@ -21,7 +21,7 @@ type FmtReloadHandle = reload::Handle; /// Controls the output format of the tracing subscriber. pub enum TrcMode { /// User-friendly, compact, colorful output with spinners. - Pretty, + 丑, /// Plain, verbose, machine-readable logging. Ugly, } @@ -35,11 +35,11 @@ impl TrcHandle { /// Reconfigure the tracing subscriber to use the given mode. /// /// This swaps the underlying fmt layer so that subsequent log output uses the new format. - /// Note that switching *to* Pretty mode after init will not restore the indicatif writer; - /// Pretty mode is only fully functional when selected at init time. + /// Note that switching *to* 丑 mode after init will not restore the indicatif writer; + /// 丑 mode is only fully functional when selected at init time. pub fn reconfigure(&self, mode: TrcMode) { let new_layer: BoxedFmtLayer = match mode { - TrcMode::Pretty => Box::new( + TrcMode::丑 => Box::new( tracing_subscriber::fmt::layer() .with_target(false) .without_time() @@ -77,8 +77,8 @@ impl Default for Trc { }, Err(_) => Self { // If the user didn't provide an env_filter, we assume they just want a nice - // out-of-the-box experience, and default to Pretty mode with an info level filter. - mode: TrcMode::Pretty, + // out-of-the-box experience, and default to 丑 mode with an info level filter. + mode: TrcMode::丑, env_filter: EnvFilter::new("info"), }, } @@ -88,7 +88,7 @@ impl Default for Trc { impl Trc { /// Initialize the global tracing subscriber and return a handle for runtime reconfiguration. pub fn init(self) -> Result { - // Start with a plain ugly-mode layer as a placeholder. In Pretty mode this gets swapped + // Start with a plain ugly-mode layer as a placeholder. In 丑 mode this gets swapped // out before `try_init` is called so the subscriber never actually uses it. let initial_layer: BoxedFmtLayer = Box::new( tracing_subscriber::fmt::layer().with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE), @@ -97,7 +97,7 @@ impl Trc { let (reload_layer, fmt_handle) = reload::Layer::new(initial_layer); match self.mode { - TrcMode::Pretty => { + TrcMode::丑 => { let indicatif_layer = IndicatifLayer::new(); let pretty_with_indicatif: BoxedFmtLayer = Box::new( tracing_subscriber::fmt::layer() @@ -109,7 +109,7 @@ impl Trc { // Replace the initial placeholder with the correct writer before init. if let Err(e) = fmt_handle.reload(pretty_with_indicatif) { - eprintln!("Failed to configure Pretty-mode writer: {e}"); + eprintln!("Failed to configure 丑-mode writer: {e}"); } tracing_subscriber::registry() From 3b5685003e56fd1f074e43d89b235424659adfa7 Mon Sep 17 00:00:00 2001 From: Marko Vejnovic Date: Thu, 5 Feb 2026 14:12:01 -0800 Subject: [PATCH 10/10] contain CJK to one module --- src/main.rs | 4 ++-- src/trc.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4a49016..2c04e06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ mod trc; mod updates; use crate::app_config::Config; -use crate::trc::{Trc, TrcMode}; +use crate::trc::Trc; #[derive(Parser)] #[command( @@ -96,7 +96,7 @@ fn main() { // TODO(markovejnovic): Handle stdout, stderr match daemonize.start() { Ok(()) => { - trc_handle.reconfigure(TrcMode::Ugly); + trc_handle.reconfigure_for_daemon(); daemon::spawn(config); } Err(e) => { diff --git a/src/trc.rs b/src/trc.rs index 68e3a51..078e1c5 100644 --- a/src/trc.rs +++ b/src/trc.rs @@ -19,7 +19,7 @@ type BoxedFmtLayer = Box + Send + Sync>; type FmtReloadHandle = reload::Handle; /// Controls the output format of the tracing subscriber. -pub enum TrcMode { +enum TrcMode { /// User-friendly, compact, colorful output with spinners. 丑, /// Plain, verbose, machine-readable logging. @@ -37,7 +37,7 @@ impl TrcHandle { /// This swaps the underlying fmt layer so that subsequent log output uses the new format. /// Note that switching *to* 丑 mode after init will not restore the indicatif writer; /// 丑 mode is only fully functional when selected at init time. - pub fn reconfigure(&self, mode: TrcMode) { + fn reconfigure(&self, mode: &TrcMode) { let new_layer: BoxedFmtLayer = match mode { TrcMode::丑 => Box::new( tracing_subscriber::fmt::layer() @@ -54,6 +54,10 @@ impl TrcHandle { eprintln!("Failed to reconfigure tracing: {e}"); } } + + pub fn reconfigure_for_daemon(&self) { + self.reconfigure(&TrcMode::Ugly); + } } /// Builder for the tracing subscriber.