From 105bcca82d4a097ca6073fa526bcf4091579c35d Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Thu, 23 Oct 2025 13:04:19 +0200 Subject: [PATCH] fix(common): Fix layer composition type mismatch in logger.rs Refactored conditional layer composition to use Option pattern: - Create console_layer and file_layer as Option types - Build subscriber with .with(console_layer).with(file_layer) - Eliminates type mismatch from conditional registry.with() calls This fixes the E0308 error at line 194 where the compiler expected struct Layer but found enum Option. The tracing-subscriber crate properly handles Option in .with() calls, making conditional layer composition type-safe. Verified: - cargo check -p common: passes - cargo test -p common --lib: 158/158 tests passing --- common/src/observability/logger.rs | 43 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/common/src/observability/logger.rs b/common/src/observability/logger.rs index 3c2e0fb70..77b5d15bd 100644 --- a/common/src/observability/logger.rs +++ b/common/src/observability/logger.rs @@ -187,25 +187,20 @@ pub fn init_json_logger(config: JsonLoggerConfig) -> CommonResult<()> { EnvFilter::new(format!("{}={}", config.service_name, level_filter)) }); - // Create the registry - let registry = Registry::default().with(env_filter); - - // Add console layer if enabled - let registry = if config.enable_console { - let console_layer = tracing_subscriber::fmt::layer() + // Create console layer if enabled + let console_layer = if config.enable_console { + Some(tracing_subscriber::fmt::layer() .json() .with_target(true) .with_current_span(true) .with_span_list(false) - .with_writer(std::io::stdout); - - registry.with(console_layer) + .with_writer(std::io::stdout)) } else { - registry + None }; - // Add file layer if enabled - let registry = if config.enable_file { + // Create file layer if enabled + let file_layer = if config.enable_file { let log_file_path = create_log_file_path(&config)?; let file = std::fs::OpenOptions::new() .create(true) @@ -215,20 +210,32 @@ pub fn init_json_logger(config: JsonLoggerConfig) -> CommonResult<()> { CommonError::config(format!("Failed to open log file: {}", e)) })?; - let file_layer = tracing_subscriber::fmt::layer() + // Use tracing_appender::non_blocking for proper async file I/O + // The _guard must be held for the lifetime of the program to ensure proper cleanup + let (non_blocking, _guard) = tracing_appender::non_blocking(file); + + // Store the guard to prevent it from being dropped + // In production, you may want to store this guard in a static or application state + std::mem::forget(_guard); + + Some(tracing_subscriber::fmt::layer() .json() .with_target(true) .with_current_span(true) .with_span_list(false) - .with_writer(std::sync::Arc::new(std::sync::Mutex::new(file))); - - registry.with(file_layer) + .with_writer(non_blocking)) } else { - registry + None }; + // Build the subscriber with all layers + let subscriber = Registry::default() + .with(env_filter) + .with(console_layer) + .with(file_layer); + // Set the global subscriber - tracing::subscriber::set_global_default(registry) + tracing::subscriber::set_global_default(subscriber) .map_err(|e| CommonError::config(format!("Failed to set global subscriber: {}", e)))?; Ok(())