zlog: Add env var to enable line number logging (#41905)

Lukas Wirth created

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/gpui/src/executor.rs |  2 +-
crates/util/src/util.rs     | 16 ++++++++++------
crates/zlog/src/sink.rs     | 15 ++++++++++++++-
crates/zlog/src/zlog.rs     |  7 +++++--
4 files changed, 30 insertions(+), 10 deletions(-)

Detailed changes

crates/gpui/src/executor.rs 🔗

@@ -281,7 +281,7 @@ impl BackgroundExecutor {
         });
         let mut cx = std::task::Context::from_waker(&waker);
 
-        let duration = Duration::from_secs(500);
+        let duration = Duration::from_secs(180);
         let mut test_should_end_by = Instant::now() + duration;
 
         loop {

crates/util/src/util.rs 🔗

@@ -611,17 +611,21 @@ where
     let file = caller.file().replace('\\', "/");
     // In this codebase all crates reside in a `crates` directory,
     // so discard the prefix up to that segment to find the crate name
-    let target = file
-        .split_once("crates/")
-        .and_then(|(_, s)| s.split_once("/src/"));
+    let file = file.split_once("crates/");
+    let target = file.as_ref().and_then(|(_, s)| s.split_once("/src/"));
 
     let module_path = target.map(|(krate, module)| {
-        krate.to_owned() + "::" + &module.trim_end_matches(".rs").replace('/', "::")
+        if module.starts_with(krate) {
+            module.trim_end_matches(".rs").replace('/', "::")
+        } else {
+            krate.to_owned() + "::" + &module.trim_end_matches(".rs").replace('/', "::")
+        }
     });
+    let file = file.map(|(_, file)| format!("crates/{file}"));
     log::logger().log(
         &log::Record::builder()
-            .target(target.map_or("", |(krate, _)| krate))
-            .module_path(module_path.as_deref())
+            .target(module_path.as_deref().unwrap_or(""))
+            .module_path(file.as_deref())
             .args(format_args!("{:?}", error))
             .file(Some(caller.file()))
             .line(Some(caller.line()))

crates/zlog/src/sink.rs 🔗

@@ -39,6 +39,7 @@ pub struct Record<'a> {
     pub level: log::Level,
     pub message: &'a std::fmt::Arguments<'a>,
     pub module_path: Option<&'a str>,
+    pub line: Option<u32>,
 }
 
 pub fn init_output_stdout() {
@@ -105,7 +106,11 @@ static LEVEL_ANSI_COLORS: [&str; 6] = [
 ];
 
 // PERF: batching
-pub fn submit(record: Record) {
+pub fn submit(mut record: Record) {
+    if record.module_path.is_none_or(|p| !p.ends_with(".rs")) {
+        // Only render line numbers for actual rust files emitted by `log_err` and friends
+        record.line.take();
+    }
     if ENABLED_SINKS_STDOUT.load(Ordering::Acquire) {
         let mut stdout = std::io::stdout().lock();
         _ = writeln!(
@@ -117,6 +122,7 @@ pub fn submit(record: Record) {
             SourceFmt {
                 scope: record.scope,
                 module_path: record.module_path,
+                line: record.line,
                 ansi: true,
             },
             record.message
@@ -132,6 +138,7 @@ pub fn submit(record: Record) {
             SourceFmt {
                 scope: record.scope,
                 module_path: record.module_path,
+                line: record.line,
                 ansi: true,
             },
             record.message
@@ -167,6 +174,7 @@ pub fn submit(record: Record) {
                 SourceFmt {
                     scope: record.scope,
                     module_path: record.module_path,
+                    line: record.line,
                     ansi: false,
                 },
                 record.message
@@ -202,6 +210,7 @@ pub fn flush() {
 struct SourceFmt<'a> {
     scope: Scope,
     module_path: Option<&'a str>,
+    line: Option<u32>,
     ansi: bool,
 }
 
@@ -225,6 +234,10 @@ impl std::fmt::Display for SourceFmt<'_> {
                 f.write_str(subscope)?;
             }
         }
+        if let Some(line) = self.line {
+            f.write_char(':')?;
+            line.fmt(f)?;
+        }
         if self.ansi {
             f.write_str(ANSI_RESET)?;
         }

crates/zlog/src/zlog.rs 🔗

@@ -80,7 +80,7 @@ impl log::Log for Zlog {
             None => (private::scope_new(&[]), private::scope_new(&["*unknown*"])),
         };
         let level = record.metadata().level();
-        if !filter::is_scope_enabled(&crate_name_scope, record.module_path(), level) {
+        if !filter::is_scope_enabled(&crate_name_scope, Some(record.target()), level) {
             return;
         }
         sink::submit(sink::Record {
@@ -89,6 +89,7 @@ impl log::Log for Zlog {
             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()),
+            line: record.line(),
         });
     }
 
@@ -109,6 +110,7 @@ macro_rules! log {
                 level,
                 message: &format_args!($($arg)+),
                 module_path: Some(module_path!()),
+                line: Some(line!()),
             });
         }
     }
@@ -291,7 +293,7 @@ impl log::Log for Logger {
             return;
         }
         let level = record.metadata().level();
-        if !filter::is_scope_enabled(&self.scope, record.module_path(), level) {
+        if !filter::is_scope_enabled(&self.scope, Some(record.target()), level) {
             return;
         }
         sink::submit(sink::Record {
@@ -299,6 +301,7 @@ impl log::Log for Logger {
             level,
             message: record.args(),
             module_path: record.module_path(),
+            line: record.line(),
         });
     }