Skip to content

Commit 4e47811

Browse files
authored
update readmes for flame and error (#695)
1 parent 8913293 commit 4e47811

File tree

4 files changed

+230
-24
lines changed

4 files changed

+230
-24
lines changed

tracing-error/README.md

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# tracing-error
22

3-
Utilities for instrumenting errors with [`tracing`].
3+
Utilities for enriching error handling with [`tracing`] diagnostic
4+
information.
45

56
[![Crates.io][crates-badge]][crates-url]
67
[![Documentation][docs-badge]][docs-url]
@@ -26,7 +27,7 @@ Utilities for instrumenting errors with [`tracing`].
2627
[discord-url]: https://discord.gg/EeF3cQw
2728
[maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg
2829

29-
## Overview
30+
# Overview
3031

3132
[`tracing`] is a framework for instrumenting Rust programs to collect
3233
scoped, structured, and async-aware diagnostics. This crate provides
@@ -47,14 +48,9 @@ The crate provides the following:
4748

4849
## Usage
4950

50-
Currently, `tracing-error` provides the [`SpanTrace`] type, which captures
51-
the current `tracing` span context when it is constructed and allows it to
52-
be displayed at a later time.
53-
54-
This crate does not _currently_ provide any actual error types implementing
55-
`std::error::Error`. Instead, user-constructed errors or libraries
56-
implementing error types may capture a [`SpanTrace`] and include it as part
57-
of their error types.
51+
`tracing-error` provides the [`SpanTrace`] type, which captures the current
52+
`tracing` span context when it is constructed and allows it to be displayed
53+
at a later time.
5854

5955
For example:
6056

@@ -71,8 +67,11 @@ pub struct MyError {
7167
impl fmt::Display for MyError {
7268
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7369
// ... format other parts of the error ...
70+
7471
self.context.fmt(f)?;
72+
7573
// ... format other error context information, cause chain, etc ...
74+
# Ok(())
7675
}
7776
}
7877

@@ -88,8 +87,68 @@ impl MyError {
8887
}
8988
```
9089

91-
In the future, this crate may also provide its own `Error` types as well,
92-
for users who do not wish to use other error-handling libraries.
90+
This crate also provides [`TracedError`], for attaching a [`SpanTrace`] to an
91+
existing error. The easiest way to wrap errors in `TracedError` is to either
92+
use the [`InstrumentResult`] and [`InstrumentError`] traits or the `From`/`Into`
93+
traits.
94+
95+
```rust
96+
use tracing_error::prelude::*;
97+
98+
std::fs::read_to_string("myfile.txt").in_current_span()?;
99+
```
100+
101+
Once an error has been wrapped with with a [`TracedError`], the [`SpanTrace`]
102+
can be extracted one of three ways: either via [`TracedError`]'s
103+
`Display`/`Debug` implementations, or via the [`ExtractSpanTrace`] trait.
104+
105+
For example, here is how one might print the errors but specialize the
106+
printing when the error is a placeholder for a wrapping [`SpanTrace`]:
107+
108+
```rust
109+
use std::error::Error;
110+
use tracing_error::ExtractSpanTrace as _;
111+
112+
fn print_extracted_spantraces(error: &(dyn Error + 'static)) {
113+
let mut error = Some(error);
114+
let mut ind = 0;
115+
116+
eprintln!("Error:");
117+
118+
while let Some(err) = error {
119+
if let Some(spantrace) = err.span_trace() {
120+
eprintln!("found a spantrace:\n{}", spantrace);
121+
} else {
122+
eprintln!("{:>4}: {}", ind, err);
123+
}
124+
125+
error = err.source();
126+
ind += 1;
127+
}
128+
}
129+
130+
```
131+
132+
Whereas here, we can still display the content of the `SpanTraces` without
133+
any special casing by simply printing all errors in our error chain.
134+
135+
```rust
136+
use std::error::Error;
137+
138+
fn print_naive_spantraces(error: &(dyn Error + 'static)) {
139+
let mut error = Some(error);
140+
let mut ind = 0;
141+
142+
eprintln!("Error:");
143+
144+
while let Some(err) = error {
145+
eprintln!("{:>4}: {}", ind, err);
146+
error = err.source();
147+
ind += 1;
148+
}
149+
}
150+
```
151+
93152
Applications that wish to use `tracing-error`-enabled errors should
94153
construct an [`ErrorLayer`] and add it to their [`Subscriber`] in order to
95154
enable capturing [`SpanTrace`]s. For example:
@@ -103,17 +162,20 @@ fn main() {
103162
// any number of other subscriber layers may be added before or
104163
// after the `ErrorLayer`...
105164
.with(ErrorLayer::default());
165+
106166
// set the subscriber as the default for the application
107167
tracing::subscriber::set_global_default(subscriber);
108168
}
109169
```
110170

111-
[`SpanTrace`]: https://docs.rs/tracing-error/0.1.2/tracing_error/struct.SpanTrace.html
112-
[`ErrorLayer`]: https://docs.rs/tracing-error/0.1.2/tracing_error/struct.ErrorLayer.html
113-
[span]: https://docs.rs/tracing/latest/tracing/span/index.html
114-
[event]: https://docs.rs/tracing/latest/tracing/struct.Event.html
115-
[subscriber layer]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html
116-
[`tracing`]: https://crates.io/tracing
171+
## Feature Flags
172+
173+
- `traced-error` - Enables the [`TracedError`] type and related traits
174+
- [`InstrumentResult`] and [`InstrumentError`] extension traits, which
175+
provide an [`in_current_span()`] method for bundling errors with a
176+
[`SpanTrace`].
177+
- [`ExtractSpanTrace`] extension trait, for extracting `SpanTrace`s from
178+
behind `dyn Error` trait objects.
117179

118180
## License
119181

@@ -124,3 +186,19 @@ This project is licensed under the [MIT license](LICENSE).
124186
Unless you explicitly state otherwise, any contribution intentionally submitted
125187
for inclusion in Tracing by you, shall be licensed as MIT, without any additional
126188
terms or conditions.
189+
190+
[`SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html
191+
[`ErrorLayer`]: https://docs.rs/tracing-error/*/tracing_error/struct.ErrorLayer.html
192+
[`TracedError`]: https://docs.rs/tracing-error/*/tracing_error/struct.TracedError.html
193+
[`InstrumentResult`]: https://docs.rs/tracing-error/*/tracing_error/trait.InstrumentResult.html
194+
[`InstrumentError`]: https://docs.rs/tracing-error/*/tracing_error/trait.InstrumentError.html
195+
[`ExtractSpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/trait.ExtractSpanTrace.html
196+
[`in_current_span()`]: https://docs.rs/tracing-error/*/tracing_error/trait.InstrumentResult.html#tymethod.in_current_span
197+
[span]: https://docs.rs/tracing/latest/tracing/span/index.html
198+
[events]: https://docs.rs/tracing/latest/tracing/struct.Event.html
199+
[`Subscriber`]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
200+
[subscriber layer]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html
201+
[`tracing`]: https://docs.rs/tracing
202+
[`std::error::Error`]: https://doc.rust-lang.org/stable/std/error/trait.Error.html
203+
[`SpanTrace`]: https://docs.rs/tracing-error/0.1.2/tracing_error/struct.SpanTrace.html
204+
[`ErrorLayer`]: https://docs.rs/tracing-error/0.1.2/tracing_error/struct.ErrorLayer.html

tracing-error/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@
7070
//! }
7171
//! ```
7272
//!
73-
//! This crate also provides the [`InstrumentResult`] and [`InstrumentError`]
74-
//! traits, which can be used to wrap errors with a [`TracedError`] which
75-
//! bundles the inner error with a [`SpanTrace`].
73+
//! This crate also provides [`TracedError`], for attaching a [`SpanTrace`] to
74+
//! an existing error. The easiest way to wrap errors in `TracedError` is to
75+
//! either use the [`InstrumentResult`] and [`InstrumentError`] traits or the
76+
//! `From`/`Into` traits.
7677
//!
7778
//! ```rust
7879
//! # use std::error::Error;

tracing-flame/README.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# tracing-flame
2+
3+
A [tracing] [`Layer`][`FlameLayer`] for generating a folded stack trace for generating flamegraphs
4+
and flamecharts with [`inferno`]
5+
6+
[![Crates.io][crates-badge]][crates-url]
7+
[![Documentation][docs-badge]][docs-url]
8+
[![Documentation (master)][docs-master-badge]][docs-master-url]
9+
[![MIT licensed][mit-badge]][mit-url]
10+
[![Build Status][actions-badge]][actions-url]
11+
[![Discord chat][discord-badge]][discord-url]
12+
![maintenance status][maint-badge]
13+
14+
[Documentation][docs-url] | [Chat][discord-url]
15+
16+
# Overview
17+
18+
[`tracing`] is a framework for instrumenting Rust programs to collect
19+
scoped, structured, and async-aware diagnostics. `tracing-flame` provides helpers
20+
for consuming `tracing` instrumentation that can later be visualized as a
21+
flamegraph/flamechart. Flamegraphs/flamecharts are useful for identifying performance
22+
bottlenecks in an application. For more details, see Brendan Gregg's [post]
23+
on flamegraphs.
24+
25+
[post]: http://www.brendangregg.com/flamegraphs.html
26+
27+
## Usage
28+
29+
This crate is meant to be used in a two step process:
30+
31+
1. Capture textual representation of the spans that are entered and exited
32+
with [`FlameLayer`].
33+
2. Feed the textual representation into `inferno-flamegraph` to generate the
34+
flamegraph or flamechart.
35+
36+
*Note*: when using a buffered writer as the writer for a `FlameLayer`, it is necessary to
37+
ensure that the buffer has been flushed before the data is passed into
38+
[`inferno-flamegraph`]. For more details on how to flush the internal writer
39+
of the `FlameLayer`, see the docs for [`FlushGuard`].
40+
41+
## Layer Setup
42+
43+
```rust
44+
use std::{fs::File, io::BufWriter};
45+
use tracing_flame::FlameLayer;
46+
use tracing_subscriber::{registry::Registry, prelude::*, fmt};
47+
48+
fn setup_global_subscriber() -> impl Drop {
49+
let fmt_layer = fmt::Layer::default();
50+
51+
let (flame_layer, _guard) = FlameLayer::with_file("./tracing.folded").unwrap();
52+
53+
tracing_subscriber::registry()
54+
.with(fmt_layer)
55+
.with(flame_layer)
56+
.init().
57+
_guard
58+
}
59+
60+
// your code here ..
61+
```
62+
63+
As an alternative, you can provide _any_ type that implements `std::io::Write` to
64+
`FlameLayer::new`.
65+
66+
## Generating the Image
67+
68+
To convert the textual representation of a flamegraph to a visual one, first install `inferno`:
69+
70+
```console
71+
cargo install inferno
72+
```
73+
74+
Then, pass the file created by `FlameLayer` into `inferno-flamegraph`:
75+
76+
```console
77+
# flamegraph
78+
cat tracing.folded | inferno-flamegraph > tracing-flamegraph.svg
79+
80+
# flamechart
81+
cat tracing.folded | inferno-flamegraph --flamechart > tracing-flamechart.svg
82+
```
83+
84+
## Differences between `flamegraph`s and `flamechart`s
85+
86+
By default, `inferno-flamegraph` creates flamegraphs. Flamegraphs operate by
87+
that collapsing identical stack frames and sorting them on the frame's names.
88+
89+
This behavior is great for multithreaded programs and long-running programs
90+
where the same frames occur _many_ times, for short durations, because it reduces
91+
noise in the graph and gives the reader a better idea of the
92+
overall time spent in each part of the application.
93+
94+
However, it is sometimes desirable to preserve the _exact_ ordering of events
95+
as they were emitted by `tracing-flame`, so that it is clear when each
96+
span is entered relative to others and get an accurate visual trace of
97+
the execution of your program. This representation is best created with a
98+
_flamechart_, which _does not_ sort or collapse identical stack frames.
99+
100+
## License
101+
102+
This project is licensed under the [MIT license](LICENSE).
103+
104+
### Contribution
105+
106+
Unless you explicitly state otherwise, any contribution intentionally submitted
107+
for inclusion in Tracing by you, shall be licensed as MIT, without any additional
108+
terms or conditions.
109+
110+
[`inferno`]: https://docs.rs/inferno
111+
[`FlameLayer`]: https://docs.rs/tracing-flame/*/tracing_flame/struct.FlameLayer.html
112+
[`FlushGuard`]: https://docs.rs/tracing-flame/*/tracing_flame/struct.FlushGuard.html
113+
[`inferno-flamegraph`]: https://docs.rs/inferno/0.9.5/inferno/index.html#producing-a-flame-graph
114+
[`tracing`]: https://github.com/tokio-rs/tracing/tree/master/tracing
115+
[crates-badge]: https://img.shields.io/crates/v/tracing-flame.svg
116+
[crates-url]: https://crates.io/crates/tracing-flame
117+
[docs-badge]: https://docs.rs/tracing-flame/badge.svg
118+
[docs-url]: https://docs.rs/tracing-flame/0.2.4
119+
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
120+
[docs-master-url]: https://tracing-rs.netlify.com/tracing_flame
121+
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
122+
[mit-url]: LICENSE
123+
[actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg
124+
[actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI
125+
[discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white
126+
[discord-url]: https://discord.gg/EeF3cQw
127+
[maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg

tracing-flame/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
//!
1717
//! This crate is meant to be used in a two step process:
1818
//!
19-
//! 1. A textual representation of the spans that are entered and exited are
20-
//! captured with [`FlameLayer`].
19+
//! 1. Capture textual representation of the spans that are entered and exited
20+
//! with [`FlameLayer`].
2121
//! 2. Feed the textual representation into `inferno-flamegraph` to generate the
2222
//! flamegraph or flamechart.
2323
//!
@@ -66,7 +66,7 @@
6666
//! # flamegraph
6767
//! cat tracing.folded | inferno-flamegraph > tracing-flamegraph.svg
6868
//!
69-
//! #flamechart
69+
//! # flamechart
7070
//! cat tracing.folded | inferno-flamegraph --flamechart > tracing-flamechart.svg
7171
//! ```
7272
//!

0 commit comments

Comments
 (0)