-
Notifications
You must be signed in to change notification settings - Fork 109
/
flamegraph.rs
132 lines (115 loc) · 4.31 KB
/
flamegraph.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use env_logger::Env;
use std::fs::File;
use std::io::{self, BufReader, Read};
use std::path::PathBuf;
use structopt::StructOpt;
use inferno::flamegraph::{self, BackgroundColor, Direction, FuncFrameAttrsMap, Options, Palette};
#[derive(Debug, StructOpt)]
#[structopt(name = "inferno-flamegraph", author = "")]
struct Opt {
/// File containing attributes to use for the SVG frames of particular functions.
/// Each line in the file should be a function name followed by a tab,
/// then a sequence of tab separated name=value pairs.
#[structopt(long = "nameattr")]
nameattr_file: Option<PathBuf>,
/// Plot the flame graph up-side-down.
#[structopt(short = "i", long = "inverted")]
inverted: bool,
/// Collapsed perf output files. With no INFILE, or INFILE is -, read STDIN.
#[structopt(name = "INFILE", parse(from_os_str))]
infiles: Vec<PathBuf>,
/// Set color palette
#[structopt(
short = "c",
long = "colors",
default_value = "hot",
raw(
possible_values = r#"&["hot","mem","io","wakeup","java","js","perl","red","green","blue","aqua","yellow","purple","orange"]"#
)
)]
colors: Palette,
/// Set background colors. Gradient choices are yellow (default), blue, green, grey; flat colors use "#rrggbb"
#[structopt(long = "bgcolors")]
bgcolors: Option<BackgroundColor>,
/// Colors are keyed by function name hash
#[structopt(long = "hash")]
hash: bool,
/// Use consistent palette (palette.map)
#[structopt(long = "cp")]
cp: bool,
/// Switch differential hues (green<->red)
#[structopt(long = "negate")]
negate: bool,
/// Factor to scale sample counts by
#[structopt(long = "factor", default_value = "1.0")]
factor: f64,
/// Silence all log output
#[structopt(short = "q", long = "quiet")]
quiet: bool,
/// Verbose logging mode (-v, -vv, -vvv)
#[structopt(short = "v", long = "verbose", parse(from_occurrences))]
verbose: usize,
}
impl Into<Options> for Opt {
fn into(self) -> Options {
let mut options = Options::default();
options.colors = self.colors;
options.bgcolors = self.bgcolors;
options.hash = self.hash;
options.consistent_palette = self.cp;
if let Some(file) = self.nameattr_file {
match FuncFrameAttrsMap::from_file(&file) {
Ok(m) => {
options.func_frameattrs = m;
}
Err(e) => panic!("Error reading {}: {:?}", file.display(), e),
}
};
if self.inverted {
options.direction = Direction::Inverted;
options.title = "Icicle Graph".to_string();
}
options.negate_differentials = self.negate;
options.factor = self.factor;
options
}
}
fn main() -> quick_xml::Result<()> {
let opt = Opt::from_args();
// Initialize logger
if !opt.quiet {
env_logger::Builder::from_env(Env::default().default_filter_or(match opt.verbose {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
}))
.default_format_timestamp(false)
.init();
}
if opt.infiles.is_empty() || opt.infiles.len() == 1 && opt.infiles[0].to_str() == Some("-") {
let stdin = io::stdin();
let r = BufReader::with_capacity(128 * 1024, stdin.lock());
flamegraph::from_reader(opt.into(), r, io::stdout().lock())
} else if opt.infiles.len() == 1 {
let r = File::open(&opt.infiles[0]).map_err(quick_xml::Error::Io)?;
flamegraph::from_reader(opt.into(), r, io::stdout().lock())
} else {
let stdin = io::stdin();
let mut stdin_added = false;
let mut readers: Vec<Box<Read>> = Vec::with_capacity(opt.infiles.len());
for infile in opt.infiles.iter() {
if infile.to_str() == Some("-") {
if !stdin_added {
let r = BufReader::with_capacity(128 * 1024, stdin.lock());
readers.push(Box::new(r));
stdin_added = true;
}
} else {
let r = File::open(infile).map_err(quick_xml::Error::Io)?;
readers.push(Box::new(r));
}
}
flamegraph::from_readers(opt.into(), readers, io::stdout().lock())
}
}