Skip to content

Commit

Permalink
Add tracing-flame crate for generating flamegraphs/flamecharts (#631)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaahc authored Apr 21, 2020
1 parent aeca938 commit 280b664
Show file tree
Hide file tree
Showing 8 changed files with 641 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"tracing-core",
"tracing-attributes",
"tracing-error",
"tracing-flame",
"tracing-futures",
"tracing-tower",
"tracing-log",
Expand Down
7 changes: 7 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ default = []
tracing = { path = "../tracing", version = "0.1"}
tracing-core = { path = "../tracing-core", version = "0.1"}
tracing-error = { path = "../tracing-error" }
tracing-flame = { path = "../tracing-flame" }
tracing-tower = { version = "0.1.0", path = "../tracing-tower" }
tracing-subscriber = { path = "../tracing-subscriber", version = "0.2.4", features = ["json", "chrono"] }
tracing-futures = { version = "0.2.1", path = "../tracing-futures", features = ["futures-01"] }
Expand Down Expand Up @@ -43,3 +44,9 @@ clap = "2.33"
ansi_term = "0.11"
humantime = "1.2"
log = "0.4"

# infero example
inferno = "0.9.4"
eyre = "0.3.5"
indenter = "0.1.3"
tempdir = "0.3.7"
56 changes: 56 additions & 0 deletions examples/examples/inferno_flame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use std::thread::sleep;
use std::time::Duration;
use tempdir::TempDir;
use tracing::{span, Level};
use tracing_flame::FlameLayer;
use tracing_subscriber::{prelude::*, registry::Registry};

static PATH: &str = "flame.folded";

fn setup_global_subscriber(dir: &Path) -> impl Drop {
let (flame_layer, _guard) = FlameLayer::with_file(dir.join(PATH)).unwrap();

let subscriber = Registry::default().with(flame_layer);

tracing::subscriber::set_global_default(subscriber).unwrap();

_guard
}

fn make_flamegraph(dir: &Path) {
let inf = File::open(dir.join(PATH)).unwrap();
let reader = BufReader::new(inf);

let out = File::create(dir.join("inferno.svg")).unwrap();
let writer = BufWriter::new(out);

let mut opts = inferno::flamegraph::Options::default();
inferno::flamegraph::from_reader(&mut opts, reader, writer).unwrap();
}

fn main() {
// setup the flame layer
let tmp_dir = TempDir::new("flamegraphs").unwrap();
let guard = setup_global_subscriber(tmp_dir.path());

// do a bunch of span entering and exiting to simulate a program running
span!(Level::ERROR, "outer").in_scope(|| {
sleep(Duration::from_millis(10));
span!(Level::ERROR, "Inner").in_scope(|| {
sleep(Duration::from_millis(50));
span!(Level::ERROR, "Innermost").in_scope(|| {
sleep(Duration::from_millis(50));
});
});
sleep(Duration::from_millis(5));
});
sleep(Duration::from_millis(500));

// drop the guard to make sure the layer flushes its output then read the
// output to create the flamegraph
drop(guard);
make_flamegraph(tmp_dir.path());
}
33 changes: 33 additions & 0 deletions tracing-flame/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "tracing-flame"
version = "0.1.0"
authors = [
"Jane Lusby <[email protected]>",
"Tokio Contributors <[email protected]>"
]
edition = "2018"
license = "MIT"
readme = "README.md"
repository = "https://github.com/tokio-rs/tracing"
homepage = "https://tokio.rs"
description = """
Tracing layer for creating flamegraphs from span timings
"""
categories = [
"development-tools::debugging",
"development-tools::profiling",
"asynchronous",
]
keywords = ["tracing", "subscriber", "flamegraph", "profiling"]

[features]
default = ["smallvec"]
smallvec = ["tracing-subscriber/smallvec"]

[dependencies]
tracing-subscriber = { path = "../tracing-subscriber", version = "0.2.3", default-features = false, features = ["registry", "fmt"] }
tracing = { path = "../tracing", version = "0.1.12"}
lazy_static = "1.3.0"

[dev-dependencies]
tempdir = "0.3.7"
57 changes: 57 additions & 0 deletions tracing-flame/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::fmt;
use std::path::PathBuf;

/// The error type for `tracing-flame`
#[derive(Debug)]
pub struct Error(pub(crate) Kind);

impl Error {
pub(crate) fn report(&self) {
let current_error: &dyn std::error::Error = self;
let mut current_error = Some(current_error);
let mut ind = 0;

eprintln!("Error:");

while let Some(error) = current_error {
eprintln!(" {}: {}", ind, error);
ind += 1;
current_error = error.source();
}
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self.0 {
Kind::CreateFile { ref source, .. } => Some(source),
Kind::FlushFile(ref source) => Some(source),
}
}
}

#[derive(Debug)]
pub(crate) enum Kind {
CreateFile {
source: std::io::Error,
path: PathBuf,
},
FlushFile(std::io::Error),
}

impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CreateFile { path, .. } => {
write!(f, "cannot create output file. path={}", path.display())
}
Self::FlushFile { .. } => write!(f, "cannot flush output buffer"),
}
}
}
Loading

0 comments on commit 280b664

Please sign in to comment.