Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/target
/node_modules
/dist
.idea
pmu_config.json
.kiro/
1 change: 0 additions & 1 deletion src/analytics/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ mod cpu_utilization;
mod diskstats;
mod efa_stat;
mod ena_stat;
mod flamegraphs;
mod hotline;
mod interrupts;
mod java_profile;
Expand Down
21 changes: 0 additions & 21 deletions src/analytics/rules/flamegraphs.rs

This file was deleted.

26 changes: 2 additions & 24 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub mod cpu_utilization;
pub mod diskstats;
pub mod efa_stat;
pub mod ena_stat;
pub mod flamegraphs;
pub mod hotline;
pub mod interrupts;
pub mod java_profile;
Expand Down Expand Up @@ -33,7 +32,6 @@ use cpu_utilization::{CpuUtilization, CpuUtilizationRaw};
use diskstats::{Diskstats, DiskstatsRaw};
use efa_stat::{EfaStat, EfaStatRaw};
use ena_stat::{EnaStat, EnaStatRaw};
use flamegraphs::{Flamegraph, FlamegraphRaw};
use hotline::{Hotline, HotlineRaw};
use include_directory::{include_directory, Dir};
use interrupts::{InterruptData, InterruptDataRaw};
Expand All @@ -43,7 +41,7 @@ use memalloc::{MemallocData, MemallocDataRaw};
use meminfo::{MeminfoData, MeminfoDataRaw};
use netstat::{Netstat, NetstatRaw};
use numastat::{Numastat, NumastatRaw};
use perf_profile::{PerfProfile, PerfProfileRaw};
use perf_profile::{FlamegraphRaw, PerfProfile, PerfProfileRaw};
use perf_stat::{PerfStat, PerfStatRaw};
use processes::{Processes, ProcessesRaw};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -194,11 +192,6 @@ impl DataType {
self.data.finish_data_collection(&self.collector_params)?;
Ok(())
}

pub fn after_data_collection(&mut self) -> Result<()> {
self.data.after_data_collection(&self.collector_params)?;
Ok(())
}
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash)]
Expand Down Expand Up @@ -292,15 +285,6 @@ macro_rules! data {
}
Ok(())
}

fn after_data_collection(&mut self, params: &CollectorParams) -> Result<()> {
match self {
$(
Data::$data(ref mut value) => value.after_data_collection(params)?,
)*
}
Ok(())
}
}

#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -414,7 +398,7 @@ data!(
NetstatRaw,
NumastatRaw,
PerfProfileRaw,
FlamegraphRaw,
FlamegraphRaw, // Dummy one to maintain the order
JavaProfileRaw,
HotlineRaw,
MemallocDataRaw,
Expand All @@ -437,7 +421,6 @@ report_data!(
Numastat,
PerfProfile,
Hotline,
Flamegraph,
AperfStat,
AperfRunlog,
JavaProfile,
Expand All @@ -463,11 +446,6 @@ pub trait CollectData {
Ok(())
}

fn after_data_collection(&mut self, _params: &CollectorParams) -> Result<()> {
noop!();
Ok(())
}

fn is_static() -> bool {
false
}
Expand Down
57 changes: 54 additions & 3 deletions src/data/common/data_formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum DataFormat {
Text,
KeyValue,
Profile,
Graph,
Unknown,
}

Expand Down Expand Up @@ -46,6 +47,7 @@ pub enum AperfData {
Text(TextData),
KeyValue(KeyValueData),
Profile(ProfilingData),
Graph(GraphData),
}

impl AperfData {
Expand All @@ -55,6 +57,7 @@ impl AperfData {
AperfData::Text(_) => DataFormat::Text,
AperfData::KeyValue(_) => DataFormat::KeyValue,
AperfData::Profile(_) => DataFormat::Profile,
AperfData::Graph(_) => DataFormat::Graph,
}
}
}
Expand Down Expand Up @@ -163,16 +166,64 @@ pub struct TextData {
pub lines: Vec<String>,
}

// ------------------------------------------ GRAPH DATA -------------------------------------------
/// TODO: Temporary format only used by hotline to ship pre-rendered HTML/SVG tables to the frontend.
///
/// Data types falling into this format produce one or more HTML or SVG files at the end of a
/// recording run, which are to be rendered through IFrame in the report. The graphs can be
/// categorized into different groups, so that only one group of graphs are shown in the report
/// at a time.
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GraphData {
pub graph_groups: Vec<GraphGroup>,
}

/// Contents of a graph group, which contains all graphs to be displayed together.
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct GraphGroup {
/// Name of the graph group.
pub group_name: String,
/// A map from graph names to all graphs within the group.
pub graphs: HashMap<String, Graph>,
}

impl GraphGroup {
pub fn new(graph_group_name: &str) -> Self {
GraphGroup {
group_name: graph_group_name.to_string(),
graphs: HashMap::new(),
}
}
}

/// Information about a graph.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Graph {
/// The name of the graph.
pub graph_name: String,
/// The relative path to graph (value of the IFrame's src attribute).
pub graph_path: String,
/// The size of the graph, which can be used for graph ordering in the report.
pub graph_size: Option<u64>,
}

impl Graph {
pub fn new(graph_name: String, graph_path: String, graph_size: Option<u64>) -> Self {
Graph {
graph_name,
graph_path,
graph_size,
}
}
}

// ---------------------------------------- PROFILING DATA ------------------------------------------
/// Data types falling into this format collect profiling data from one or more profiled
/// targets (e.g. JVMs for java profiling, and system for perf profiling). Each target is
/// represented by a [`Profiler`] holding metadata and a map of [`Profile`]s keyed by profiling
/// type (e.g. "cpu", "wall", "allocation"). Each [`Profile`] carries:
/// - Time bucketed sample data with total counts for the entire profile
/// - Calling context tree used to analyze a selected time range
/// - A [`ProfileGraph`](crate::profiling::ProfileGraph) pointing to a pre-rendered HTML/SVG
/// file displayed via IFrame in the report (legacy path, to be removed once native
/// rendering is complete).
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ProfilingData {
/// Map from profiler name to its profiler data
Expand Down
1 change: 1 addition & 0 deletions src/data/common/processed_data_accessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl ProcessedDataAccessor {
DataFormat::KeyValue => self.key_value_data_json_string(processed_data),
DataFormat::Text => self.text_data_json_string(processed_data),
DataFormat::Profile => self.profiler_data_json_string(processed_data),
DataFormat::Graph => serde_json::to_string(processed_data).unwrap(),
DataFormat::Unknown => serde_json::to_string(processed_data).unwrap(),
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/data/common/utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use anyhow::{Error, Result};
use log::error;
use std::collections::{HashMap, HashSet, VecDeque};
use std::fs;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

use crate::data::common::data_formats::{Graph, GraphData};

pub fn get_data_name_from_type<T>() -> &'static str {
let full_data_module_path = std::any::type_name::<T>();

Expand Down Expand Up @@ -79,6 +82,43 @@ pub fn no_tar_gz_file_name(path: &PathBuf) -> Option<String> {
Some(file_name_str)
}

/// Copy a graph file to the report data dir and update the GraphData with its info.
pub fn copy_graph_and_update_graph_data(
source_dir: &PathBuf,
dest_dir: &PathBuf,
filename: &str,
graph_group_name: &str,
graph_key: &str,
graph_name: String,
graph_data: &mut GraphData,
) {
let source_graph_path = source_dir.join(&filename);
if !source_graph_path.exists() {
return;
}
let relative_graph_path = PathBuf::from("data").join("js").join(&filename);
let dest_graph_path = dest_dir.join(&relative_graph_path);

if let Err(e) = std::fs::copy(&source_graph_path, &dest_graph_path) {
error!("Failed to copy graph file: {e}");
} else {
graph_data
.graph_groups
.iter_mut()
.find(|graph_group| graph_group.group_name == graph_group_name)
.map(|graph_group| {
graph_group.graphs.insert(
graph_key.to_string(),
Graph {
graph_name,
graph_path: relative_graph_path.to_string_lossy().into_owned(),
graph_size: None,
},
);
});
}
}

/// Collects the paths of all files in a dir and returns a map from file names to file paths,
/// if the file system read was successful
pub fn collect_file_paths_in_dir(dir: &PathBuf) -> Result<HashMap<String, PathBuf>> {
Expand Down
Loading
Loading