Skip to content

Commit

Permalink
feat: add Graphviz DOT report mode (#582) - WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiapple852 committed Nov 9, 2023
1 parent 1b459fd commit e20dcef
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum Mode {
Csv,
/// Generate a JSON report for N cycles.
Json,
/// Generate a Graphviz DOT file for N cycles.
Dot,
/// Do not generate any tracing output for N cycles.
Silent,
}
Expand Down Expand Up @@ -498,7 +500,7 @@ impl TryFrom<(Args, &Platform)> for TrippyConfig {
let dns_timeout = humantime::parse_duration(&dns_timeout)?;
let max_rounds = match mode {
Mode::Stream | Mode::Tui => None,
Mode::Pretty | Mode::Markdown | Mode::Csv | Mode::Json | Mode::Silent => {
Mode::Pretty | Mode::Markdown | Mode::Csv | Mode::Json | Mode::Dot | Mode::Silent => {
Some(report_cycles)
}
};
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ fn run_frontend(
Mode::Json => report::run_report_json(&traces[0], args.report_cycles, &resolver)?,
Mode::Pretty => report::run_report_table_pretty(&traces[0], args.report_cycles, &resolver)?,
Mode::Markdown => report::run_report_table_md(&traces[0], args.report_cycles, &resolver)?,
Mode::Dot => report::run_report_dot(&traces[0], args.report_cycles)?,
Mode::Silent => report::run_report_silent(&traces[0], args.report_cycles)?,
}
Ok(())
Expand Down
29 changes: 29 additions & 0 deletions src/report.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use crate::backend::flows::FlowEntry;
use crate::backend::trace::Trace;
use crate::TraceInfo;
use anyhow::anyhow;
use comfy_table::presets::{ASCII_MARKDOWN, UTF8_FULL};
use comfy_table::{ContentArrangement, Table};
use itertools::Itertools;
use parking_lot::RwLock;
use petgraph::dot::{Config, Dot};
use petgraph::graphmap::DiGraphMap;
use serde::{Serialize, Serializer};
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
use std::thread::sleep;
use std::time::Duration;
Expand Down Expand Up @@ -272,6 +276,31 @@ pub fn run_report_silent(info: &TraceInfo, report_cycles: usize) -> anyhow::Resu
Ok(())
}

/// Run a trace and generate a dot file.
pub fn run_report_dot(info: &TraceInfo, report_cycles: usize) -> anyhow::Result<()> {
wait_for_round(&info.data, report_cycles)?;
let trace = info.data.read().clone();
let mut graph: DiGraphMap<IpAddr, ()> = DiGraphMap::new();
for (flow, _id) in trace.flow_registry().flows() {
for (fst, snd) in flow.entries.windows(2).map(|pair| (pair[0], pair[1])) {
match (fst, snd) {
(FlowEntry::Known(addr1), FlowEntry::Known(addr2)) => {
graph.add_edge(addr1, addr2, ());
}
(FlowEntry::Known(addr1), FlowEntry::Unknown) => {
graph.add_edge(addr1, IpAddr::V4(Ipv4Addr::UNSPECIFIED), ());
}
(FlowEntry::Unknown, FlowEntry::Known(addr2)) => {
graph.add_edge(IpAddr::V4(Ipv4Addr::UNSPECIFIED), addr2, ());
}
_ => {}
}
}
}
println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
Ok(())
}

/// Block until trace data for round `round` is available.
fn wait_for_round(trace_data: &Arc<RwLock<Trace>>, report_cycles: usize) -> anyhow::Result<Trace> {
let mut trace = trace_data.read().clone();
Expand Down

0 comments on commit e20dcef

Please sign in to comment.