From 3ca8490ce2d7a929790d1fa0103130227594eec9 Mon Sep 17 00:00:00 2001 From: Frans Skarman Date: Sun, 4 Dec 2022 00:42:30 +0000 Subject: [PATCH] Add uicolor option (#271) --- CHANGELOG.md | 4 + Cargo.toml | 2 +- src/bin/flamegraph.rs | 17 ++- src/flamegraph/color/mod.rs | 44 ++---- src/flamegraph/mod.rs | 7 + src/flamegraph/svg.rs | 17 ++- tests/data/flamegraph/austin/flame.svg | 12 +- .../flamegraph/colors/async-profiler-java.svg | 12 +- .../data/flamegraph/colors/deterministic.svg | 12 +- tests/data/flamegraph/colors/java.svg | 12 +- tests/data/flamegraph/colors/js.svg | 12 +- .../flamegraph/differential/diff-negated.svg | 12 +- tests/data/flamegraph/differential/diff.svg | 12 +- .../example-perf-stacks.svg | 12 +- tests/data/flamegraph/factor/factor-2.5.svg | 12 +- tests/data/flamegraph/flamechart/flame.svg | 12 +- .../fractional-reversed.svg | 12 +- .../flamegraph/grey-frames/grey-frames.svg | 12 +- tests/data/flamegraph/inverted/inverted.svg | 12 +- tests/data/flamegraph/nameattr/nameattr.svg | 12 +- .../nameattr_duplicate_attributes.svg | 12 +- .../narrow-blocks/narrow-blocks.svg | 12 +- .../flamegraph/options/colordiffusion.svg | 12 +- .../flamegraph/options/count_name_simple.svg | 12 +- .../options/count_name_with_symbols.svg | 12 +- tests/data/flamegraph/options/default.svg | 12 +- .../flamegraph/options/font_type_cursive.svg | 12 +- .../flamegraph/options/font_type_fantasy.svg | 12 +- .../options/font_type_monospace.svg | 12 +- .../options/font_type_sans-serif.svg | 12 +- .../flamegraph/options/font_type_serif.svg | 12 +- .../flamegraph/options/font_type_simple.svg | 12 +- .../options/font_type_with_quote.svg | 12 +- .../flamegraph/options/name_type_simple.svg | 12 +- .../options/name_type_with_backslash.svg | 12 +- .../options/name_type_with_quote.svg | 12 +- .../data/flamegraph/options/notes_simple.svg | 12 +- .../flamegraph/options/notes_with_symbols.svg | 12 +- .../data/flamegraph/options/search_color.svg | 12 +- .../data/flamegraph/options/stroke_color.svg | 12 +- .../flamegraph/options/subtitle_simple.svg | 12 +- .../options/subtitle_with_symbols.svg | 12 +- .../data/flamegraph/options/title_simple.svg | 12 +- .../flamegraph/options/title_with_symbols.svg | 12 +- .../flamegraph/options/truncate-right.svg | 12 +- .../data/flamegraph/options/uicolor_color.svg | 142 ++++++++++++++++++ .../palette-map/consistent-palette.svg | 12 +- ...tacks-01-collapsed-all-reversed-stacks.svg | 12 +- .../perf-vertx-stacks-01-collapsed-all.svg | 12 +- tests/flamegraph.rs | 12 ++ 50 files changed, 460 insertions(+), 289 deletions(-) create mode 100644 tests/data/flamegraph/options/uicolor_color.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index f9cbf569..7210d391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Add flag `--uicolor` to specify the color to draw UI element text, like the Reset view button. [#271](https://github.com/jonhoo/inferno/pull/271) + ### Changed - Updated `ahash` to version 0.8 - Updated `quick-xml` to version 0.26 +- Bumped `clap` to 3.2.0 + ### Removed ## [0.11.12] - 2022-10-24 diff --git a/Cargo.toml b/Cargo.toml index d0747d38..73eeaf03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ num-format = { version = "0.4.3", default-features = false } quick-xml = { version = "0.26", default-features = false } rgb = "0.8.13" str_stack = "0.1" -clap = { version = "3.0.1", optional = true, features = ["derive"] } +clap = { version = "3.2.1", optional = true, features = ["derive"] } once_cell = "1.12.0" [dev-dependencies] diff --git a/src/bin/flamegraph.rs b/src/bin/flamegraph.rs index de39e90d..1ab5ca13 100644 --- a/src/bin/flamegraph.rs +++ b/src/bin/flamegraph.rs @@ -2,7 +2,9 @@ use std::io; use std::path::{Path, PathBuf}; use env_logger::Env; -use inferno::flamegraph::color::{BackgroundColor, PaletteMap, SearchColor, StrokeColor}; +use inferno::flamegraph::color::{ + parse_hex_color, BackgroundColor, Color, PaletteMap, SearchColor, StrokeColor, +}; use inferno::flamegraph::{self, defaults, Direction, Options, Palette, TextTruncateDirection}; #[cfg(feature = "nameattr")] @@ -131,6 +133,18 @@ struct Opt { )] fontwidth: f64, + /// Color of UI text such as the search and reset zoom buttons + #[clap( + long = "uicolor", + default_value = defaults::UI_COLOR, + value_parser = |s: &str| { + parse_hex_color(s) + .ok_or_else(|| format!("Expected a color in hexadecimal format, got: {}", s)) + }, + value_name = "#RRGGBB" + )] + uicolor: Color, + /// Height of each frame #[clap( long = "height", @@ -264,6 +278,7 @@ impl<'a> Opt { options.factor = self.factor; options.search_color = self.search_color; options.stroke_color = self.stroke_color; + options.uicolor = self.uicolor; (self.infiles, options) } diff --git a/src/flamegraph/color/mod.rs b/src/flamegraph/color/mod.rs index 2cbaaecb..abcba7ac 100644 --- a/src/flamegraph/color/mod.rs +++ b/src/flamegraph/color/mod.rs @@ -141,7 +141,7 @@ impl FromStr for BackgroundColor { "blue" => Ok(BackgroundColor::Blue), "green" => Ok(BackgroundColor::Green), "grey" => Ok(BackgroundColor::Grey), - flat => parse_flat_bgcolor(flat) + flat => parse_hex_color(flat) .map(BackgroundColor::Flat) .ok_or_else(|| format!("unknown background color: {}", flat)), } @@ -154,7 +154,8 @@ macro_rules! u8_from_hex_iter { }; } -fn parse_flat_bgcolor(s: &str) -> Option { +/// Parses a string as a hex color, returning None if it is an invalid color +pub fn parse_hex_color(s: &str) -> Option { if !s.starts_with('#') || (s.len() != 7) { None } else { @@ -176,7 +177,7 @@ impl FromStr for SearchColor { type Err = String; fn from_str(s: &str) -> Result { - parse_flat_bgcolor(s) + parse_hex_color(s) .map(SearchColor) .ok_or_else(|| format!("unknown color: {}", s)) } @@ -204,7 +205,7 @@ impl FromStr for StrokeColor { if s == "none" { return Ok(StrokeColor::None); } - parse_flat_bgcolor(s) + parse_hex_color(s) .map(StrokeColor::Color) .ok_or_else(|| format!("unknown color: {}", s)) } @@ -466,36 +467,21 @@ pub(super) fn bgcolor_for<'a>( #[cfg(test)] mod tests { use super::namehash; - use super::parse_flat_bgcolor; + use super::parse_hex_color; use super::Color; use pretty_assertions::assert_eq; #[test] fn bgcolor_parse_test() { - assert_eq!( - parse_flat_bgcolor("#ffffff"), - Some(color!(0xff, 0xff, 0xff)) - ); - assert_eq!( - parse_flat_bgcolor("#000000"), - Some(color!(0x00, 0x00, 0x00)) - ); - assert_eq!( - parse_flat_bgcolor("#abcdef"), - Some(color!(0xab, 0xcd, 0xef)) - ); - assert_eq!( - parse_flat_bgcolor("#123456"), - Some(color!(0x12, 0x34, 0x56)) - ); - assert_eq!( - parse_flat_bgcolor("#789000"), - Some(color!(0x78, 0x90, 0x00)) - ); - assert_eq!(parse_flat_bgcolor("ffffff"), None); - assert_eq!(parse_flat_bgcolor("#fffffff"), None); - assert_eq!(parse_flat_bgcolor("#xfffff"), None); - assert_eq!(parse_flat_bgcolor("# fffff"), None); + assert_eq!(parse_hex_color("#ffffff"), Some(color!(0xff, 0xff, 0xff))); + assert_eq!(parse_hex_color("#000000"), Some(color!(0x00, 0x00, 0x00))); + assert_eq!(parse_hex_color("#abcdef"), Some(color!(0xab, 0xcd, 0xef))); + assert_eq!(parse_hex_color("#123456"), Some(color!(0x12, 0x34, 0x56))); + assert_eq!(parse_hex_color("#789000"), Some(color!(0x78, 0x90, 0x00))); + assert_eq!(parse_hex_color("ffffff"), None); + assert_eq!(parse_hex_color("#fffffff"), None); + assert_eq!(parse_hex_color("#xfffff"), None); + assert_eq!(parse_hex_color("# fffff"), None); } macro_rules! test_hash { diff --git a/src/flamegraph/mod.rs b/src/flamegraph/mod.rs index 991497b6..6edfe518 100644 --- a/src/flamegraph/mod.rs +++ b/src/flamegraph/mod.rs @@ -76,6 +76,7 @@ pub mod defaults { define! { COLORS: &str = "hot", SEARCH_COLOR: &str = "#e600e6", + UI_COLOR: &str = "#000000", STROKE_COLOR: &str = "none", TITLE: &str = "Flame Graph", CHART_TITLE: &str = "Flame Chart", @@ -102,6 +103,9 @@ pub struct Options<'a> { /// If `None`, the background color will be selected based on the value of `colors`. pub bgcolors: Option, + /// The color of UI text such as the search and reset view button. Defaults to black + pub uicolor: color::Color, + /// Choose names based on the hashes of function names. /// /// This will cause similar functions to be colored similarly. @@ -306,6 +310,7 @@ impl<'a> Default for Options<'a> { notes: Default::default(), subtitle: Default::default(), bgcolors: Default::default(), + uicolor: Default::default(), hash: Default::default(), deterministic: Default::default(), palette_map: Default::default(), @@ -511,10 +516,12 @@ where StrokeColor::Color(c) => Some(c.to_string()), StrokeColor::None => None, }; + let uicolor = opt.uicolor.to_string(); let style_options = StyleOptions { imageheight, bgcolor1, bgcolor2, + uicolor, strokecolor, }; diff --git a/src/flamegraph/svg.rs b/src/flamegraph/svg.rs index 4995b505..ae0ac95c 100644 --- a/src/flamegraph/svg.rs +++ b/src/flamegraph/svg.rs @@ -51,6 +51,7 @@ pub(super) struct StyleOptions<'a> { pub(super) imageheight: usize, pub(super) bgcolor1: Cow<'a, str>, pub(super) bgcolor2: Cow<'a, str>, + pub(super) uicolor: String, pub(super) strokecolor: Option, } @@ -121,7 +122,7 @@ where let titlesize = &opt.font_size + 5; svg.write_event(Event::Text(BytesText::from_escaped(&format!( " -text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} +text {{ font-family:{}; font-size:{}px }} #title {{ text-anchor:middle; font-size:{}px; }} ", font_type, &opt.font_size, titlesize, @@ -181,7 +182,7 @@ text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} x: Dimension::Percent(50.0), y: (opt.font_size * 2) as f64, text: (&*opt.title).into(), - extra: vec![("id", "title")], + extra: vec![("id", "title"), ("fill", &style_options.uicolor)], }, )?; @@ -212,7 +213,7 @@ text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} opt.ypad1() - opt.font_size } as f64, text: " ".into(), - extra: iter::once(("id", "details")), + extra: vec![("id", "details"), ("fill", &style_options.uicolor)], }, )?; @@ -223,7 +224,11 @@ text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} x: Dimension::Pixels(super::XPAD), y: (opt.font_size * 2) as f64, text: "Reset Zoom".into(), - extra: vec![("id", "unzoom"), ("class", "hide")], + extra: vec![ + ("id", "unzoom"), + ("class", "hide"), + ("fill", &style_options.uicolor), + ], }, )?; @@ -234,7 +239,7 @@ text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} x: Dimension::Pixels(image_width as usize - super::XPAD), y: (opt.font_size * 2) as f64, text: "Search".into(), - extra: vec![("id", "search")], + extra: vec![("id", "search"), ("fill", &style_options.uicolor)], }, )?; @@ -245,7 +250,7 @@ text {{ font-family:{}; font-size:{}px; fill:rgb(0,0,0); }} x: Dimension::Pixels(image_width as usize - super::XPAD), y: (style_options.imageheight - (opt.ypad2() / 2)) as f64, text: " ".into(), - extra: iter::once(("id", "matched")), + extra: vec![("id", "matched"), ("fill", &style_options.uicolor)], }, )?; diff --git a/tests/data/flamegraph/austin/flame.svg b/tests/data/flamegraph/austin/flame.svg index f3979ece..52290e5e 100644 --- a/tests/data/flamegraph/austin/flame.svg +++ b/tests/data/flamegraph/austin/flame.svg @@ -10,7 +10,7 @@ + + + Flame Graph + + Reset Zoom + Search + + + + _start (56 samples, 10.92%; 0.00%) + + _start + + + __libc_start_main (56 samples, 10.92%; 0.00%) + + __libc_start_main + + + main (56 samples, 10.92%; 0.00%) + + main + + + cksum (56 samples, 10.92%; +4.87%) + + cksum + + + cksum (5 samples, 0.97%; -0.78%) + + + + + __GI___fread_unlocked (3 samples, 0.58%; 0.00%) + + + + + _IO_file_xsgetn (3 samples, 0.58%; 0.00%) + + + + + _IO_file_read (3 samples, 0.58%; 0.00%) + + + + + entry_SYSCALL_64_fastpath (3 samples, 0.58%; 0.00%) + + + + + sys_read (3 samples, 0.58%; 0.00%) + + + + + vfs_read (3 samples, 0.58%; 0.00%) + + + + + __vfs_read (3 samples, 0.58%; 0.00%) + + + + + ext4_file_read_iter (3 samples, 0.58%; +0.39%) + + + + + cksum (96 samples, 18.71%; 0.00%) + + cksum + + + main (35 samples, 6.82%; 0.00%) + + main + + + cksum (35 samples, 6.82%; +3.12%) + + cksum + + + [unknown] (2 samples, 0.39%; 0.00%) + + + + + all (513 samples, 100%) + + + + + noploop (417 samples, 81.29%; 0.00%) + + noploop + + + main (415 samples, 80.90%; +27.49%) + + main + + + \ No newline at end of file diff --git a/tests/data/flamegraph/palette-map/consistent-palette.svg b/tests/data/flamegraph/palette-map/consistent-palette.svg index d1a7e7fa..950baab2 100644 --- a/tests/data/flamegraph/palette-map/consistent-palette.svg +++ b/tests/data/flamegraph/palette-map/consistent-palette.svg @@ -10,7 +10,7 @@