zebrad/components/tracing/
flame.rs

1//! A tracing flamegraph component.
2
3use color_eyre::eyre::Report;
4use std::{
5    fs::File,
6    io::{BufReader, BufWriter},
7    path::Path,
8    path::PathBuf,
9};
10use tracing::Subscriber;
11use tracing_subscriber::{registry::LookupSpan, Layer};
12
13pub struct Grapher {
14    guard: tracing_flame::FlushGuard<BufWriter<File>>,
15    path: PathBuf,
16}
17
18pub fn layer<S>(path_root: &Path) -> (impl Layer<S>, Grapher)
19where
20    S: Subscriber + for<'span> LookupSpan<'span>,
21{
22    let path = path_root.with_extension("folded");
23    let (layer, guard) = tracing_flame::FlameLayer::with_file(&path).unwrap();
24    let layer = layer.with_empty_samples(false).with_threads_collapsed(true);
25    let flamegrapher = Grapher { guard, path };
26    (layer, flamegrapher)
27}
28
29impl Grapher {
30    pub fn write_flamegraph(&self) -> Result<(), Report> {
31        self.guard.flush()?;
32        let out_path = self.path.with_extension("svg");
33        let inf = File::open(&self.path)?;
34        let reader = BufReader::new(inf);
35
36        let out = File::create(out_path)?;
37        let writer = BufWriter::new(out);
38
39        let mut opts = inferno::flamegraph::Options::default();
40        debug!("writing flamegraph to disk...");
41        inferno::flamegraph::from_reader(&mut opts, reader, writer)?;
42
43        Ok(())
44    }
45}