use std::collections::BTreeMap;
use flowscope::extract::FiveTuple;
use flowscope::pcap::PcapFlowSource;
use flowscope::reassembler::BufferedReassemblerFactory;
use flowscope::{FlowDriver, Timestamp};
use metrics_util::MetricKind;
use metrics_util::debugging::{DebugValue, DebuggingRecorder};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = std::env::args()
.nth(1)
.unwrap_or_else(|| "tests/data/mixed_short.pcap".to_string());
let recorder = DebuggingRecorder::new();
let snapshotter = recorder.snapshotter();
recorder.install()?;
let mut driver = FlowDriver::new(
FiveTuple::bidirectional(),
BufferedReassemblerFactory::default(),
)
.with_emit_anomalies(true);
let mut last_ts = Timestamp { sec: 0, nsec: 0 };
for view in PcapFlowSource::open(&path)?.views() {
let view = view?;
last_ts = view.timestamp;
let _ = driver.track(&view);
}
let _ = driver.sweep(last_ts);
let snap = snapshotter.snapshot().into_vec();
let mut by_name: BTreeMap<String, (MetricKind, Vec<(String, String)>)> = BTreeMap::new();
for (key, _unit, _desc, value) in &snap {
let name = key.key().name().to_string();
let kind = key.kind();
let labels: Vec<String> = key
.key()
.labels()
.map(|l| format!("{}=\"{}\"", l.key(), l.value()))
.collect();
let labels_part = if labels.is_empty() {
String::new()
} else {
format!("{{{}}}", labels.join(","))
};
let value_str = match value {
DebugValue::Counter(n) => n.to_string(),
DebugValue::Gauge(g) => format!("{}", g.into_inner()),
DebugValue::Histogram(hs) => {
let total = hs.iter().map(|v| v.into_inner()).sum::<f64>();
let n = hs.len() as f64;
format!("{}", if n > 0.0 { total / n } else { 0.0 })
}
};
let entry = by_name.entry(name).or_insert_with(|| (kind, Vec::new()));
entry.1.push((labels_part, value_str));
}
for (name, (kind, mut samples)) in by_name {
let kind_str = match kind {
MetricKind::Counter => "counter",
MetricKind::Gauge => "gauge",
MetricKind::Histogram => "summary",
};
println!("# TYPE {name} {kind_str}");
samples.sort();
for (labels, value) in samples {
println!("{name}{labels} {value}");
}
}
Ok(())
}