From e3a2d52472b53b0fb44df75c66b63e6426b2fb7a Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Thu, 1 May 2025 10:59:51 -0400 Subject: [PATCH] zlog: Fall back to printing module path instead of `*unknown*` or just crate name (#29691) Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/zlog/src/sink.rs | 76 +++++++++++++++++++++++++++-------------- crates/zlog/src/zlog.rs | 4 +++ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/crates/zlog/src/sink.rs b/crates/zlog/src/sink.rs index edf2398a0e..4140fd1225 100644 --- a/crates/zlog/src/sink.rs +++ b/crates/zlog/src/sink.rs @@ -32,6 +32,13 @@ static SINK_FILE_SIZE_BYTES: AtomicU64 = AtomicU64::new(0); /// Maximum size of the log file before it will be rotated, in bytes. const SINK_FILE_SIZE_BYTES_MAX: u64 = 1024 * 1024; // 1 MB +pub struct Record<'a> { + pub scope: Scope, + pub level: log::Level, + pub message: &'a std::fmt::Arguments<'a>, + pub module_path: Option<&'a str>, +} + pub fn init_output_stdout() { unsafe { ENABLED_SINKS_STDOUT = true; @@ -91,20 +98,21 @@ static LEVEL_ANSI_COLORS: [&str; 6] = [ ANSI_MAGENTA, // Trace: Magenta ]; +// PERF: batching pub fn submit(record: Record) { if unsafe { ENABLED_SINKS_STDOUT } { let mut stdout = std::io::stdout().lock(); _ = writeln!( &mut stdout, - "{} {}{}{}{} {}[{}]{} {}", + "{} {ANSI_BOLD}{}{}{ANSI_RESET} {} {}", chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z"), - ANSI_BOLD, LEVEL_ANSI_COLORS[record.level as usize], LEVEL_OUTPUT_STRINGS[record.level as usize], - ANSI_RESET, - ANSI_BOLD, - ScopeFmt(record.scope), - ANSI_RESET, + SourceFmt { + scope: record.scope, + module_path: record.module_path, + ansi: true, + }, record.message ); } @@ -132,10 +140,14 @@ pub fn submit(record: Record) { let mut writer = SizedWriter { file, written: 0 }; _ = writeln!( &mut writer, - "{} {} [{}] {}", + "{} {} {} {}", chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z"), LEVEL_OUTPUT_STRINGS[record.level as usize], - ScopeFmt(record.scope), + SourceFmt { + scope: record.scope, + module_path: record.module_path, + ansi: false, + }, record.message ); SINK_FILE_SIZE_BYTES.fetch_add(writer.written, Ordering::Relaxed) + writer.written @@ -166,26 +178,38 @@ pub fn flush() { } } -struct ScopeFmt(Scope); - -impl std::fmt::Display for ScopeFmt { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use std::fmt::Write; - f.write_str(self.0[0])?; - for scope in &self.0[1..] { - if !scope.is_empty() { - f.write_char(SCOPE_STRING_SEP_CHAR)?; - } - f.write_str(scope)?; - } - Ok(()) - } +struct SourceFmt<'a> { + scope: Scope, + module_path: Option<&'a str>, + ansi: bool, } -pub struct Record<'a> { - pub scope: Scope, - pub level: log::Level, - pub message: &'a std::fmt::Arguments<'a>, +impl std::fmt::Display for SourceFmt<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use std::fmt::Write; + f.write_char('[')?; + if self.ansi { + f.write_str(ANSI_BOLD)?; + } + // NOTE: if no longer prefixing scopes with their crate name, check if scope[0] is empty + if (self.scope[1].is_empty() && self.module_path.is_some()) || self.scope[0].is_empty() { + f.write_str(self.module_path.unwrap_or("?"))?; + } else { + f.write_str(self.scope[0])?; + for subscope in &self.scope[1..] { + if subscope.is_empty() { + break; + } + f.write_char(SCOPE_STRING_SEP_CHAR)?; + f.write_str(subscope)?; + } + } + if self.ansi { + f.write_str(ANSI_RESET)?; + } + f.write_char(']')?; + Ok(()) + } } fn rotate_log_file( diff --git a/crates/zlog/src/zlog.rs b/crates/zlog/src/zlog.rs index a9383ec974..7ccff6ff8c 100644 --- a/crates/zlog/src/zlog.rs +++ b/crates/zlog/src/zlog.rs @@ -61,6 +61,8 @@ impl log::Log for Zlog { scope: module_scope, level, message: record.args(), + // PERF(batching): store non-static paths in a cache + leak them and pass static str here + module_path: record.module_path().or(record.file()), }); } @@ -80,6 +82,7 @@ macro_rules! log { scope: logger.scope, level, message: &format_args!($($arg)+), + module_path: Some(module_path!()), }); } } @@ -267,6 +270,7 @@ impl log::Log for Logger { scope: self.scope, level, message: record.args(), + module_path: record.module_path(), }); }