1- The compiler has a lot of [ ` debug! ` ] calls, which print out logging information
1+ # Using tracing to debug the compiler
2+
3+ <!-- toc -->
4+
5+ The compiler has a lot of [ ` debug! ` ] (or ` trace! ` ) calls, which print out logging information
26at many points. These are very useful to at least narrow down the location of
37a bug if not to find it entirely, or just to orient yourself as to why the
48compiler is doing a particular thing.
59
610[ `debug!` ] : https://docs.rs/tracing/0.1/tracing/macro.debug.html
711
812To see the logs, you need to set the ` RUSTC_LOG ` environment variable to your
9- log filter. Your log filter can be just ` debug ` to get all ` debug! ` output and
13+ log filter.
14+
15+ ## Function level filters
16+
17+ Lots of functions in rustc are annotated with
18+
19+ ```
20+ #[instrument(level = "debug", skip(self))]
21+ fn foo(&self, bar: Type) {}
22+ ```
23+
24+ which allows you to use
25+
26+ ```
27+ RUSTC_LOG=[foo]
28+ ```
29+
30+ to do the following all at once
31+
32+ * log all function calls to ` foo `
33+ * log the arguments (except for those in the ` skip ` list)
34+ * log everything (from anywhere else in the compiler) until the function returns
35+
36+ ### I don't want everything
37+
38+ Depending on the scope of the function, you may not want to log everything in its body.
39+ As an example: the ` do_mir_borrowck ` function will dump hundreds of lines even for trivial
40+ code being borrowchecked.
41+
42+ Since you can combine all filters, you can add a crate/module path, e.g.
43+
44+ ```
45+ RUSTC_LOG=rustc_borrowck[do_mir_borrowck]
46+ ```
47+
48+ ### I don't want all calls
49+
50+ If you are compiling libcore, you likely don't want * all* borrowck dumps, but only one
51+ for a specific function. You can filter function calls by their arguments by regexing them.
52+
53+ ```
54+ RUSTC_LOG=[do_mir_borrowck{id=\.\*from_utf8_unchecked\.\*}]
55+ ```
56+
57+ will only give you the logs of borrowchecking ` from_utf8_unchecked ` . Note that you will
58+ still get a short message per ignored ` do_mir_borrowck ` , but none of the things inside those
59+ calls. This helps you in looking through the calls that are happening and helps you adjust
60+ your regex if you mistyped it.
61+
62+ ## Broad module level filters
63+
64+ You can also use filters similar to the ` log ` crate's filters, which will enable
65+ everything within a specific module. This is often too verbose and too unstructured,
66+ so it is recommended to use function level filters.
67+
68+ Your log filter can be just ` debug ` to get all ` debug! ` output and
1069higher (e.g., it will also include ` info! ` ), or ` path::to::module ` to get * all*
1170output (which will include ` trace! ` ) from a particular module, or
1271` 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
69128$ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs
70129```
71130
72- ### Log colors
131+ ## Log colors
73132
74133By default, rustc (and other tools, like rustdoc and Miri) will be smart about
75134when 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
94153from rustc functions that Miri calls. Use ` RUSTC_LOG_COLOR ` to color logs from
95154rustc.
96155
97- ### How to keep or remove ` debug! ` and ` trace! ` calls from the resulting binary
156+ ## How to keep or remove ` debug! ` and ` trace! ` calls from the resulting binary
98157
99158While calls to ` error! ` , ` warn! ` and ` info! ` are included in every build of the compiler,
100159calls to ` debug! ` and ` trace! ` are only included in the program if
@@ -104,30 +163,32 @@ if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see
104163` INFO ` logs, make sure that ` debug-logging=true ` is turned on in your
105164config.toml.
106165
107- ### Logging etiquette and conventions
166+ ## Logging etiquette and conventions
108167
109168Because calls to ` debug! ` are removed by default, in most cases, don't worry
110169about adding "unnecessary" calls to ` debug! ` and leaving them in code you
111170commit - they won't slow down the performance of what we ship, and if they
112171helped you pinning down a bug, they will probably help someone else with a
113172different one.
114173
115- A loosely followed convention is to use ` debug!("foo(...)") ` at the _ start_ of
116- a function ` foo ` and ` debug!("foo: ...") ` _ within_ the function. Another
117- loosely followed convention is to use the ` {:?} ` format specifier for debug
118- logs.
174+ It may be preferrable to use ` trace! ` over ` debug! ` for very noisy logs.
175+
176+ A loosely followed convention is to use ` #[instrument(level = "debug")] ` in
177+ favour of ` debug!("foo(...)") ` at the start of a function ` foo ` .
178+ Within functions, prefer ` debug!(?variable.field) ` over ` debug!("xyz = {:?}", variable.field) `
179+ and ` debug!(bar = ?var.method(arg)) ` over ` debug!("bar = {:?}", var.method(arg)) ` .
119180
120181One thing to be ** careful** of is ** expensive** operations in logs.
121182
122183If in the module ` rustc::foo ` you have a statement
123184
124185``` Rust
125- debug! (" {:?} " , random_operation (tcx ));
186+ debug! (x = ? random_operation (tcx ));
126187```
127188
128189Then if someone runs a debug ` rustc ` with ` RUSTC_LOG=rustc::bar ` , then
129190` random_operation() ` will run.
130191
131192This means that you should not put anything too expensive or likely to crash
132193there - that would annoy anyone who wants to use logging for their own module.
133- No-one will know it until someone tries to use logging to find * another* bug.
194+ No-one will know it until someone tries to use logging to find * another* bug.
0 commit comments