Repository navigation
Formatting of std::backtrace::Backtrace #65280
Description
I'd like to propose some changes to formatting of the Backtrace type introduced in #53487.
-
Don't include newlines in the default
Debugoutput. I personally find it pretty jarring when looking at the debug output of an error where everything is on the same line except the backtrace, and then any additional properties are printed way down on the last line.I'd suggest instead printing a "list" of "maps", such that it'd look like
[{ function: "errors::new", file: "./src/new.rs", line: 21 }, ...]. -
Allow passing the "precision" format flag to limit how many frames are printed. The most relevant frames are normally near the top, but deciding exactly how many depends on the app. Then a user could write
println!("short trace: {:.5}", trace)to see just 5 frames. -
Remove
stack backtrace:\nprefix entirely. When formatting, I'd think a user would pick their own prefix, likeprintln!("Call stack:\n{}", trace).
Activity
dtolnay commentedon Oct 11, 2019
+1 to all three points. I would accept a PR for this change.
0paIescent commentedon Oct 15, 2019
I'd like to take on this issue and make a PR for it. This is my first time taking on a PR for rust though, so is there anything you'd suggest outside of the Contributing guide?
seanmonstar commentedon Oct 15, 2019
I think this requires edits in libstd (
rust/src/libstd/backtrace.rs
Lines 269 to 323 in 437ca55
0paIescent commentedon Oct 15, 2019
Thanks! I had already looked into it though, I meant more of general contribution to Rust 😄
0paIescent commentedon Oct 16, 2019
How's this looking?
dtolnay commentedon Oct 16, 2019
The trailing comma at the end looks wrong
}, ]. It should be}].Could you share the
println!("{:#?}", backtrace)prettyprinted representation too?0paIescent commentedon Oct 16, 2019
Yeah I'm working on getting that out of there, I was starting with just modifying the
write!()s, but I wonder if more of a redesign is needed.And here it is prettyprinted:
seanmonstar commentedon Oct 16, 2019
You can get a lot of this for "free" if you make use of
Formatter::debug_list()and make a wrapperDebugFrame<'a>(&'a Frame).And in
DebugFrame, you can useFormatter::debug_struct.0paIescent commentedon Oct 16, 2019
Oh that's a great idea, I had forgotten those helper methods were there in Debug. Thanks!
0paIescent commentedon Oct 16, 2019
Here's my fork with what I have so far for backtrace-rs. Now, the reason there was a trailing comma at the end was that the last frame had a IP of 0x0, and its symbol had no data. Do those need to be filtered out or is there a practical use for those?
Also, the one thing left besides precision is getting the path properly, but before it was done by being passed in to BacktraceFmt. Do you have some suggestions for how I could get that into the DebugBacktraceSymbol in a more efficient way than just passing it down through the DebugBacktraceFrame and then down into the DebugBacktraceSymbol?
0paIescent commentedon Oct 17, 2019
So, I changed it back to the previous way of printing everything out, just with some added formatting, and a check to see if it's the first frame so it knows when to print a comma after a symbol's "map".
The precision also works now, but there's a catch, since the formatter is passed down to the print path function the precision persists when printing out the path. Since
Formatterdoesn't have setters for its attributes, what else could I do to update the precision toNoneother than just making a PR for a setter for precision?seanmonstar commentedon Oct 17, 2019
My idea using precision might not end up working well...
8 remaining items
seanmonstar commentedon Jun 4, 2020
Probably! Of the points I posted originally:
Debugformat that doesn't force newlines and respects:#?.stack bactrace:\nprefix has been removed, so a user can call it something different if the prefer (call stack, frames, etc).yaahc commentedon Jun 4, 2020
Would adding the precision stuff later be considered a breaking change that violates std's stability guaruntees?
withoutboats commentedon Jun 4, 2020
IMO currently the only guarantee we're making about backtrace is that formatted with the normal Debug formatting (
"{:?}") will not change. In the worst case (though this shouldn't happen), the API could instead be a new method on backtrace which returns a view of only a range of ranges.Mark-Simulacrum commentedon Jun 4, 2020
@withoutboats I would maybe not even go that far? e.g. that we probably don't want to guarantee a specific implementation wrt to showing inlined functions and such. But maybe you mean that we will keep the format of the "raw" Debug display consistent with what it is today.
I'd personally be unsure that I would want to stabilize even that -- I think if we're essentially stabilizing that I would rather stabilize accessor methods returning an iterator or something along those lines to avoid people parsing our output (and preventing any, even minor, changes as a result).
withoutboats commentedon Jun 4, 2020
This should probably be on the #72981 but: users are curently relying on that format to parse out info about the frames, because we don't provide a better API. We should not break that, at least until we have stable accessors. I agree that we should provide those APIs as well, but I wouldn't agree that it should block stabilizing backtrace. I just think we should be aware that users are currently, on nightly, relying on the format of the debug output.
Mark-Simulacrum commentedon Jun 4, 2020
Ah, I was not aware that we knew of use cases that were doing that. I agree that we should not break them just because and certainly not before methods are added to replace functionality. I also agree it need not block stabilization.
One thing that might be good to do is to add a method that explicitly keeps the current format or at least add a snippet to the Debug impl noting that we intend to keep it stable.
yaahc commentedon Jun 4, 2020
Yea, my inclination is to not block stabilization on the filtering issue, users can already filter the frames themselves by parsing the output from the
Debugimpl with something like https://crates.io/crates/btparse. Also, once we get a stable access api for iterating over frames it should be easy to build filtering ontop ofBacktraceand crates likecolor-backtracewhich do more accurate filtering than the precision based filtering built into theDisplayimpl could probably achieve.cauebs commentedon Nov 12, 2020
Have you guys settled on the precision idea or are you open to other approaches? Using
Indexwith ranges seems way more intuitive to me.yaahc commentedon Nov 12, 2020
My impression is that we're punting on the issue and instead focusing on making it possible for ppl to experiment with their own display formats by adding a
framesmethod toBacktrace.tmandry commentedon Nov 20, 2020
On Fuchsia we use external symbolization, which means the file and line number are not resolved in the process itself. This allows us to capture backtraces without having to ship binaries containing debuginfo. We use a standard symbolization markup format across the platform, where each frame is typically printed on its own line.
I'm not opposed to these changes on other platforms, but I bring this up to highlight that the Display/Debug formats of
Backtracecan't be the same across all platforms and build configurations.philip-peterson commentedon Feb 28, 2021
@tmandry is that implemented using the Rust standard tooling or some other way? Would be nice for development on this issue to have a minimal repro case, against which to test changes to Rust on.