about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2025-08-11 18:32:05 +0200
committerJakub Beránek <berykubik@gmail.com>2025-08-11 18:32:05 +0200
commit6f584bc21e9446faa982864b3eeb5e6b6dadccf7 (patch)
treeb0698f49aeb4ab3c8a4b796c8f3aed9ae37274fa
parenta0306bfa314ba328ddb22123fe021c0ca90a0dec (diff)
Print created location of executed commands
-rw-r--r--src/bootstrap/src/utils/tracing.rs77
1 files changed, 57 insertions, 20 deletions
diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs
index 8b9d6ca213c..428ba013c98 100644
--- a/src/bootstrap/src/utils/tracing.rs
+++ b/src/bootstrap/src/utils/tracing.rs
@@ -54,13 +54,17 @@ const COMMAND_SPAN_TARGET: &str = "COMMAND";
 #[cfg(feature = "tracing")]
 pub fn trace_cmd(command: &crate::BootstrapCommand) -> tracing::span::EnteredSpan {
     let fingerprint = command.fingerprint();
+    let location = command.get_created_location();
+    let location = format!("{}:{}", location.file(), location.line());
+
     tracing::span!(
         target: COMMAND_SPAN_TARGET,
         tracing::Level::TRACE,
         "cmd",
         cmd_name = fingerprint.program_name().to_string(),
         cmd = fingerprint.format_short_cmd(),
-        full_cmd = ?command
+        full_cmd = ?command,
+        location
     )
     .entered()
 }
@@ -269,33 +273,66 @@ mod inner {
                 }
             }
 
-            // We handle steps specially. We instrument them dynamically in `Builder::ensure`,
-            // and we want to have custom name for each step span. But tracing doesn't allow setting
-            // dynamic span names. So we detect step spans here and override their name.
-            if span.metadata().target() == STEP_SPAN_TARGET {
-                let name = field_values.and_then(|v| v.step_name.as_deref()).unwrap_or(span.name());
-                write!(writer, "{name}")?;
-
-                // There should be only one more field called `args`
-                if let Some(values) = field_values {
-                    let field = &values.fields[0];
-                    write!(writer, " {{{}}}", field.1)?;
-                }
-            } else {
-                write!(writer, "{}", span.name())?;
-                if let Some(values) = field_values.filter(|v| !v.fields.is_empty()) {
+            fn write_fields<'a, I: IntoIterator<Item = &'a (&'a str, String)>, W: Write>(
+                writer: &mut W,
+                iter: I,
+            ) -> std::io::Result<()> {
+                let items = iter.into_iter().collect::<Vec<_>>();
+                if !items.is_empty() {
                     write!(writer, " [")?;
-                    for (index, (name, value)) in values.fields.iter().enumerate() {
+                    for (index, (name, value)) in items.iter().enumerate() {
                         write!(writer, "{name} = {value}")?;
-                        if index < values.fields.len() - 1 {
+                        if index < items.len() - 1 {
                             write!(writer, ", ")?;
                         }
                     }
                     write!(writer, "]")?;
                 }
-            };
+                Ok(())
+            }
+
+            // We handle steps specially. We instrument them dynamically in `Builder::ensure`,
+            // and we want to have custom name for each step span. But tracing doesn't allow setting
+            // dynamic span names. So we detect step spans here and override their name.
+            match span.metadata().target() {
+                // Executed step
+                STEP_SPAN_TARGET => {
+                    let name =
+                        field_values.and_then(|v| v.step_name.as_deref()).unwrap_or(span.name());
+                    write!(writer, "{name}")?;
+
+                    // There should be only one more field called `args`
+                    if let Some(values) = field_values {
+                        let field = &values.fields[0];
+                        write!(writer, " {{{}}}", field.1)?;
+                    }
+                    write_location(writer, span.metadata())?;
+                }
+                // Executed command
+                COMMAND_SPAN_TARGET => {
+                    write!(writer, "{}", span.name())?;
+                    if let Some(values) = field_values {
+                        write_fields(
+                            writer,
+                            values.fields.iter().filter(|(name, _)| *name != "location"),
+                        )?;
+                        write!(
+                            writer,
+                            " ({})",
+                            values.fields.iter().find(|(name, _)| *name == "location").unwrap().1
+                        )?;
+                    }
+                }
+                // Other span
+                _ => {
+                    write!(writer, "{}", span.name())?;
+                    if let Some(values) = field_values {
+                        write_fields(writer, values.fields.iter())?;
+                    }
+                    write_location(writer, span.metadata())?;
+                }
+            }
 
-            write_location(writer, span.metadata())?;
             writeln!(writer)?;
             Ok(())
         }