Document tracing awesomeness
This commit is contained in:
parent
1620515e37
commit
3657acea97
|
|
@ -1,4 +1,8 @@
|
||||||
The compiler has a lot of [`debug!`] calls, which print out logging information
|
# Using tracing to debug the compiler
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information
|
||||||
at many points. These are very useful to at least narrow down the location of
|
at many points. These are very useful to at least narrow down the location of
|
||||||
a bug if not to find it entirely, or just to orient yourself as to why the
|
a bug if not to find it entirely, or just to orient yourself as to why the
|
||||||
compiler is doing a particular thing.
|
compiler is doing a particular thing.
|
||||||
|
|
@ -6,7 +10,62 @@ compiler is doing a particular thing.
|
||||||
[`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html
|
[`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html
|
||||||
|
|
||||||
To see the logs, you need to set the `RUSTC_LOG` environment variable to your
|
To see the logs, you need to set the `RUSTC_LOG` environment variable to your
|
||||||
log filter. Your log filter can be just `debug` to get all `debug!` output and
|
log filter.
|
||||||
|
|
||||||
|
## Function level filters
|
||||||
|
|
||||||
|
Lots of functions in rustc are annotated with
|
||||||
|
|
||||||
|
```
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
fn foo(&self, bar: Type) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
which allows you to use
|
||||||
|
|
||||||
|
```
|
||||||
|
RUSTC_LOG=[foo]
|
||||||
|
```
|
||||||
|
|
||||||
|
to do the following all at once
|
||||||
|
|
||||||
|
* log all function calls to `foo`
|
||||||
|
* log the arguments (except for those in the `skip` list)
|
||||||
|
* log everything (from anywhere else in the compiler) until the function returns
|
||||||
|
|
||||||
|
### I don't want everything
|
||||||
|
|
||||||
|
Depending on the scope of the function, you may not want to log everything in its body.
|
||||||
|
As an example: the `do_mir_borrowck` function will dump hundreds of lines even for trivial
|
||||||
|
code being borrowchecked.
|
||||||
|
|
||||||
|
Since you can combine all filters, you can add a crate/module path, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
RUSTC_LOG=rustc_borrowck[do_mir_borrowck]
|
||||||
|
```
|
||||||
|
|
||||||
|
### I don't want all calls
|
||||||
|
|
||||||
|
If you are compiling libcore, you likely don't want *all* borrowck dumps, but only one
|
||||||
|
for a specific function. You can filter function calls by their arguments by regexing them.
|
||||||
|
|
||||||
|
```
|
||||||
|
RUSTC_LOG=[do_mir_borrowck{id=\.\*from_utf8_unchecked\.\*}]
|
||||||
|
```
|
||||||
|
|
||||||
|
will only give you the logs of borrowchecking `from_utf8_unchecked`. Note that you will
|
||||||
|
still get a short message per ignored `do_mir_borrowck`, but none of the things inside those
|
||||||
|
calls. This helps you in looking through the calls that are happening and helps you adjust
|
||||||
|
your regex if you mistyped it.
|
||||||
|
|
||||||
|
## Broad module level filters
|
||||||
|
|
||||||
|
You can also use filters similar to the `log` crate's filters, which will enable
|
||||||
|
everything within a specific module. This is often too verbose and too unstructured,
|
||||||
|
so it is recommended to use function level filters.
|
||||||
|
|
||||||
|
Your log filter can be just `debug` to get all `debug!` output and
|
||||||
higher (e.g., it will also include `info!`), or `path::to::module` to get *all*
|
higher (e.g., it will also include `info!`), or `path::to::module` to get *all*
|
||||||
output (which will include `trace!`) from a particular module, or
|
output (which will include `trace!`) from a particular module, or
|
||||||
`path::to::module=debug` to get `debug!` output and higher from a particular
|
`path::to::module=debug` to get `debug!` output and higher from a particular
|
||||||
|
|
@ -69,7 +128,7 @@ $ RUSTDOC_LOG=info rustdoc +stage1 my-file.rs
|
||||||
$ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs
|
$ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
### Log colors
|
## Log colors
|
||||||
|
|
||||||
By default, rustc (and other tools, like rustdoc and Miri) will be smart about
|
By default, rustc (and other tools, like rustdoc and Miri) will be smart about
|
||||||
when to use ANSI colors in the log output. If they are outputting to a terminal,
|
when to use ANSI colors in the log output. If they are outputting to a terminal,
|
||||||
|
|
@ -94,7 +153,7 @@ Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, not logs
|
||||||
from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from
|
from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from
|
||||||
rustc.
|
rustc.
|
||||||
|
|
||||||
### How to keep or remove `debug!` and `trace!` calls from the resulting binary
|
## How to keep or remove `debug!` and `trace!` calls from the resulting binary
|
||||||
|
|
||||||
While calls to `error!`, `warn!` and `info!` are included in every build of the compiler,
|
While calls to `error!`, `warn!` and `info!` are included in every build of the compiler,
|
||||||
calls to `debug!` and `trace!` are only included in the program if
|
calls to `debug!` and `trace!` are only included in the program if
|
||||||
|
|
@ -104,7 +163,7 @@ if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see
|
||||||
`INFO` logs, make sure that `debug-logging=true` is turned on in your
|
`INFO` logs, make sure that `debug-logging=true` is turned on in your
|
||||||
config.toml.
|
config.toml.
|
||||||
|
|
||||||
### Logging etiquette and conventions
|
## Logging etiquette and conventions
|
||||||
|
|
||||||
Because calls to `debug!` are removed by default, in most cases, don't worry
|
Because calls to `debug!` are removed by default, in most cases, don't worry
|
||||||
about adding "unnecessary" calls to `debug!` and leaving them in code you
|
about adding "unnecessary" calls to `debug!` and leaving them in code you
|
||||||
|
|
@ -112,17 +171,19 @@ commit - they won't slow down the performance of what we ship, and if they
|
||||||
helped you pinning down a bug, they will probably help someone else with a
|
helped you pinning down a bug, they will probably help someone else with a
|
||||||
different one.
|
different one.
|
||||||
|
|
||||||
A loosely followed convention is to use `debug!("foo(...)")` at the _start_ of
|
It may be preferrable to use `trace!` over `debug!` for very noisy logs.
|
||||||
a function `foo` and `debug!("foo: ...")` _within_ the function. Another
|
|
||||||
loosely followed convention is to use the `{:?}` format specifier for debug
|
A loosely followed convention is to use `#[instrument(level = "debug")]` in
|
||||||
logs.
|
favour of `debug!("foo(...)")` at the start of a function `foo`.
|
||||||
|
Within functions, prefer `debug!(?variable.field)` over `debug!("xyz = {:?}", variable.field)`
|
||||||
|
and `debug!(bar = ?var.method(arg))` over `debug!("bar = {:?}", var.method(arg))`.
|
||||||
|
|
||||||
One thing to be **careful** of is **expensive** operations in logs.
|
One thing to be **careful** of is **expensive** operations in logs.
|
||||||
|
|
||||||
If in the module `rustc::foo` you have a statement
|
If in the module `rustc::foo` you have a statement
|
||||||
|
|
||||||
```Rust
|
```Rust
|
||||||
debug!("{:?}", random_operation(tcx));
|
debug!(x = ?random_operation(tcx));
|
||||||
```
|
```
|
||||||
|
|
||||||
Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::bar`, then
|
Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::bar`, then
|
||||||
|
|
@ -130,4 +191,4 @@ Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::bar`, then
|
||||||
|
|
||||||
This means that you should not put anything too expensive or likely to crash
|
This means that you should not put anything too expensive or likely to crash
|
||||||
there - that would annoy anyone who wants to use logging for their own module.
|
there - that would annoy anyone who wants to use logging for their own module.
|
||||||
No-one will know it until someone tries to use logging to find *another* bug.
|
No-one will know it until someone tries to use logging to find *another* bug.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue