Skip to content

Commit e05cc17

Browse files
authored
Unrolled build for #145490
Rollup merge of #145490 - Kobzol:bootstrap-io-tracing, r=jieyouxu Trace some basic I/O operations in bootstrap When working on removing the rmeta sysroot copies, it is quite difficult to figure out *why* was did a certain file appear in a given directory. This should help with that a bit. r? `@jieyouxu`
2 parents 16ad385 + abecf68 commit e05cc17

File tree

4 files changed

+91
-30
lines changed

4 files changed

+91
-30
lines changed

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,7 @@ impl Step for Assemble {
23302330
///
23312331
/// For a particular stage this will link the file listed in `stamp` into the
23322332
/// `sysroot_dst` provided.
2333+
#[track_caller]
23332334
pub fn add_to_sysroot(
23342335
builder: &Builder<'_>,
23352336
sysroot_dst: &Path,

src/bootstrap/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,7 @@ impl Build {
17431743
///
17441744
/// If `src` is a symlink, `src` will be resolved to the actual path
17451745
/// and copied to `dst` instead of the symlink itself.
1746+
#[track_caller]
17461747
pub fn resolve_symlink_and_copy(&self, src: &Path, dst: &Path) {
17471748
self.copy_link_internal(src, dst, true);
17481749
}
@@ -1751,6 +1752,7 @@ impl Build {
17511752
/// Attempts to use hard links if possible, falling back to copying.
17521753
/// You can neither rely on this being a copy nor it being a link,
17531754
/// so do not write to dst.
1755+
#[track_caller]
17541756
pub fn copy_link(&self, src: &Path, dst: &Path, file_type: FileType) {
17551757
self.copy_link_internal(src, dst, false);
17561758

@@ -1765,6 +1767,7 @@ impl Build {
17651767
}
17661768
}
17671769

1770+
#[track_caller]
17681771
fn copy_link_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
17691772
if self.config.dry_run() {
17701773
return;
@@ -1773,6 +1776,10 @@ impl Build {
17731776
if src == dst {
17741777
return;
17751778
}
1779+
1780+
#[cfg(feature = "tracing")]
1781+
let _span = trace_io!("file-copy-link", ?src, ?dst);
1782+
17761783
if let Err(e) = fs::remove_file(dst)
17771784
&& cfg!(windows)
17781785
&& e.kind() != io::ErrorKind::NotFound
@@ -1815,6 +1822,7 @@ impl Build {
18151822
/// Links the `src` directory recursively to `dst`. Both are assumed to exist
18161823
/// when this function is called.
18171824
/// Will attempt to use hard links if possible and fall back to copying.
1825+
#[track_caller]
18181826
pub fn cp_link_r(&self, src: &Path, dst: &Path) {
18191827
if self.config.dry_run() {
18201828
return;
@@ -1837,12 +1845,14 @@ impl Build {
18371845
/// Will attempt to use hard links if possible and fall back to copying.
18381846
/// Unwanted files or directories can be skipped
18391847
/// by returning `false` from the filter function.
1848+
#[track_caller]
18401849
pub fn cp_link_filtered(&self, src: &Path, dst: &Path, filter: &dyn Fn(&Path) -> bool) {
18411850
// Immediately recurse with an empty relative path
18421851
self.cp_link_filtered_recurse(src, dst, Path::new(""), filter)
18431852
}
18441853

18451854
// Inner function does the actual work
1855+
#[track_caller]
18461856
fn cp_link_filtered_recurse(
18471857
&self,
18481858
src: &Path,
@@ -1903,17 +1913,26 @@ impl Build {
19031913
t!(fs::read_to_string(path))
19041914
}
19051915

1916+
#[track_caller]
19061917
fn create_dir(&self, dir: &Path) {
19071918
if self.config.dry_run() {
19081919
return;
19091920
}
1921+
1922+
#[cfg(feature = "tracing")]
1923+
let _span = trace_io!("dir-create", ?dir);
1924+
19101925
t!(fs::create_dir_all(dir))
19111926
}
19121927

19131928
fn remove_dir(&self, dir: &Path) {
19141929
if self.config.dry_run() {
19151930
return;
19161931
}
1932+
1933+
#[cfg(feature = "tracing")]
1934+
let _span = trace_io!("dir-remove", ?dir);
1935+
19171936
t!(fs::remove_dir_all(dir))
19181937
}
19191938

src/bootstrap/src/utils/tracing.rs

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,37 @@ macro_rules! error {
4848
}
4949
}
5050

51+
#[cfg(feature = "tracing")]
52+
pub const IO_SPAN_TARGET: &str = "IO";
53+
54+
/// Create a tracing span around an I/O operation, if tracing is enabled.
55+
/// Note that at least one tracing value field has to be passed to this macro, otherwise it will not
56+
/// compile.
57+
#[macro_export]
58+
macro_rules! trace_io {
59+
($name:expr, $($args:tt)*) => {
60+
::tracing::trace_span!(
61+
target: $crate::utils::tracing::IO_SPAN_TARGET,
62+
$name,
63+
$($args)*,
64+
location = $crate::utils::tracing::format_location(*::std::panic::Location::caller())
65+
).entered()
66+
}
67+
}
68+
69+
#[cfg(feature = "tracing")]
70+
pub fn format_location(location: std::panic::Location<'static>) -> String {
71+
format!("{}:{}", location.file(), location.line())
72+
}
73+
5174
#[cfg(feature = "tracing")]
5275
const COMMAND_SPAN_TARGET: &str = "COMMAND";
5376

5477
#[cfg(feature = "tracing")]
5578
pub fn trace_cmd(command: &crate::BootstrapCommand) -> tracing::span::EnteredSpan {
5679
let fingerprint = command.fingerprint();
5780
let location = command.get_created_location();
58-
let location = format!("{}:{}", location.file(), location.line());
81+
let location = format_location(location);
5982

6083
tracing::span!(
6184
target: COMMAND_SPAN_TARGET,
@@ -84,6 +107,7 @@ mod inner {
84107
use std::fmt::Debug;
85108
use std::fs::File;
86109
use std::io::Write;
110+
use std::path::{Path, PathBuf};
87111
use std::sync::atomic::Ordering;
88112

89113
use chrono::{DateTime, Utc};
@@ -93,8 +117,8 @@ mod inner {
93117
use tracing_subscriber::registry::{LookupSpan, SpanRef};
94118
use tracing_subscriber::{EnvFilter, Layer};
95119

120+
use super::{COMMAND_SPAN_TARGET, IO_SPAN_TARGET};
96121
use crate::STEP_SPAN_TARGET;
97-
use crate::utils::tracing::COMMAND_SPAN_TARGET;
98122

99123
pub fn setup_tracing(env_name: &str) -> TracingGuard {
100124
let filter = EnvFilter::from_env(env_name);
@@ -291,6 +315,23 @@ mod inner {
291315
Ok(())
292316
}
293317

318+
// Write fields while treating the "location" field specially, and assuming that it
319+
// contains the source file location relevant to the span.
320+
let write_with_location = |writer: &mut W| -> std::io::Result<()> {
321+
if let Some(values) = field_values {
322+
write_fields(
323+
writer,
324+
values.fields.iter().filter(|(name, _)| *name != "location"),
325+
)?;
326+
let location =
327+
&values.fields.iter().find(|(name, _)| *name == "location").unwrap().1;
328+
let (filename, line) = location.rsplit_once(':').unwrap();
329+
let filename = shorten_filename(filename);
330+
write!(writer, " ({filename}:{line})",)?;
331+
}
332+
Ok(())
333+
};
334+
294335
// We handle steps specially. We instrument them dynamically in `Builder::ensure`,
295336
// and we want to have custom name for each step span. But tracing doesn't allow setting
296337
// dynamic span names. So we detect step spans here and override their name.
@@ -311,17 +352,11 @@ mod inner {
311352
// Executed command
312353
COMMAND_SPAN_TARGET => {
313354
write!(writer, "{}", span.name())?;
314-
if let Some(values) = field_values {
315-
write_fields(
316-
writer,
317-
values.fields.iter().filter(|(name, _)| *name != "location"),
318-
)?;
319-
write!(
320-
writer,
321-
" ({})",
322-
values.fields.iter().find(|(name, _)| *name == "location").unwrap().1
323-
)?;
324-
}
355+
write_with_location(writer)?;
356+
}
357+
IO_SPAN_TARGET => {
358+
write!(writer, "{}", span.name())?;
359+
write_with_location(writer)?;
325360
}
326361
// Other span
327362
_ => {
@@ -342,21 +377,10 @@ mod inner {
342377
writer: &mut W,
343378
metadata: &'static tracing::Metadata<'static>,
344379
) -> std::io::Result<()> {
345-
use std::path::{Path, PathBuf};
346-
347380
if let Some(filename) = metadata.file() {
348-
// Keep only the module name and file name to make it shorter
349-
let filename: PathBuf = Path::new(filename)
350-
.components()
351-
// Take last two path components
352-
.rev()
353-
.take(2)
354-
.collect::<Vec<_>>()
355-
.into_iter()
356-
.rev()
357-
.collect();
358-
359-
write!(writer, " ({}", filename.display())?;
381+
let filename = shorten_filename(filename);
382+
383+
write!(writer, " ({filename}")?;
360384
if let Some(line) = metadata.line() {
361385
write!(writer, ":{line}")?;
362386
}
@@ -365,6 +389,21 @@ mod inner {
365389
Ok(())
366390
}
367391

392+
/// Keep only the module name and file name to make it shorter
393+
fn shorten_filename(filename: &str) -> String {
394+
Path::new(filename)
395+
.components()
396+
// Take last two path components
397+
.rev()
398+
.take(2)
399+
.collect::<Vec<_>>()
400+
.into_iter()
401+
.rev()
402+
.collect::<PathBuf>()
403+
.display()
404+
.to_string()
405+
}
406+
368407
impl<S> Layer<S> for TracingPrinter
369408
where
370409
S: Subscriber,

src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,11 @@ There are two orthogonal ways to control which kind of tracing logs you want:
8181
- If you select a level, all events/spans with an equal or higher priority level will be shown.
8282
2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` or a custom target like `CONFIG_HANDLING` or `STEP`.
8383
- Custom targets are used to limit what kinds of spans you are interested in, as the `BOOTSTRAP_TRACING=trace` output can be quite verbose. Currently, you can use the following custom targets:
84-
- `CONFIG_HANDLING`: show spans related to config handling
85-
- `STEP`: show all executed steps. Note that executed commands have `info` event level.
86-
- `COMMAND`: show all executed commands. Note that executed commands have `trace` event level.
84+
- `CONFIG_HANDLING`: show spans related to config handling.
85+
- `STEP`: show all executed steps. Executed commands have `info` event level.
86+
- `COMMAND`: show all executed commands. Executed commands have `trace` event level.
87+
- `IO`: show performed I/O operations. Executed commands have `trace` event level.
88+
- Note that many I/O are currently not being traced.
8789

8890
You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally):
8991

0 commit comments

Comments
 (0)